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

📄 cfar.c

📁 OXCC is a multipass, interpreting C compiler with several language extensions. It generates an Archi
💻 C
📖 第 1 页 / 共 3 页
字号:
void *dirh;
CFDIRENT *d;
	memclr(ltypes, MAXLIBTYPE);
	dirh = cfopendir(name);
	while((d = cfreaddir(dirh)) != NULL) {
		if(		d->d_name[0] == 'l'
			&&	d->d_name[1] == 't')
		{
		long x = atol(&d->d_name[5]);
			ltypes[x] = 1;
		}
	}
	cfclosedir(dirh);
}
static void
get_libnums(char *name)
{
void *dirh;
CFDIRENT *d;
	memclr(lnums, 4096);		
	dirh = cfopendir(name);
	while((d = cfreaddir(dirh)) != NULL)
	{
		if(		d->d_name[0] == 'l'
			&&	d->d_name[1] == 'i')
		{
		long x = atol(&d->d_name[3]);
			lnums[x] = 1;
		}
	}
	cfclosedir(dirh);
}
static char *
fileof(char *path)
{
int len = strlen(path);
char *cp = &path[len-1];
char *cp1;
	while(cp != path)
	{
		if(*cp == '/' || *cp == '\\' || *cp == ':') {
			++cp;
			break;
		}
		--cp;
	}
	len = strlen(cp);
	cp1 = malloc(len+1);
	strcpy(cp1, cp);
	return cp1;
}
static char *
objof(char *name)
{
	if(issymbol) {
	long dupnum = 0;
	SymItem symval;
	int symlen = strlen(name);
		for(;;)
		{
		int	result = cffind_dupnum(msyms, name, symlen, &symval, &dupnum);

			if(result >= FOUND)
			{
				if(		(act == arCHECK)
					||	(	symval.libtype == libtype
						 &&	symval.libnum == libnum))
				{
				char curpath[256];
					if(cfget(qipaths, &symval, 8, curpath, 256) >= FOUND) {
					  if(act == arCHECK)
						cfprintf("symbol %s is defined in %s\n", name, curpath);
					  else return fileof(curpath);
					}
				}
				++dupnum;
			}
			else return NULL;
		}
	}
	else return fileof(name);
}
static void
delete_file(char *name, int internal)
{
char *objname = objof(name);
int objlen;
Item packval;
SymItem symval;
char cpath[256];
int cpathlen;
Item objloc;

	if(!objname)
		return;

	cpathlen = cfsprintf(cpath, "%s/%s", curlib, objname);

	/* Delete the data chunk */

	objlen = strlen(objname);
	if(cffind(lib, objname, objlen, &objloc) < FOUND) {
		if(!internal)
			cfprintf("cfar: %s not found\n", cpath);
		return;
	}
	if(verbose && !internal)
		cfprintf("%s\n", objname);

	cfdelete(lib, objname, objlen);

	/* Read the quick access symbol pack and delete the symbols */
	objname[objlen-1] = 'x';
	if(cffind(lib, objname, objlen, &packval) >= FOUND)
	{
	char *cp, *sp, symlen;
		cp = cflocalize(lib, &packval);
		for(sp = cp; *sp ; sp += symlen+1)
		{
		long dupnum = 0;
			symlen = strlen(sp);			
			for(;;)
			{
			int	result = cffind_dupnum(msyms, sp, symlen, &symval, &dupnum);
				if(result >= FOUND)
				{
					if(		symval.libtype == libtype
						&&	symval.libnum == libnum)
					{
						cfdelete_dupnum(msyms, sp, symlen, dupnum);
						break;
					}
					++dupnum;
				}
				else break;
			}
		}
		cfrelease(cp, R_CLEAN);
		/* Delete the symbol pack */
		cfdelete(lib, objname, objlen);
		/* Delete the origin linkage */
		objname[objlen-1] = 't';
		cfdelete(lib, objname, objlen);
	}
	/* Delete the path info */
	cfdelete(ipaths, cpath, cpathlen);
	cfdelete(qipaths, &symval, 8);
	free(objname);
}
static void
extract_file(char *name)
{
char *objname = objof(name);
int objlen;
Item objloc;

	if(!objname)
		return;

	objlen = strlen(objname);
	if(cffind(lib, objname, objlen, &objloc) == FOUND)
	{
	void *hobj;
	void *fd;

		if((hobj = cfopen_chunk(lib, &objloc)) != NULL)
		{
			if((fd = cfopen(objname, F_RDWR|F_CREAT, NULL)) != NULL)
			{
				cfcopy_file(fd, hobj);
				cfclose(fd);
				if(verbose)
					cfprintf("%s\n", objname);
			}
			cfclose(hobj);
		}
	}
	free(objname);
}
static void
setup_origin(unsigned long filetime, int flag)
{
int orglen;
char *cp;
Item orgsn;

	cur_org.filetime = filetime;
	cur_org.tag = STO_VALUE;
	cp = &cur_orgpath[strlen(cur_orgpath)-1];

	if(!flag && (*cp != 'a' || cp[-1] != '.'))
	{/* origin is not a library */
		cp = strrchr(cur_orgpath, '/');
		*cp = 0;
	}
	if(flag && !newname)
	{
		cp = strrchr(cur_orgpath, '/');
		*cp = 0;
	}
	/* Check if the origin is in the system */
	orglen = strlen(cur_orgpath);
	if(cffind(origins, cur_orgpath, orglen, &orgsn) >= FOUND)
	{/* It is in the system, get the serial number */
		cur_org.sn = orgsn.a0;
	}
	else
	{/* Enter this origin into the system */
		orgsn.item = new_sn("SN1");
		orgsn.a2.type = STO_VALUE;
		cur_org.sn = orgsn.a0;

		/* Store the origin, indexed both ways */
		cfinsert(origins, cur_orgpath, orglen, &orgsn);
		cfput(qorigins, &orgsn, 4, cur_orgpath, orglen+1, NULL);
	}
	if(*cp == 0) *cp = '/';
}
static void
insert_file(char *path)
{
void *desc;

	/* Open the input file */
	if((desc = cfopen(path, F_RDONLY, NULL)) != NULL)
	{
	int numobjs;
	int i, j;
	char *objname;
	char *sympack;
	int packx;
	void *scratch;
	CFSTAT s;

		cfstat(desc, &s);
		setup_origin(s.st_mtime, 0);

		/* Create a scratch object in memory */
		scratch = make_scratch();

		/* Take a look at the input file */
		numobjs = oxlink_scan_file(desc, scratch);		

		/* oxlink_scan_file returns results in 'scratch' 
			and on the 'scratch' stack */
		for(i = 0; i < numobjs; ++i, free(objname), free(sympack))
		{
		unsigned long numsyms;
		unsigned long symsize;
		unsigned long objsize;
		unsigned long objoffset;
		unsigned long objnum;
		unsigned long objnamlen;
		SymItem objval;
		int objexists = 0;
		int clash = 0;

			cfpop_value(scratch, &symsize);
			cfpop_value(scratch, &numsyms);
			cfpop_value(scratch, &objnum);
			cfpop_value(scratch, &objnamlen);
			if(objnamlen > 0) {
				objname = malloc(objnamlen);
				cfpop_data(scratch, objname, objnamlen);
			} else {
				objname = fileof(path);
				objnamlen = strlen(objname)+1;
			}
			cfpop_value(scratch, &objsize);
			cfpop_value(scratch, &objoffset);

			/* Get space for a chunk of symbols */
			sympack = malloc(symsize+1);
			packx = 0;

			if((objnamlen + curliblen) > 255)
			{
				cfprintf("%s -- name too long. CONTINUING\n", objname);
				continue;
			}
			 /* Check the object file for current existence */
			curobjlen = cfsprintf(curobj, "%s/%s", curlib, objname);
			if(cffind(ipaths, curobj, curobjlen, &objval) >= FOUND)
			{
				objexists = 1;
				if(!(act & (arREPLACE|arUPDATE))) {
					cfprintf("%s found in archive. CONTINUING\n", curobj);
					continue;
				}
			}
			/* Pass 1 over the symbols, check for clashes */ 
			for(j = 0; j < numsyms; ++j)
			{/* The global symbols for each .o file have been saved
					in 'sratch', keyed by (objnum<<18+symnum) */
			Item symptr;
			long key = (objnum<<18)+j;
			SymItem symval;
			int x;
			  if(cffind(scratch, &key, 4, &symptr) == FOUND)
			  {
			  char *cp = cflocalize(scratch, &symptr);
				if(cp)
				{
				  /* Add to the quick access pack of symbols */
				  x = _strcpy(&sympack[packx], cp)+1;
				  if(!objexists)
				  {/* Check for symbol clash with other .o files in lib */
					long dupnum = 0;
					  for(;;)
					  {/* Duplicate symbols are allowed, in separate libs */
					  int result = cffind_dupnum(msyms,cp,x-1,&symval,&dupnum);
						if(result >= FOUND)
						{
							if(		symval.libtype == libtype
								&&	symval.libnum == libnum)
							{
								clash = 1;
							}
							if(!clash && result > FOUND)
							{/* Duplicate symbols exist */
								++dupnum;
								continue;
							} else break;
						} else break;
					  }
					}/* if(!objexists) */
					cfrelease(cp, R_CLEAN);
					if(clash)
					{
					char pathname[256];

					  pathname[0] = 0;
					  cfget(qipaths, &symval, 8, pathname, 256);
					  cfprintf("cfar: symbol `%s' in %s clashes with `%s' CONTINUING\n",
								&sympack[packx], objname, pathname);
					  break;
					}
					packx += x;
				  }/* if(cp) */
				}/* if(cffind ) */
			}/* END: for(j ) symbol pass 1 */
			if(clash || !(act & (arADD|arREPLACE|arUPDATE)))
				continue;

			/* NOW add or replace the object file */
			if(verbose || act == arUPDATE)
			{
				if(act == arUPDATE)
					 cfprintf("updating %s\n",objname);
				else cfprintf("%s\n", objname);
			}
			if(objexists) {
				delete_file(objname, 1);	
			} else {/* Get a new serial number for the .o file */
				objval.sn = new_sn("SN0");				
				objval.libnum = libnum;
				objval.libtype = libtype;
				objval.unused = 0;
				objval.tag = STO_VALUE;
			}

			/* Store the object file in a chunk */
#if 1 /* the easy slow way, not much memory usage */
			{
			void *of;
				if((of = cfmake_chunk(lib, objname, objnamlen-1, objsize)))
				{
					if(cfcopy_file(of, desc) != objsize)
					{
						cfclose(of);
						cfprintf("cfar: ERROR copying %s\n", objname);
						break;
					}
					cfclose(of);
				}
				else
				{
					cfprintf("cfar: ERROR can't make chunk for %s\n", objname);
					break;
				}
			}
#else /* the hard fast way, may use a LOT of memory */
			{
			Item space;
			char *loc;
				if(cfgetspace(lib, objsize, &space) != NULL)
				{/* ensure that there is enough space in the localizer bufs */
				long curbufs, objbufs;
					objbufs = (objsize / 1024)+1;
					curbufs = cfcurbufs();
					if(objbufs > curbufs)
					{
						cfmodbufs((objbufs-curbufs)+16);
						objbufs = cfcurbufs();
					}
					if((loc = cflocalize(lib, &space)) != NULL) {
						cfseek(desc, objoffset, S_SET);
						cfread(desc, loc, objsize);
						cfrelease(loc, R_DIRTY);
						cfinsert(lib, objname, objnamlen-1, &space);
					} else {
						cfretspace(lib, &space);
						cfprintf("cfar: ERROR can't localize space for %s\n", objname);
						break;
					}
				}
				else
				{
					cfprintf("cfar: ERROR can't allocate space for %s\n", objname);
					break;
				}
			}
#endif
			/* Store the quick access package of symbols */
			objname[objnamlen-2] = 'x';
			sympack[symsize] = 0;
			cfput(lib, objname, objnamlen-1, sympack, symsize+1, NULL); 

			/* Store the backlink to the origin, time + origin serial number */
			objname[objnamlen-2] = 't';
			cfinsert(lib, objname, objnamlen-1, &cur_org);

			/* Store the path, indexed both ways */
			cfinsert(ipaths, curobj, curobjlen, &objval);
			cfput(qipaths, &objval, 8, curobj, curobjlen+1, NULL);

			/* Store the symbols, symname is the key, objval is the item */
			/* Pass 2 over the symbols */ 
			for(j = 0; j < numsyms; ++j)
			{/* The global symbols for each .o file have been saved
					in 'scratch', keyed by (objnum<<18+symnum) */
			Item symptr;
			long key = (objnum<<18)+j;
				if(cffind(scratch, &key, 4, &symptr) == FOUND)
				{
				char *cp;
					if((cp = cflocalize(scratch, &symptr)) != NULL) {
						cfinsert_dupnum(msyms, cp, strlen(cp), &objval, NULL);
						cfrelease(cp, R_CLEAN);
					} else {
						cfprintf("cfar: ERROR can't localize space for symbol %d\n", j);
						break;
					}
				}
			}
		}/* END: for(numobjs) */
		cfclose(scratch);
		cfclose(desc);
	}/* END: if(desc) */
	else cfprintf("cfar: can't open file %s, CONTINUING\n", path);
}
static void
proc_objfile(char *path)
{
	if(issymbol && (act == arCHECK))
	{
		objof(path);
		return;
	}
	if(act & arEXTRACT)
		extract_file(path);
	if(act & arDELETE)
		delete_file(path, 0);
	if(act & (arADD|arREPLACE|arCHECK|arUPDATE))
		insert_file(path);
}
static void
print_map(char *arch)
{
char path[256];
void *dirh;
CFDIRENT *d;
int i, j;

	cfprintf("MAP of %s\n", arch);
	if(map_entries) {
		cfprintentries(arch);
		cfsprintf(path, "%s/ipaths", arch);
		cfprintentries(path);
		cfsprintf(path, "%s/qipaths", arch);
		cfprintentries(path);
		cfsprintf(path, "%s/origins", arch);
		cfprintentries(path);
		cfsprintf(path, "%s/qorigins", arch);
		cfprintentries(path);
		cfsprintf(path, "%s/msyms", arch);
		cfprintentries(path);
	}
	/* Print a list of origins */
	cfprintf("\n-------- OUTSIDE ORIGINS ----------\n\n");
	cfsprintf(path, "%s/origins", arch);
	if((origins = cfopen(path, F_STAT, NULL)) != NULL)
	{
	Item orgnum;
		if(cfhead(origins, &orgnum) == OK)
		{
			do {
				memclr(path, 255);
				cfkey(origins, path, 255);
				cfprintf("oid:%u\t%s\n", orgnum.a0, path);			
			} while(cfnext(origins, &orgnum) == OK);
		}	
		cfclose(origins);
	}
	/* Print the various libraries and entries */
	cfprintf("\n-------- LIBRARIES ----------\n\n");

	get_libtypes(arch);
	for(i = 0; i < MAXLIBTYPE; ++i)
	{
		if(!ltypes[i])
			continue;
		cfsprintf(path, "%s/ltype%d", arch, i);
		cfprintf("\nLibrary type %d\n", i);
		get_libnums(path);
		if(map_entries) {
			cfprintf("------------ RAW ENTRIES -----------\n");
			cfprintentries(path);
		}
		if(i == 3)
		{/* dllmode library */
			cfprintf("DLL SYMBOL ENTRIES\n");
			continue;
		}
		for(j = 0; j < 4096; ++j)
		{
		void *clib;
			if(!lnums[j])
				continue;
			cfsprintf(path, "%s/ltype%d/lib%d", arch, i, j);
			if((clib = cfopen(path, F_STAT, NULL)) != NULL) {
				if(verbose)
					cfprintf("------- lib%d  %d bytes -------\n",
						j, cfbytesused(clib));
				else
					cfprintf("------- lib%d --------\n", j);
				cfhead(clib, NULL);
				do {
				char key[256];
				int keylen;
					memclr(key,256);
					cfkey(clib, key, 255);
					keylen = strlen(key);
					if(key[keylen-1] == 'o') {
						if(verbose) {
						int dlen;
						OrgItem oi;
							cfdatalen(clib, &dlen);
							key[keylen-1] = 't';
							cffind(clib, key, keylen, &oi);
							key[keylen-1] = 'o';
							cfprintf("    %s  bytes:%u oid:%u %s", 
								key, dlen, oi.sn, ctime(&oi.filetime));
						}
						else
							cfprintf("     %s\n", key);
						if(verbose) {
						Item pakval;
						char *cp, *sp;
							key[keylen-1] = 'x';
							cfmark(clib);
							cffind(clib, key, keylen, &pakval);
							cp = cflocalize(clib, &pakval);
							for(sp=cp; *sp; sp += strlen(sp)+1)
							{
								cfprintf("        %s\n", sp);
							}
							cfrelease(cp, R_CLEAN);
							cffind_mark(clib, NULL);
						}
					}
				} while (cfnext(clib, NULL) == OK);
				if(map_entries) {
					cfprintf("------------ RAW ENTRIES -----------\n");
					cfprintentries(clib);
				}
				cfclose(clib);
			}
		}
	}
	/* Print the list of stored files */
	cfprintf("\n---------- STORED FILES ----------\n\n");
	cfsprintf(path, "%s/fipaths", arch);
	if((fipaths = cfopen(path, F_STAT, NULL)) != NULL)
	{
	OrgItem oi;
		if(cfhead(fipaths, &oi) == OK)
		{
			do {
				memclr(path, 255);
				cfkey(fipaths, path, 255);
				cfprintf("%s\toid:%u  %s",
					path, oi.sn, ctime(&oi.filetime));
			} while(cfnext(fipaths, &oi) == OK);
		}
		if(map_entries) {
			cfprintf("------------ RAW ENTRIES -----------\n");
			cfprintentries(fipaths);
		}
		cfclose(fipaths);
	}
	if(map_bitmaps) {
		cfprintf("\n------------ BITMAPS ---------------\n");
		cfprintbitmaps(arch);
	}
}
static void
Usage()
{
cfprintf("\
Usage: cfar [-acdflmrstvxCDFMNS] cfpath [file...]\n\
    Switch -- Meaning\n\
    a         Add file, do not overwrite\n\
    c         Check input files against library for clashes\n\
    d         Delete file\n\
    f         Freshen the archive (replace outdated files)\n\
    l#        Place file in libnum #, max:4095\n\
    m         Print archive map to stdout\n\
    r         Replace/Add file\n\
    s         'file' is a symbol name not a file name (for extract/delete)\n\
    t#        Set libtype # 0=module, 1=class, 2=subsystem, max:15\n\
    v         Verbose\n\
    x         Extract file\n\
    M         Print to stdout, commands which would recreate the archive\n\
    S         Shrink archive\n\
    D         Dll mode, deal with symbols stored in dlls\n\
    F         File mode, symbols not saved\n\
    C         If File mode, put file in a chunk\n\

⌨️ 快捷键说明

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