示例#1
0
void	compile_source_file(unsigned short flen, char *faddr)
{
	plength		plen;
	mval		fstr, ret;
	int		i;
	unsigned char	*p;
	error_def	(ERR_FILEPARSE);
	error_def	(ERR_FILENOTFND);
	error_def	(ERR_ERRORSUMMARY);

	if (MAX_FBUFF < flen)
	{
		dec_err(VARLSTCNT(4) ERR_FILEPARSE, 2, flen, faddr);
		dollar_zcstatus = ERR_ERRORSUMMARY;
	} else
	{
		fstr.mvtype = MV_STR;
		fstr.str.addr = faddr;
		fstr.str.len = flen;
		ESTABLISH(source_ch);
		tt_so_do_once = FALSE;
		for (i = 0 ;  ; i++)
		{
			plen.p.pint = op_fnzsearch(&fstr, 0, &ret);
			if (!ret.str.len)
			{
				if (!i)
				{
					dec_err(VARLSTCNT(4) ERR_FILENOTFND, 2, fstr.str.len, fstr.str.addr);
					dollar_zcstatus = ERR_ERRORSUMMARY;
				}
				break;
			}
			assert(ret.mvtype == MV_STR);
			assert(ret.str.len <= MAX_FBUFF);
			source_name_len = ret.str.len;
			memcpy(source_file_name, ret.str.addr, source_name_len);
			source_file_name[source_name_len] = 0;
			p = &source_file_name[plen.p.pblk.b_dir];
			if ((plen.p.pblk.b_dir >= sizeof("/dev/") - 1) && !MEMCMP_LIT(source_file_name, "/dev/"))
				tt_so_do_once = TRUE;
			else if (plen.p.pblk.b_ext != 2
				 || ('M' != p[plen.p.pblk.b_name + 1]  &&  'm' != p[plen.p.pblk.b_name + 1]))
			{
				dec_err(VARLSTCNT(4) ERR_FILEPARSE, 2, source_name_len, source_file_name);
				dollar_zcstatus = ERR_ERRORSUMMARY;
				continue;
			}

			if (compiler_startup())
				dollar_zcstatus = ERR_ERRORSUMMARY;

			if (tt_so_do_once)
				break;
		}
		REVERT;
	}
}
示例#2
0
void op_zrupdate(int argcnt, ...)
{
	mval			*objfilespec;
	va_list			var;
	mval			objpath;
	char			tranbuf[MAX_FBUFF + 1], *chptr, chr;
	open_relinkctl_sgm 	*linkctl;
	relinkrec_t		*rec;
	plength			plen;
	int			status, fextlen, fnamlen, fcnt;
	parse_blk		pblk;
	struct stat		outbuf;
        int			stat_res;
	boolean_t		seenfext, fileexists;
	mstr			objdir, rtnname;
	uint4			hash, prev_hash_index;

	/* Currently only expecting one value per invocation right now. That will change in phase 2 hence the stdarg setup */
	va_start(var, argcnt);
	assert(1 == argcnt);
	objfilespec = va_arg(var, mval *);
	va_end(var);
	MV_FORCE_STR(objfilespec);
	/* First some pre-processing to determine if an explicit file name or type was specified. If so, it must be ".o" for
	 * this phase of implementation. Later phases may allow ".m" to be specified but not initially. Use parse_file() to
	 * parse everything out and isolate any extention.
	 */
	memset(&pblk, 0, SIZEOF(pblk));
        pblk.buffer = tranbuf;
	pblk.buff_size = (unsigned char)(MAX_FBUFF);	/* Pass size of buffer - 1 (standard protocol for parse_file) */
	pblk.def1_buf = DOTOBJEXT;			/* Default .o file type if not specified */
	pblk.def1_size = SIZEOF(DOTOBJEXT) - 1;
	pblk.fop = F_SYNTAXO;				/* Syntax check only - bypass directory existence check */
	status = parse_file(&objfilespec->str, &pblk);
	if (ERR_PARNORMAL != status)
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, objfilespec->str.len, objfilespec->str.addr, status);
	tranbuf[pblk.b_esl] = '\0';			/* Needed for subsequent STAT_FILE */
	seenfext = FALSE;
	if (0 != pblk.b_ext)
	{	/* If a file extension was specified - get the extension sans any potential wildcard character */
		for (chptr = pblk.l_ext + 1, fextlen = pblk.b_ext - 1; 0 < fextlen; chptr++, fextlen--)
		{	/* Check each character in the extension except first which is the dot if ext exists at all */
			if (WILDCARD != *chptr)
			{	/* We see a char that isn't a wildcard character. If we've already seen our "o" file extension,
				 * this char makes our requirement filetype impossible so raise an error.
				 */
				if (seenfext || (OBJEXT != *chptr))
					/* No return from this error */
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_FILEPARSE,
						      2, objfilespec->str.len, objfilespec->str.addr,
						      ERR_TEXT, 2, RTS_ERROR_TEXT("Unsupported filetype specified"));
				seenfext = TRUE;
			}
		}
	}
	/* Do a simlar check for the file type */
	if (0 != pblk.b_name)
	{	/* A file name was specified (if not, tiz probably hard to find the file but that can be dealt with later).
		 * Like in the above, the name must be comprised of valid chars for routine names.
		 */
		for (chptr = pblk.l_name, fnamlen = pblk.b_name; 0 < fnamlen; chptr++, fnamlen--)
		{
			if (WILDCARD != *chptr)
			{	/* Substitute '%' for '_'. While this substitution is really only valid on the first char, only the
				 * first char check allows "%" so a 2nd or later char check would fail the '%' substitution anyway.
				 */
				chr = ('_' == *chptr) ? '%' : *chptr;
				/* We see a char that isn't a wildcard character. If this is the first character, it can be
				 * alpha or percent. If the second or later character, it can be alphanumeric.
				 */
				if (((fnamlen != pblk.b_name) && !VALID_MNAME_NFCHAR(chr))	/* 2nd char or later check */
				    || ((fnamlen == pblk.b_name) && !VALID_MNAME_FCHAR(chr)))	/* 1st char check */
				{
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_FILEPARSE,
						      2, objfilespec->str.len, objfilespec->str.addr,
						      ERR_TEXT, 2, RTS_ERROR_TEXT("Filename is not a valid routine name"));
				}
			}
		}
	}
	/* When specifying a non-wildcarded object file, it is possible for the file to have been removed, in which case we still
	 * need to update its relinkctl entry (if exists) to notify other processes about the object's deletion.
	 */
	if (!(pblk.fnb & F_WILD) & seenfext)
	{	/* If no wildcards in path and saw the extension we want - no need to wash through zsearch() */
		objdir.addr = pblk.l_dir;
		objdir.len = pblk.b_dir;
		linkctl = relinkctl_attach(&objdir);		/* Create/attach/open relinkctl file */
		if (NULL == linkctl)				/* Non-existant path and no associated relinkctl file */
			/* Note this reference to errno depends on nothing in relinkctl_attach() doing anything to modify
			 * errno after the realpath() call. No return from this error.
			 */
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, objfilespec->str.len, objfilespec->str.addr,
				      errno);
		/* What we do at this point depends on the following conditions:
		 *
		 * 1) If the specified file exists, we can add it to relinkctl file and/or update its cycle.
		 * 2) If the file doesn't exist on disk but the routine is found in the relinkctl file, update cycle.
		 * 3) If no file and no entry, just ignore it and do nothing (info error removed by request).
		 */
		STAT_FILE(tranbuf, &outbuf, stat_res);
		if (-1 == stat_res)
		{
			if (ENOENT != errno)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_FILEPARSE, 2, objfilespec->str.len,
					      objfilespec->str.addr, errno);
			fileexists = FALSE;
		} else
			fileexists = TRUE;
		rtnname.len = pblk.b_name;
		rtnname.addr = pblk.l_name;
		CONVERT_FILENAME_TO_RTNNAME(rtnname);	/* Set rtnname right before searching in relinkctl file */
		assert(valid_mname(&rtnname));
		COMPUTE_RELINKCTL_HASH(&rtnname, hash);
		rec = relinkctl_find_record(linkctl, &rtnname, hash, &prev_hash_index);
		if ((NULL == rec) && !fileexists)
			return;					/* No file and no entry - ignore */
		/* Either the file exists or the entry exists so add or update it */
		rec = relinkctl_insert_record(linkctl, &rtnname);
		RELINKCTL_CYCLE_INCR(rec, linkctl); 		/* Increment cycle indicating change to world */
		return;
	}
	/* If we have a wildcarded request or one without the object filetype, reprocess the string with $ZSEARCH using our
	 * defined stream to resolve wildcards. Then loop through processing each file returned. In this loop, we just ignore
	 * any file that doesn't have a ".o" extension.
	 */
	op_fnzsearch((mval *)&literal_null, STRM_ZRUPDATE, 0, &objpath);	/* Clear any existing cache */
	for (fcnt = 0; ; fcnt++)
	{
		plen.p.pint = op_fnzsearch(objfilespec, STRM_ZRUPDATE, 0, &objpath);
		if (0 == objpath.str.len)
		{	/* End of file list */
			if (0 == fcnt)
				/* Still looking to process our first file - give no objects found message as a "soft" message
				 * (INFO level message - supressed in other than direct mode)
				 */
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) MAKE_MSG_INFO(ERR_FILEPARSE), 2, objfilespec->str.len,
					      objfilespec->str.addr, ERR_TEXT, 2, RTS_ERROR_TEXT("No object files found"));
			break;
		}
		/* The extension contains the extension-start character ('.') so we are looking for the extension '.o' hence
		 * the length must be 2 and the 2nd char must be OBJEXT.
		 */
		if ((2 == plen.p.pblk.b_ext) && (OBJEXT == *(objpath.str.addr + plen.p.pblk.b_dir + plen.p.pblk.b_name + 1)))
		{			/* This is (probably) an object file. Double check file is a file and not a directory */
			memcpy(tranbuf, objpath.str.addr, objpath.str.len);	/* Need null terminated version for STAT */
			tranbuf[objpath.str.len] = '\0';		/* Not guaranteed null termination from op_fnzsearch */
			STAT_FILE(tranbuf, &outbuf, stat_res);
			/* If either something happened to the file since op_fnzsearch() saw it or the file is not a file, then
			 * ignore it.
			 */
			if ((-1 == stat_res) || !S_ISREG(outbuf.st_mode))
			{
				fcnt--;					/* Don't count files not found for whatever reason */
				continue;
			}
			/* Before opening the relinkctl file, verify we actually do have a valid routine name */
			rtnname.len = plen.p.pblk.b_name;
			rtnname.addr = objpath.str.addr + plen.p.pblk.b_dir;
			CONVERT_FILENAME_TO_RTNNAME(rtnname);		/* Set rtnname right before searching in relinkctl file */
			if (!valid_mname(&rtnname))
			{
				fcnt--;
				continue;				/* Ignore files that are invalid wildcard matches */
			}
			objdir.addr = objpath.str.addr;
			objdir.len = plen.p.pblk.b_dir;
			linkctl = relinkctl_attach(&objdir);		/* Create/attach/open relinkctl file */
			if (NULL == linkctl)
			{
				fcnt--;					/* Path disappeared - don't count it */
				continue;
			}
			rec = relinkctl_insert_record(linkctl, &rtnname);
			RELINKCTL_CYCLE_INCR(rec, linkctl); 		/* Increment cycle indicating change to world */
		} else
			fcnt--;						/* Don't count ignored files */

	}
}
示例#3
0
void	compile_source_file(unsigned short flen, char *faddr, boolean_t MFtIsReqd)
{
	plength		plen;
	mval		fstr, ret;
	int		i, rc;
	unsigned char	*p;
	boolean_t	wildcarded, dm_action;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	if (MAX_FBUFF < flen)
	{
		dec_err(VARLSTCNT(4) ERR_FILEPARSE, 2, flen, faddr);
		TREF(dollar_zcstatus) = ERR_ERRORSUMMARY;
	} else
	{
		object_file_des = FD_INVALID;
		fstr.mvtype = MV_STR;
		fstr.str.addr = faddr;
		fstr.str.len = flen;
		ESTABLISH(source_ch);
		tt_so_do_once = FALSE;
		zsrch_clr(STRM_COMP_SRC);	/* Clear any existing search cache */
		for (i = 0; ; i++)
		{
			plen.p.pint = op_fnzsearch(&fstr, STRM_COMP_SRC, 0, &ret);
			if (!ret.str.len)
			{
				if (!i)
				{
					dec_err(VARLSTCNT(4) ERR_FILENOTFND, 2, fstr.str.len, fstr.str.addr);
					TREF(dollar_zcstatus) = ERR_ERRORSUMMARY;
				}
				break;
			}
			assert(ret.mvtype == MV_STR);
			assert(ret.str.len <= MAX_FBUFF);
			source_name_len = ret.str.len;
			memcpy(source_file_name, ret.str.addr, source_name_len);
			source_file_name[source_name_len] = 0;
			p = &source_file_name[plen.p.pblk.b_dir];
			if ((plen.p.pblk.b_dir >= SIZEOF("/dev/") - 1) && !MEMCMP_LIT(source_file_name, "/dev/"))
				tt_so_do_once = TRUE;
			else if (MFtIsReqd && (plen.p.pblk.b_ext != 2 || ('M' != p[plen.p.pblk.b_name + 1]
									  &&  'm' != p[plen.p.pblk.b_name + 1])))
			{	/* M filetype is required but not present */
				dec_err(VARLSTCNT(4) ERR_FILEPARSE, 2, source_name_len, source_file_name);
				TREF(dollar_zcstatus) = ERR_ERRORSUMMARY;
				continue;
			}
			if (compiler_startup())
				TREF(dollar_zcstatus) = ERR_ERRORSUMMARY;
			if (FD_INVALID != object_file_des)
			{
				CLOSEFILE_RESET(object_file_des, rc);	/* resets "object_file_des" to FD_INVALID */
				if (-1 == rc)
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_OBJFILERR, 2,
							object_name_len, object_file_name, errno);
			}
			if (tt_so_do_once)
				break;
		}
		REVERT;
	}
}