⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfar.c

📁 OXCC is a multipass, interpreting C compiler with several language extensions. It generates an Archi
💻 C
📖 第 1 页 / 共 3 页
字号:
/* cfar.c */
/* Import .o and .a (a.out format) files into a cff archive */
/* Version 2 now incorporates FILE mode, absorbing 'cfin' and 'cfdel' */
/* Copyright 1993, 1995 Norman D. Culver, All Rights Reserved */

/* compile: gcc -o -O2 -DSKELETON cfar.c */

typedef unsigned long size_t;

#include "oxbow.h"

extern void (*BUGPRINTF)(char *fmt, ...);

extern long atol(const char *);
extern int strlen(const char *);
extern void *strcpy(char *, const char *);
extern int _strcpy(char *, char *);
extern void memclr(char *, long);
extern int strlwr(char *);
extern void *strrchr(const char *, char);
extern void *strstr(const char *, const char *);
static void setup_origin(unsigned long, int);
extern void oxlink_close_libs(void);

/* Program version */
static Item prgversion = (Item)2;
/* Archive version */
static Item arversion;

/* Maximum library types */
#define MAXLIBTYPE 16

typedef struct {
	unsigned long sn;
	unsigned long libnum : 12;	/* capacity for 4096 libraries per libtype */
	unsigned long libtype : 4;	/* capacity for 16 library types */
	unsigned long unused : 12;
	unsigned long tag : 4;
} SymItem;

typedef struct {
	unsigned long filetime;
	unsigned long sn : 28;
	unsigned long tag : 4;
} OrgItem;

/* Action bitmap */
static int act;
#define arADD (1)
#define arREPLACE (2)
#define arDELETE (4)
#define arEXTRACT (8)
#define arCHECK (16)
#define arUPDATE (32)

static int verbose;			/* if 1, verbose mode */
static long libtype;	/* 0 = modules, 1 = classes */
static long oldlibtype = -1;
static long libnum;		/* library number into which files are stored */
static long oldlibnum = -1;
static int map;			/* if 1, print archive map */
static int map_bitmaps;	/* if 1, and map, print bitmaps */
static int map_entries; /* if 1, and map, print entries */
static int freshen;		/* if 1, freshen entries */
static int shrink;		/* if 1, shrink archive */
static int issymbol;	/* if 1, file names are really symbol names */
static int batfile;		/* if 1, print a batchfile to remake archive */
static void *archive;	/* handle of the open archive */
static void *msyms;		/* handle of the master symbol table */
static void *fipaths;	/* handle of the internal filemode path table */
static void *ipaths;	/* handle of the internal path table */
static void *qipaths;
static void *origins;	/* handle of the origin path table */
static void *qorigins;
static void *lib;			/* handle of the current internal library */
static void *plib;			/* handle of the library parent directory */
static char curlib[1024];		/* internal path to the current library */
static int curliblen;
static char curobj[1024];	/* internal path to the current file */
static int curobjlen;
static char *cur_orgpath;	/* current origin path as given by cfpathtrn */
static int cur_orgtype;		/* current origin type as given by cfpathtrn */
static OrgItem cur_org;		/* current origin time and serial num */
static char ltypes[MAXLIBTYPE];
static char lnums[4096];
static int delete;
static int replace;
static int add;

static unsigned long
new_sn(char *name)
{
Item sn;
int namlen = strlen(name);
	if(cffind(archive, name, namlen, &sn) >= FOUND)
	{
		++sn.a0;
		cfreinsert(archive, name, namlen, &sn);
		return sn.a0;
	}
	return 0;
}

/* ++++++++++++++++++++++++++++ DLLMODE ++++++++++++++++++++++++++++++++ */
static int dllmode;

static void
proc_dllmode(char *dllpath)
{
char buf[256];
char symbol[256];
char dllname[256];
char dlldef[256];
int ordinal, argcnt, symlen, match, deflen;
int filesize, filesize1;
long dupnum;
SymItem symval, saveval;
char *filename;
cfFILE *df;
CFSTAT sbuf;
void *xx, *xx1, *yy;
int dlltype, dll_sn;
char *cp;

	filename = strrchr(dllpath, '/');
	if(filename)
		++filename;
	else filename = dllpath;

	deflen = _strcpy(dlldef, filename);
	if(strstr(dlldef, ".w32"))
		dlltype = 1<<4;
	else if(strstr(dlldef, ".os2"))
		dlltype = 2<<4;
	else if(strstr(dlldef, ".lnx"))
		dlltype = 3<<4;
	else if(strstr(dlldef, ".w16"))
		dlltype = 4<<4;
	else if(strstr(dlldef, ".os1"))
		dlltype = 5<<4;
	else
		dlltype = 0;

	strcpy(curlib, "ltype3");
	plib = cfsubopen(archive, curlib, F_RDWR|F_CREAT, NULL);
	xx = cfsubopen(plib, dlldef, F_RDONLY, NULL);
	if(!xx && delete)
	{
		cfprintf("cfar: %s does not exist\n", filename);
		return;
	}
	if(xx && !(replace || delete))
	{
		cfclose(xx);
		cfprintf("cfar: %s exists and replace not enabled\n", dlldef);
		return;	
	}
	if(add || replace)
	{
		if(!(xx1 = cfopen(dllpath, F_RDONLY, NULL)))
		{
			cfclose(xx);
			cfprintf("cfar: cannot open %s\n", dllpath);
			return;
		}
		cfstat(xx1, &sbuf);
		setup_origin(sbuf.st_mtime, 1);
	}
	symbol[0] = '_';	/* add leading underscore to symbols */
	if(xx && (replace || delete))
	{/* DELETE ALL OF THE OLD SYMBOLS */
		saveval.sn = 0;

		/* get an in-memory uncompressed copy */
		yy = cfsubopen(MEMTEMP, "", F_TEMPFILE, NULL);
		filesize = cfunzip(yy,0,xx,0);
		cfclose(xx);

		/* convert the memory file to a stream FILE */
		cfseek(yy, 0, S_SET);
		df = cffdopen(yy, "rt");
		while(cffgets(buf, sizeof(buf)-1, df))
		{
		  if( buf[0] == '#' || !isalnum(buf[0]) )
			continue;
		  if(buf[0] == 'U' && strstr(buf, "UNHANDLED "))
			break;
		  if(isdigit(buf[0]))
		  {
			if(!strstr(buf, "ERROR:"))
			{
			  /* the symbol is stored as oooo sssssssss cccc\n */
			  cfsscanf(buf, "%d %s %d", &ordinal, &symbol[1], &argcnt);

			  /* Delete the symbol from msyms */
			  symlen = strlen(symbol);
			  dupnum = 0;
			  for(;;)
			  {
			  int	result = cffind_dupnum(msyms, symbol, symlen, &symval, &dupnum);

			    if(result >= FOUND)
			    {
				  symval.unused = 0;
				  match = 0;
				  if(saveval.sn)
				  {
					if(symval.sn == saveval.sn && symval.libtype == 3)
					{
						match = 1;
					}
				  }
				  else
				  {/* first */
				    if(symval.libtype == 3)
				    {/* check if the dll names match */
				    int snum = symval.libnum;
				 	  symval.libnum = 0;

					  if(cfget(qipaths, &symval, 8, buf, 256) >= FOUND)
					  {
						if(!strcmp(buf, dllname))
						{
							symval.libnum = snum;
							saveval = symval;
							match = 1;
						 }
					   }
					  }/* END: symval.libtype == 3 */
				  }/* END: first */
				  if(match)
				  {
					if(cfdelete_dupnum(msyms, symbol, symlen, dupnum) != OK)
					  cfprintf("cfar: ERROR can't delete %s dumpnum=%d\n",
							symbol, dupnum);
					break;
				  }
				  ++dupnum;
			    }/* END: result >= FOUND */
			    else break;
			  }/* END: for(;;) */
			}/* END: !strstr(ERROR) */
		  }/* END: isdigit(buf[0]) */
		  else if((cp = strstr(buf, ".dll")))
		  {/* new dll encountered */
			cp[4]=0;
			if(saveval.sn)
			{/* delete previous dll name from qipath */
			int u = saveval.unused;
			int n = saveval.libnum;
				saveval.unused = 0;
				saveval.libnum = 0;
				cfdelete(qipaths, &saveval, 8);
				saveval.unused = u;
				saveval.libnum = n;
			}
			strcpy(dllname, buf);
			saveval.sn = 0;
			if(verbose)
				cfprintf("delete %s\n", dllname);
			continue;
		  }/* END: new dll encountered */			
		}/* END: while(cffgets()) */

		/* delete last dllname from qipaths */
		if(saveval.sn)
		{
			saveval.unused = 0;
			saveval.libnum = 0;
			cfdelete(qipaths, &saveval, 8);
		}
		cffclose(df); /* auto delete of tempfile yy */

		/* Delete the internal copy of dlldef */
		cfdelete(plib, dlldef, deflen);
		/* Delete the origin linkage */
		strcat(dlldef, ".org");
		cfdelete(plib, dlldef, deflen+4);
		dlldef[deflen] = 0;
	}/* END: DELETE OLD SYMBOLS */

	if(add || replace)
	{/* INSERT NEW SYMBOLS */

		/* get the compressed file size */
		filesize = cfzip(0,0,xx1,0);

		/* create a chunk to hold the compressed file */
		xx = cfmake_chunk(plib, dlldef, deflen, filesize);
		if(!xx)
		{
			cfprintf("cfar: cannot create internal file %s\n", filename);
			cfclose(xx1);
			return;
		}
#if 1
		/* compress the external file into the internal chunk */
		cfseek(xx1, 0, S_SET);
		if((filesize1 = cfzip(xx,0,xx1,0)) != filesize)
		  cfprintf("cfar: ERROR ziperr fs1=%d fs=%d\n", filesize1, filesize);
#else
		/* copy the external file into the internal chunk */
		cfseek(xx1, 0, S_SET);
		if(cfcopy_file(xx, xx1) != sbuf.st_filesize)
		{
			cfprintf("cfar: ERROR copying %s\n", filename);
			cfclose(xx);
			cfclose(xx1);
			return;
		}
#endif
		cfclose(xx);	/* close the internal dlldef file chunk */

		/* Process the external dlldef file */
		cfseek(xx1, 0, S_SET);
		df = cffdopen(xx1, "rt");
		while(cffgets(buf, sizeof(buf)-1, df))
		{
			if( buf[0] == '#' || !isalnum(buf[0]) )
				continue;
			if((buf[0] == 'U') && strstr(buf, "UNHANDLED "))
				break;
			if(isdigit(buf[0]))
			{
			  if(!strstr(buf, "ERROR:"))
			  {
			   /* the symbol is stored as oooo sssssssss cccc\n */
			   cfsscanf(buf, "%d %s %d", &ordinal, &symbol[1], &argcnt);

			   /* INSERT THE SYMBOL IN MSYMS, symval links to dllname */
			   symlen = strlen(symbol);
			   symval.sn = dll_sn;
			   symval.libtype = 3;
			   symval.unused = ordinal;
			   symval.libnum = (argcnt&15) | dlltype;
			   cfinsert_dupnum(msyms, symbol, symlen, &symval, NULL);
			   if(verbose)
			   	cfprintf("ord:%d argcnt:%d %s\n", ordinal, argcnt, symbol);
			 }
			}
			else if((cp = strstr(buf, ".dll")))
			{/* new dll encountered */
			  cp[4]=0;
			  strcpy(dllname, buf);
			  /* insert in qipaths */
			  dll_sn = new_sn("SN0");
			  symval.sn = dll_sn;
			  symval.libtype = 3;
			  symval.unused = 0;
			  symval.libnum = 0;
			  symval.tag = STO_VALUE;
			  if(verbose)
			  	cfprintf("%s\n", dllname);
			  if(!cfput(qipaths, &symval, 8, dllname, strlen(dllname)+1,NULL))
				cfprintf("cfar: ERROR put dllname `%s' failed\n", dllname);
			}			
		}/* END: while(cffgets()) */

		cffclose(df);

		/* save the backlink to the origin */
		strcat(dlldef, ".org");
		cfinsert(plib, dlldef, deflen+4, &cur_org);

	}/* END: INSERT NEW SYMBOLS */
}/* proc_dllmode() */

/* +++++++++++++++++++++++++++++ FILEMODE ++++++++++++++++++++++++++++++ */
static int filemode;
static int chunk;
static int newname;
static void *subdir;
static char *midpart;
static char *lastpart;
static char basefile[256];
static char midpath[1024];
static char innerpath[1024];

static void
proc_filemode(char *filepath)
{
void *fit;
void *h = (subdir) ? subdir : archive;
void *fd;
char *filename;
char *cfname;
Item item;
CFSTAT sbuf;
int cfnamlen;
int filesize;
char *tag;
int exists = 0;

	filename = strrchr(filepath, '/');
	if(filename)
		++filename;
	else filename = filepath;

	if(newname)
		cfname = lastpart;
	else
		cfname = filename;

	cfnamlen = strlen(cfname);

	if((fit = cfopen(filepath, F_RDONLY, NULL)) != NULL)
	{
		/* check for existance of the archive item */
		if(cfsubstat(h, cfname, &sbuf) == OK)
		{
		  if(!replace)
		  {
			cfclose(fit);
			cfprintf("cfar: %s exists and replace not enabled\n", cfname);
			return;
		  }
		  exists = 1;
		  cfunlink(h, cfname);
		}
		cfstat(fit, &sbuf);
		filesize = sbuf.st_filesize;
		setup_origin(sbuf.st_mtime, 1);

		if(verbose || act == arUPDATE)
		{
			if(act == arUPDATE)
				 cfprintf("updating %s\n", cfname);
			else cfprintf("%s\n", cfname);
		}
		if(chunk)
		{
			if(!(fd = cfmake_chunk(h, cfname, cfnamlen, filesize)))
			{
				cfprintf("cfar: cannot make chunk for %s\n", cfname);
				cfclose(fit);
				return;
			} 
		}
		else
		{
			if(!(fd = cfsubopen(h, cfname, F_RDWR|F_CREAT|F_FILEONLY, NULL)))
			{
				cfprintf("cfar: could not create file %s\n", cfname);
				cfclose(fit);
				return;
			}
		}

		if(cfcopy_file(fd, fit) != filesize)
			cfprintf("cfar: ERROR copying %s\n", cfname);

		cfclose(fd);
		cfclose(fit);

		/* Store the backlink to the origin, time + origin serial number */
		if(newname)
			tag = "?";
		else
			tag = " ";
		
		curobjlen = cfsprintf(curobj, "%s/%s%s", innerpath, cfname, tag);
		if(exists || act == arUPDATE)
		{
			cfreinsert(fipaths, curobj, curobjlen, &cur_org);
		}
		else
		{
			cfinsert(fipaths, curobj, curobjlen, &cur_org);
		}
	}
	else
	{
		cfprintf("cfar: input file %s not found\n", filepath);
	}
}
static void *
create_middle(char *path, void *basehandle)
{
char *cp;

	cp = path;
	while((cp = (char*)strchr(cp, '/')) != NULL)
	{
	void *subhandle;
		*cp = '\0';		
		subhandle = cfsubopen(basehandle, path, F_RDWR|F_CREAT, NULL);
		cfclose(subhandle);
		*cp = '/';
		++cp;
	} 
	return cfsubopen(basehandle, path, F_RDWR|F_CREAT, NULL);
}
static void *
open_middle(void *basehandle)
{
void *subhandle = NULL;

	if(newname)
	{
	  if(midpart)
	  {
		subhandle = cfsubopen(basehandle, midpath, F_RDWR|F_CREAT, NULL);
		if(subhandle == NULL)
		{/* create the path in pieces */
			subhandle = create_middle(midpath, basehandle);
		}
	  }
	}
	else /* not newname */
	{
	  if(innerpath[0])
	  {
		subhandle = cfsubopen(basehandle, &innerpath[1], F_RDWR|F_CREAT, NULL);
		if(subhandle == NULL)
		{/* create the path in pieces */
			subhandle = create_middle(&innerpath[1], basehandle);
		}
	  }
	}
#if 0
	if(subhandle)
		cfsetverylazy(subhandle);
#endif
	return subhandle;
}
static void
del_entry()
{
CFSTAT sbuf;
char forgpath[1024];

	if(innerpath[0])
	{
		if(verbose)	
			cfprintf("%s\n", lastpart);

		if(cfunlink(archive, innerpath) != OK)
		{
			cfprintf("cfar: delete failed for `%s'\n", innerpath);
		}
		else
		{
			cfsprintf(forgpath, "/fipaths%s ", innerpath);
			if(cfunlink(archive, forgpath) != OK)
			{
				cfsprintf(forgpath, "/fipath/%s?", innerpath);
				if(cfunlink(archive, forgpath) != OK)
					cfprintf("cfar: delerror, fipath:%s\n", forgpath);
			}
		}
	}
	else
	{
		cfprintf("cfar: delete, path missing\n");
	}
}
static void
out_entry()
{
void *in, *of;

	if(innerpath[0])
	{
	  if((in = cfsubopen(archive, innerpath, F_RDONLY, NULL)) == NULL)
	  {
		cfprintf("cfar: extract, `%s' does not exist\n", innerpath);
		return;
	  }
	  if((of = cfopen(lastpart, F_RDWR|F_CREAT, NULL)) == NULL)
	  {
	  	cfprintf("cfar: extract, cannot create output file `%s'\n", lastpart);
		cfclose(in);
	  }
	  if(verbose)
	  	cfprintf("%s\n", lastpart);
	  cfcopy_file(of, in);
	  cfclose(in);
	  cfclose(of);
	}
	else
	{
		cfprintf("cfar: extract, path missing\n");
	}
}
/* ====================== END FILEMODE =================================== */
static int
open_curlib()
{
	if(lib)
	{/* library is already open */
		if(libtype == oldlibtype && libnum == oldlibnum)
			return 1;

		cfclose(lib);
		if(oldlibtype != libtype)
		{
			cfclose(plib);
			cfsprintf(curlib, "ltype%d", libtype);
			plib = cfsubopen(archive, curlib, F_RDWR|F_CREAT, NULL);
		}
		oldlibtype = libtype;
		oldlibnum = libnum;
	}
	if(oldlibtype != libtype) {
		cfsprintf(curlib, "ltype%d", libtype);
		plib = cfsubopen(archive, curlib, F_RDWR|F_CREAT, NULL);
	}
	curliblen = cfsprintf(curlib, "ltype%d/lib%d", libtype, libnum);
	lib = cfsubopen(archive, curlib, F_RDWR|F_CREAT|F_SORTED, NULL);
	if(!lib)
	{
		cfprintf("cfar: can't open library %s\n", curlib);
		return 0;
	}
#if 0
	cfsetverylazy(lib);
	cfsetverylazy(plib);
#endif
	return 1;
}
static void *
make_scratch()
{
	return cfsubopen(MEMTEMP, "", F_TEMPFILE|F_BITMAP, NULL);
}
static void
get_libtypes(char *name)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -