Exemplo n.º 1
0
callin_entry_list* citab_parse (void)
{
	int			parameter_count, i, fclose_res;
	uint4			inp_mask, out_mask, mask;
	mstr			labref, callnam;
	enum gtm_types		ret_tok, parameter_types[MAX_ACTUALS], pr;
	char			str_buffer[MAX_TABLINE_LEN], *tbp, *end;
	FILE			*ext_table_file_handle;
	callin_entry_list	*entry_ptr = NULL, *save_entry_ptr = NULL;

	ext_table_file_name = GETENV(CALLIN_ENV_NAME);
	if (!ext_table_file_name) /* environment variable not set */
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CITABENV, 2, LEN_AND_STR(CALLIN_ENV_NAME));

	ext_table_file_handle = Fopen(ext_table_file_name, "r");
	if (!ext_table_file_handle) /* call-in table not found */
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(11) ERR_CITABOPN, 2, LEN_AND_STR(ext_table_file_name),
			  ERR_SYSCALL, 5, LEN_AND_LIT("fopen"), CALLFROM, errno);
	ext_source_line_num = 0;
	while (read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle))
	{
		if (!*(tbp = exttab_scan_space(str_buffer)))
			continue;
		if (!(end = scan_ident(tbp)))
			ext_stx_error(ERR_CIRCALLNAME, ext_table_file_name);
		callnam.addr = tbp;
		callnam.len = INTCAST(end - tbp);
		tbp = exttab_scan_space(end);
		if (':' != *tbp++)
			ext_stx_error(ERR_COLON, ext_table_file_name);
		ret_tok = scan_keyword(&tbp); /* return type */
		switch (ret_tok) /* return type valid ? */
		{
			case gtm_void:
			case gtm_char_star:
			case gtm_int_star:
			case gtm_uint_star:
			case gtm_long_star:
			case gtm_ulong_star:
			case gtm_float_star:
			case gtm_double_star:
			case gtm_string_star:
			case gtm_jboolean:
			case gtm_jint:
			case gtm_jlong:
			case gtm_jfloat:
			case gtm_jdouble:
			case gtm_jstring:
			case gtm_jbyte_array:
			case gtm_jbig_decimal:
				break;
			default:
				ext_stx_error(ERR_CIRTNTYP, ext_table_file_name);
		}
		labref.addr = tbp;
		if ((end = scan_labelref(tbp)))
			labref.len = INTCAST(end - tbp);
		else
			ext_stx_error(ERR_CIENTNAME, ext_table_file_name);
		tbp = exttab_scan_space(end);
		inp_mask = out_mask = 0;
		for (parameter_count = 0; (*tbp && ')' != *tbp); parameter_count++)
		{
			if (MAX_ACTUALS <= parameter_count)
				ext_stx_error(ERR_CIMAXPARAM, ext_table_file_name);
			/* must have comma if this is not the first parameter, otherwise '(' */
			if (((0 == parameter_count)?'(':',') != *tbp++)
				ext_stx_error(ERR_CIRPARMNAME, ext_table_file_name);
			tbp = exttab_scan_space(tbp);
			if ((0 == parameter_count) && (*tbp == ')')) /* special case () */
				break;
			/* looking for an I, a O or an IO */
			mask = (1 << parameter_count);
			inp_mask |= ('I' == *tbp) ? (tbp++, mask) : 0;
			out_mask |= ('O' == *tbp) ? (tbp++, mask) : 0;
			if ((!(inp_mask & mask) && !(out_mask & mask)) || (':' != *tbp++))
				ext_stx_error(ERR_CIDIRECTIVE, ext_table_file_name);
			switch ((pr = scan_keyword(&tbp))) /* valid param type? */
			{
				case gtm_int:
				case gtm_uint:
				case gtm_long:
				case gtm_ulong:
				case gtm_float:
				case gtm_double:
					if (out_mask & mask)
						ext_stx_error(ERR_CIPARTYPE, ext_table_file_name);
					/* fall-thru */
				case gtm_char_star:
				case gtm_int_star:
				case gtm_uint_star:
				case gtm_long_star:
				case gtm_ulong_star:
				case gtm_float_star:
				case gtm_double_star:
				case gtm_string_star:
				case gtm_jboolean:
				case gtm_jint:
				case gtm_jlong:
				case gtm_jfloat:
				case gtm_jdouble:
				case gtm_jstring:
				case gtm_jbyte_array:
				case gtm_jbig_decimal:
					break;
				default:
					ext_stx_error(ERR_CIUNTYPE, ext_table_file_name);
			}
			parameter_types[parameter_count] = pr;
			tbp = exttab_scan_space(tbp);
		}
		if (!*tbp)
			ext_stx_error(ERR_CIRPARMNAME, ext_table_file_name);
		entry_ptr = get_memory(SIZEOF(callin_entry_list));
		entry_ptr->next_entry = save_entry_ptr;
		save_entry_ptr = entry_ptr;
		entry_ptr->return_type = ret_tok;
		entry_ptr->argcnt = parameter_count;
		entry_ptr->input_mask = inp_mask;
		entry_ptr->output_mask = out_mask;
		entry_ptr->parms = get_memory(parameter_count * SIZEOF(entry_ptr->parms[0]));
		for (i = 0 ; i < parameter_count; i++)
			entry_ptr->parms[i] = parameter_types[i];
		put_mstr(&labref, &entry_ptr->label_ref);
		put_mstr(&callnam, &entry_ptr->call_name);
	}
	FCLOSE(ext_table_file_handle, fclose_res);
	return entry_ptr;
}
Exemplo n.º 2
0
std::string string_format(const char* fmt, int numargs, FormatArg const * const args[]) {
	std::string out;
	const char *c = fmt;
	while (*c) {
		while (*c && *c != '%') ++c;
		if (c != fmt) out.append(fmt, c - fmt);
		fmt = c;

		if (*c == '%') {
			++c;
			if (*c == '%') {
				fmt = c;
				++c;
			} else {
				int argid = -1;
				const char* identBegin = c;
				const char* identEnd = c;

				// parse and match reference
				if (isdigit(*c)) {
					c = identEnd = scan_int(identBegin = c, argid);
				} else {
					if (*c == '{') {
						identBegin = ++c;
						while (*c && (*c != '}')) ++c;
						identEnd = c;
						if (*c == '}')
							++c;
						else {
							out.append("%(err: unfinished reference)");
							goto bad_reference;
						}
					} else if (isalpha(*c) || (*c == '_')) {
						c = identEnd = scan_ident(identBegin = c);
					} else {
						out.append("%(err: unfinished reference)");
						goto bad_reference;
					}

					if (identBegin == identEnd) {
						out.append("%(err: blank reference)");
						goto bad_reference;
					}

					for (int i = 0; i < numargs; ++i) {
						size_t identLen = (identEnd - identBegin);
						if (args[i]->name
							&& (strncmp(args[i]->name, identBegin, identLen) == 0)
							&& (args[i]->name[identLen] == '\0')) {
							argid = i;
							break;
						}
					}
				}

				if (argid >= 0 && argid < numargs) {
					const FormatArg& arg = *args[argid];
					const char* fmtBegin = 0;
					const char* fmtEnd = 0;
					// scan format specifier, if provided
					if (*c == '{') {
						++c;
						if (!*c) {
							out.append("%(err: unfinished format)");
							goto bad_reference;
						}

						c = fmtEnd = scan_bracetext(fmtBegin = c);

						if (fmtBegin == fmtEnd) {
							fmtBegin = fmtEnd = 0;
						}

						if (!*c) {
							out.append("%(err: unfinished format)");
							goto bad_reference;
						} else
							++c;
					}

					if (fmtBegin) {
						assert(fmtEnd > fmtBegin);
						FormatSpec fspec(fmtBegin, fmtEnd - fmtBegin);
						out.append(arg.format(fspec));
					} else if (arg.defaultformat) {
						FormatSpec fspec(arg.defaultformat);
						out.append(arg.format(fspec));
					} else
						out.append(arg.format(FormatSpec()));

				} else {
					out.append("%(err: unknown arg '");
					out.append(identBegin, identEnd - identBegin);
					out.append("')");
					goto bad_reference;
				}

bad_reference:
				fmt = c;
			}
		}
	}
	// append the final range
	if (c != fmt)
		out.append(fmt, c - fmt);
	return out;
}
Exemplo n.º 3
0
/* Note: Need condition handler to clean-up allocated structures and close intput file in the event of an error */
struct extcall_package_list *exttab_parse(mval *package)
{
	int		parameter_alloc_values[MAX_ACTUALS], parameter_count, ret_pre_alloc_val, i, fclose_res;
	int		len, keywordlen;
	boolean_t	is_input[MAX_ACTUALS], is_output[MAX_ACTUALS], got_status;
	mstr		callnam, rtnnam, clnuprtn;
	mstr 		val, trans;
	void_ptr_t	pakhandle;
	enum gtm_types	ret_tok, parameter_types[MAX_ACTUALS], pr;
	char		str_buffer[MAX_TABLINE_LEN], *tbp, *end;
	char		str_temp_buffer[MAX_TABLINE_LEN];
	FILE		*ext_table_file_handle;
	struct extcall_package_list	*pak;
	struct extcall_entry_list	*entry_ptr;

	/* First, construct package name environment variable */
	memcpy(str_buffer, PACKAGE_ENV_PREFIX, SIZEOF(PACKAGE_ENV_PREFIX));
	tbp = &str_buffer[SIZEOF(PACKAGE_ENV_PREFIX) - 1];
	if (package->str.len)
	{
		/* guaranteed by compiler */
		assert(package->str.len < MAX_NAME_LENGTH - SIZEOF(PACKAGE_ENV_PREFIX) - 1);
		*tbp++ = '_';
		memcpy(tbp, package->str.addr, package->str.len);
		tbp += package->str.len;
	}
	*tbp = 0;
	/* Now we have the environment name, lookup file name */
	ext_table_file_name = GETENV(str_buffer);
	if (NULL == ext_table_file_name)
	{
		/* Environment variable for the package not found */
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZCCTENV, 2, LEN_AND_STR(str_buffer));
	}
	ext_table_file_handle = Fopen(ext_table_file_name, "r");
	if (NULL == ext_table_file_handle)
	{
		/* Package's external call table could not be found */
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZCCTOPN, 2, LEN_AND_STR(ext_table_file_name));
	}
	ext_source_line_num = 0;
	/* Pick-up name of shareable library */
	tbp = read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle);
	if (NULL == tbp)
	{
		/* External call table is a null file */
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZCCTNULLF, 2, package->str.len, package->str.addr);
	}
	STRNCPY_STR(str_temp_buffer, str_buffer, MAX_TABLINE_LEN);
	val.addr = str_temp_buffer;
	val.len = STRLEN(str_temp_buffer);
	/* Need to copy the str_buffer into another temp variable since
	 * TRANS_LOG_NAME requires input and output buffers to be different.
	 * If there is an env variable present in the pathname, TRANS_LOG_NAME
	 * expands it and return SS_NORMAL. Else it returns SS_NOLOGNAM.
	 * Instead of checking 2 return values, better to check against SS_LOG2LONG
	 * which occurs if the pathname is too long after any kind of expansion.
 	 */
	if (SS_LOG2LONG == TRANS_LOG_NAME(&val, &trans, str_buffer, SIZEOF(str_buffer), dont_sendmsg_on_log2long))
	{
		/* Env variable expansion in the pathname caused buffer overflow */
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.len, val.addr, SIZEOF(str_buffer) - 1);
	}
	pakhandle = fgn_getpak(str_buffer, INFO);
	if (NULL == pakhandle)
	{
		/* Unable to obtain handle to the shared library */
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZCUNAVAIL, 2, package->str.len, package->str.addr);
	}
	pak = get_memory(SIZEOF(*pak));
	pak->first_entry = 0;
	put_mstr(&package->str, &pak->package_name);
	pak->package_handle = pakhandle;
	pak->package_clnup_rtn = NULL;
	len = STRLEN("GTMSHLIBEXIT");
	/* At this point, we have a valid package, pointed to by pak */
#	ifdef DEBUG_EXTCALL
	FPRINTF(stderr, "GT.M external call opened package name: %s\n", pak->package_name.addr);
#	endif
	for (;;)
	{
		star_found = FALSE;
		tbp = read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle);
		if (NULL == tbp)
			break;
		tbp = exttab_scan_space(str_buffer);
		/* Empty line? */
		if (!*tbp)
			continue;
		/* No, must be entryref or keyword */
		end = scan_ident(tbp);
		if (!end)
			ext_stx_error(ERR_ZCENTNAME, ext_table_file_name);
		keywordlen = end - tbp;
		end = exttab_scan_space(end);
		if ('=' == *end)
		{	/* Keyword before '=' has a string of size == STRLEN("GTMSHLIBEXIT") */
			if (keywordlen == len)
			{
				if (0 == MEMCMP_LIT(tbp, "GTMSHLIBEXIT"))
				{
					/* Skip past the '=' char */
					tbp = exttab_scan_space(end + 1);
					if (*tbp)
					{	/* We have a cleanup routine name */
						clnuprtn.addr = tbp;
						clnuprtn.len = scan_ident(tbp) - tbp;
						clnuprtn.addr[clnuprtn.len] = 0;
						pak->package_clnup_rtn =
						  (clnupfptr)fgn_getrtn(pak->package_handle, &clnuprtn, ERROR);
					} else
						ext_stx_error(ERR_ZCCLNUPRTNMISNG, ext_table_file_name);
					continue;
				}
			}
			ext_stx_error(ERR_ZCINVALIDKEYWORD, ext_table_file_name);
			continue;
		}
		if ('^' == *end)
		{
			end++;
			end = scan_ident(end);
			if (!end)
				ext_stx_error(ERR_ZCENTNAME, ext_table_file_name);
		}
		rtnnam.addr = tbp;
		rtnnam.len = INTCAST(end - tbp);
		tbp = exttab_scan_space(end);
		if (':' != *tbp++)
			ext_stx_error(ERR_ZCCOLON, ext_table_file_name);
		/* Get return type */
		ret_tok = scan_keyword(&tbp);
		/* Check for legal return type */
		switch (ret_tok)
		{
			case gtm_status:
			case gtm_void:
			case gtm_int:
			case gtm_uint:
			case gtm_long:
			case gtm_ulong:
			case gtm_char_star:
			case gtm_float_star:
			case gtm_string_star:
			case gtm_int_star:
			case gtm_uint_star:
			case gtm_long_star:
			case gtm_ulong_star:
			case gtm_double_star:
			case gtm_char_starstar:
			case gtm_pointertofunc:
			case gtm_pointertofunc_star:
			case gtm_jboolean:
			case gtm_jint:
			case gtm_jlong:
			case gtm_jfloat:
			case gtm_jdouble:
			case gtm_jstring:
			case gtm_jbyte_array:
			case gtm_jbig_decimal:
				break;
			default:
				ext_stx_error(ERR_ZCRTNTYP, ext_table_file_name);
		}
		got_status = (ret_tok == gtm_status);
		/* Get call name */
		if ('[' == *tbp)
		{
			if (star_found)
				ret_pre_alloc_val = scan_array_bound(&tbp,ret_tok);
			else
				ext_stx_error(ERR_ZCPREALLVALPAR, ext_table_file_name);
			/* We should allow the pre-allocated value upto to the maximum string size (MAX_STRLEN) plus 1 for the
			 * extra terminating NULL. Negative values would have been caught by scan_array_bound() above.
			 */
			if (ret_pre_alloc_val > MAX_STRLEN + 1)
				ext_stx_error(ERR_ZCPREALLVALINV, ext_table_file_name);
		} else
			ret_pre_alloc_val = -1;
		/* Fix C9E12-002681 */
		if ('%' == *tbp)
			*tbp = '_';
		end = scan_ident(tbp);
		if (!end)
			ext_stx_error(ERR_ZCRCALLNAME, ext_table_file_name);
		callnam.addr = tbp;
		callnam.len = INTCAST(end - tbp);
		tbp = exttab_scan_space(end);
		tbp = exttab_scan_space(tbp);
		for (parameter_count = 0;(MAX_ACTUALS > parameter_count) && (')' != *tbp); parameter_count++)
		{
			star_found = FALSE;
			/* Must have comma if this is not the first parameter, otherwise '(' */
			if (((0 == parameter_count)?'(':',') != *tbp++)
				ext_stx_error(ERR_ZCRPARMNAME, ext_table_file_name);
			tbp = exttab_scan_space(tbp);
			/* Special case: () is ok */
			if ((0 == parameter_count) && (*tbp == ')'))
				break;
			/* Looking for an I, an O or an IO */
			is_input[parameter_count] = is_output[parameter_count] = FALSE;
			if ('I' == *tbp)
			{
				is_input[parameter_count] = TRUE;
				tbp++;
			}
			if ('O' == *tbp)
			{
				is_output[parameter_count] = TRUE;
				tbp++;
			}
			if (((FALSE == is_input[parameter_count]) && (FALSE == is_output[parameter_count]))
			    ||(':' != *tbp++))
				ext_stx_error(ERR_ZCRCALLNAME, ext_table_file_name);
			/* Scanned colon--now get type */
			pr = scan_keyword(&tbp);
			if (gtm_notfound == pr)
				ext_stx_error(ERR_ZCUNTYPE, ext_table_file_name);
			if (gtm_status == pr)
			{
				/* Only one type "status" allowed per call */
				if (got_status)
					ext_stx_error(ERR_ZCMLTSTATUS, ext_table_file_name);
				else
					got_status = TRUE;
			}
			parameter_types[parameter_count] = pr;
			if ('[' == *tbp)
			{
				if (star_found && !is_input[parameter_count])
					parameter_alloc_values[parameter_count] = scan_array_bound(&tbp, pr);
				else
					ext_stx_error(ERR_ZCPREALLVALPAR, ext_table_file_name);
				/* We should allow the pre-allocated value upto to the maximum string size (MAX_STRLEN) plus 1 for
				 * the extra terminating NULL. Negative values would have been caught by scan_array_bound() above.
				 */
				if (parameter_alloc_values[parameter_count] > MAX_STRLEN + 1)
					ext_stx_error(ERR_ZCPREALLVALINV, ext_table_file_name);
			} else
				parameter_alloc_values[parameter_count] = -1;
			tbp = exttab_scan_space(tbp);
		}
		entry_ptr = get_memory(SIZEOF(*entry_ptr));
		entry_ptr->next_entry = pak->first_entry;
		pak->first_entry = entry_ptr;
		entry_ptr->return_type = ret_tok;
		entry_ptr->ret_pre_alloc_val = ret_pre_alloc_val;
		entry_ptr->argcnt = parameter_count;
		entry_ptr->input_mask = array_to_mask(is_input, parameter_count);
		entry_ptr->output_mask = array_to_mask(is_output, parameter_count);
		entry_ptr->parms = get_memory(parameter_count * SIZEOF(entry_ptr->parms[0]));
		entry_ptr->param_pre_alloc_size = get_memory(parameter_count * SIZEOF(intszofptr_t));
		entry_ptr->parmblk_size = (SIZEOF(void *) * parameter_count) + SIZEOF(intszofptr_t);
		for (i = 0 ; i < parameter_count; i++)
		{
			entry_ptr->parms[i] = parameter_types[i];
			assert(gtm_void != parameter_types[i]);
			entry_ptr->parmblk_size += parm_space_needed[parameter_types[i]];
			entry_ptr->param_pre_alloc_size[i] = parameter_alloc_values[i];
		}
		put_mstr(&rtnnam, &entry_ptr->entry_name);
		put_mstr(&callnam, &entry_ptr->call_name);

		/* The reason for passing INFO severity is that PROFILE has several routines listed in
		 * the external call table that are not in the shared library. PROFILE folks would
		 * rather see info/warning messages for such routines at shared library open time,
		 * than error out. These unimplemented routines, they say were not being called from
		 * the application and wouldn't cause any application failures. If we fail to open
		 * the shared libary, or we fail to locate a routine that is called from the
		 * application, we issue rts_error message (in extab_parse.c).
		 */
		entry_ptr->fcn = fgn_getrtn(pak->package_handle, &entry_ptr->call_name, INFO);
#		ifdef DEBUG_EXTCALL
		FPRINTF(stderr, "   package entry point: %s, address: %x\n", entry_ptr->entry_name.addr, entry_ptr->fcn);
#		endif
	}
	FCLOSE(ext_table_file_handle, fclose_res);
	return pak;
}
Exemplo n.º 4
0
STATICFNDEF enum gtm_types scan_keyword(char **c)
{
	const static struct
	{
		char		nam[MAX_NAM_LEN];
		enum gtm_types	typ[MAXIMUM_STARS + 1]; /* One entry for each level of indirection eg [1] is type* */
	} xctab[] =
	{
	/*	typename		type			type *			type **			*/

		{"void",		gtm_void,		gtm_notfound,		gtm_notfound		},

		{"gtm_int_t",		gtm_int,		gtm_int_star,		gtm_notfound		},
		{"gtm_jboolean_t",	gtm_jboolean,		gtm_notfound,		gtm_notfound		},
		{"gtm_jint_t",		gtm_jint,		gtm_notfound,		gtm_notfound		},
		{"xc_int_t",		gtm_int,		gtm_int_star,		gtm_notfound		},
		{"int",			gtm_int,		gtm_notfound,		gtm_notfound		},

		{"gtm_uint_t",		gtm_uint,		gtm_uint_star,		gtm_notfound		},
		{"xc_uint_t",		gtm_uint,		gtm_uint_star,		gtm_notfound		},
		{"uint",		gtm_uint,		gtm_uint_star,		gtm_notfound		},

		{"gtm_long_t",		gtm_long,		gtm_long_star,		gtm_notfound		},
		{"gtm_jlong_t",		gtm_jlong,		gtm_notfound,		gtm_notfound		},
		{"xc_long_t",		gtm_long,		gtm_long_star,		gtm_notfound		},
		{"long",		gtm_long,		gtm_long_star,		gtm_notfound		},

		{"gtm_ulong_t",		gtm_ulong,		gtm_ulong_star,		gtm_notfound		},
		{"xc_ulong_t",		gtm_ulong,		gtm_ulong_star,		gtm_notfound		},
		{"ulong",		gtm_ulong,		gtm_ulong_star,		gtm_notfound		},

		{"gtm_status_t",	gtm_status,		gtm_notfound,		gtm_notfound		},
		{"xc_status_t",		gtm_status,		gtm_notfound,		gtm_notfound		},

		{"gtm_char_t",		gtm_notfound,		gtm_char_star,		gtm_char_starstar	},
		{"gtm_jstring_t",	gtm_jstring,		gtm_notfound,		gtm_notfound		},
		{"gtm_jbyte_array_t",	gtm_jbyte_array, 	gtm_notfound,		gtm_notfound		},
		{"gtm_jbig_decimal_t",	gtm_jbig_decimal,	gtm_notfound,		gtm_notfound		},
		{"xc_char_t",		gtm_notfound,		gtm_char_star,		gtm_char_starstar	},
		{"char",		gtm_notfound,		gtm_char_star,		gtm_char_starstar	},

		{"gtm_string_t",	gtm_notfound,		gtm_string_star,	gtm_notfound		},
		{"xc_string_t",		gtm_notfound,		gtm_string_star,	gtm_notfound		},
		{"string",		gtm_notfound,		gtm_string_star,	gtm_notfound		},

		{"gtm_float_t",		gtm_float,		gtm_float_star,		gtm_notfound		},
		{"gtm_jfloat_t",	gtm_jfloat,		gtm_notfound,		gtm_notfound		},
		{"xc_float_t",		gtm_float,		gtm_float_star,		gtm_notfound		},
		{"float",		gtm_float,		gtm_float_star,		gtm_notfound		},

		{"gtm_double_t",	gtm_double,		gtm_double_star,	gtm_notfound		},
		{"gtm_jdouble_t",	gtm_jdouble,		gtm_notfound,		gtm_notfound		},
		{"xc_double_t",		gtm_double,		gtm_double_star,	gtm_notfound		},
		{"double",		gtm_double,		gtm_double_star,	gtm_notfound		},

		{"gtm_pointertofunc_t", gtm_pointertofunc, 	gtm_pointertofunc_star,	gtm_notfound		},
		{"xc_pointertofunc_t", 	gtm_pointertofunc, 	gtm_pointertofunc_star,	gtm_notfound		}
	};
	char	*b = *c;
	char	*d;
	int	len, i, star_count;

	b = exttab_scan_space(b);
	d = scan_ident(b);
	if (!d)
		return gtm_notfound;
	len = (int)(d - b);
	for (i = 0 ; i < SIZEOF(xctab) / SIZEOF(xctab[0]) ; i++)
	{
		if ((0 == memcmp(xctab[i].nam, b, len)) && ('\0' ==  xctab[i].nam[len]))
		{
			/* got name */
			/* scan stars */
			for (star_count = 0; (MAXIMUM_STARS >= star_count); star_count++, d++)
			{
				d = exttab_scan_space(d);
				if ('*' != *d)
					break;
				star_found = TRUE;
			}
			assert(star_count <= MAXIMUM_STARS);
			*c = exttab_scan_space(d);
			return xctab[i].typ[star_count];
		}
	}
	return gtm_notfound;
}
Exemplo n.º 5
0
/* Note: need condition handler to clean-up allocated structures and close intput file in the event of an error */
struct extcall_package_list	*exttab_parse(mval *package)
{
	int		parameter_alloc_values[MAXIMUM_PARAMETERS], parameter_count, ret_pre_alloc_val, i, fclose_res;
	boolean_t	is_input[MAXIMUM_PARAMETERS], is_output[MAXIMUM_PARAMETERS], got_status;
	mstr		callnam, rtnnam;
	void_ptr_t	pakhandle;
	enum xc_types	ret_tok, parameter_types[MAXIMUM_PARAMETERS], pr;
	char		str_buffer[MAX_TABLINE_LEN], *tbp, *end;
	FILE		*ext_table_file_handle;
	struct extcall_package_list	*pak;
	struct extcall_entry_list	*entry_ptr;

	error_def(ERR_ZCRTENOTF);
	error_def(ERR_ZCALLTABLE);
	error_def(ERR_ZCUSRRTN);
	error_def(ERR_ZCCTENV);
	error_def(ERR_ZCCTOPN);
	error_def(ERR_ZCCTNULLF);
	error_def(ERR_ZCUNAVAIL);
	error_def(ERR_ZCENTNAME);
	error_def(ERR_ZCCOLON);
	error_def(ERR_ZCRTNTYP);
	error_def(ERR_ZCRCALLNAME);
	error_def(ERR_ZCUNTYPE);
	error_def(ERR_ZCMLTSTATUS);
	error_def(ERR_ZCRPARMNAME);
	error_def(ERR_ZCPREALLVALPAR);
	error_def(ERR_ZCPREALLVALINV);

	/* First, construct package name environment variable */
	memcpy(str_buffer, PACKAGE_ENV_PREFIX, sizeof(PACKAGE_ENV_PREFIX));
	tbp = &str_buffer[sizeof(PACKAGE_ENV_PREFIX) - 1];
	if (package->str.len)
	{
		/* guaranteed by compiler */
		assert(package->str.len < MAX_NAME_LENGTH - sizeof(PACKAGE_ENV_PREFIX) - 1);
		*tbp++ = '_';
		memcpy(tbp, package->str.addr, package->str.len);
		tbp += package->str.len;
	}
	*tbp = 0;
	/* Now we have the environment name, lookup file name */
	ext_table_file_name = GETENV(str_buffer);
	if (NULL == ext_table_file_name)
	{
		/* Environment variable for the package not found */
		rts_error(VARLSTCNT(4) ERR_ZCCTENV, 2, LEN_AND_STR(str_buffer));
	}
	ext_table_file_handle = Fopen(ext_table_file_name, "r");
	if (NULL == ext_table_file_handle)
	{
		/* Package's external call table could not be found */
		rts_error(VARLSTCNT(4) ERR_ZCCTOPN, 2, LEN_AND_STR(ext_table_file_name));
	}
	ext_source_line_num = 0;
	/* pick-up name of shareable library */
	tbp = read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle);
	if (NULL == tbp)
	{
		/* External call table is a null file */
		rts_error(VARLSTCNT(4) ERR_ZCCTNULLF, 2, package->str.len, package->str.addr);
	}
	pakhandle = fgn_getpak(str_buffer, INFO);
	if (NULL == pakhandle)
	{
		/* Unable to obtain handle to the shared library */
		rts_error(VARLSTCNT(4) ERR_ZCUNAVAIL, 2, package->str.len, package->str.addr);
	}
	pak = get_memory(sizeof(*pak));
	pak->first_entry = 0;
	put_mstr(&package->str, &pak->package_name);
	pak->package_handle = pakhandle;
	/* At this point, we have a valid package, pointed to by pak */
#ifdef DEBUG_EXTCALL
	FPRINTF(stderr, "GT.M external call opened package name: %s\n", pak->package_name.addr);
#endif
	for (;;)
	{
		star_found = FALSE;
		tbp = read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle);
		if (NULL == tbp)
			break;
		tbp = scan_space(str_buffer);
		/* empty line? */
		if (!*tbp)
			continue;
		/* No, must be entryref */
		end = scan_ident(tbp);
		if (!end)
			ext_stx_error(ERR_ZCENTNAME, ext_table_file_name);
		if ('^' == *end)
		{
			end++;
			end = scan_ident(end);
			if (!end)
				ext_stx_error(ERR_ZCENTNAME, ext_table_file_name);
		}
		rtnnam.addr = tbp;
		rtnnam.len = INTCAST(end - tbp);
		tbp = scan_space(end);
		if (':' != *tbp++)
			ext_stx_error(ERR_ZCCOLON, ext_table_file_name);
		/* get return type */
		ret_tok = scan_keyword(&tbp);
		/* check for legal return type */
		switch (ret_tok)
		{
			case xc_status:
			case xc_void:
			case xc_int:
			case xc_uint:
			case xc_long:
			case xc_ulong:
			case xc_char_star:
			case xc_float_star:
			case xc_string_star:
			case xc_int_star:
			case xc_uint_star:
			case xc_long_star:
			case xc_ulong_star:
			case xc_double_star:
			case xc_char_starstar:
			case xc_pointertofunc:
			case xc_pointertofunc_star:
				break;
			default:
				ext_stx_error(ERR_ZCRTNTYP, ext_table_file_name);
		}
		got_status = (ret_tok == xc_status);
		/*  get call name */
		if ('[' == *tbp)
		{
			if (star_found)
				ret_pre_alloc_val = scan_array_bound(&tbp,ret_tok);
			else
				ext_stx_error(ERR_ZCPREALLVALPAR, ext_table_file_name);
			/* We should allow the pre-allocated value upto to the maximum string size (MAX_STRLEN) plus 1 for the
			 * extra terminating NULL. Negative values would have been caught by scan_array_bound() above */
			if (ret_pre_alloc_val > MAX_STRLEN + 1)
				ext_stx_error(ERR_ZCPREALLVALINV, ext_table_file_name);
		} else
			ret_pre_alloc_val = -1;
		end = scan_ident(tbp);
		if (!end)
			ext_stx_error(ERR_ZCRCALLNAME, ext_table_file_name);
		callnam.addr = tbp;
		callnam.len = INTCAST(end - tbp);
		tbp = scan_space(end);
		tbp = scan_space(tbp);
		for (parameter_count = 0;(MAXIMUM_PARAMETERS > parameter_count) && (')' != *tbp); parameter_count++)
		{
			star_found = FALSE;
			/* must have comma if this is not the first parameter, otherwise '(' */
			if (((0 == parameter_count)?'(':',') != *tbp++)
				ext_stx_error(ERR_ZCRPARMNAME, ext_table_file_name);
			tbp = scan_space(tbp);
			/* special case: () is ok */
			if ((0 == parameter_count) && (*tbp == ')'))
				break;
			/* looking for an I, an O or an IO */
			is_input[parameter_count] = is_output[parameter_count] = FALSE;
			if ('I' == *tbp)
			{
				is_input[parameter_count] = TRUE;
				tbp++;
			}
			if ('O' == *tbp)
			{
				is_output[parameter_count] = TRUE;
				tbp++;
			}
			if (((FALSE == is_input[parameter_count]) && (FALSE == is_output[parameter_count]))
			    ||(':' != *tbp++))
				ext_stx_error(ERR_ZCRCALLNAME, ext_table_file_name);
			/* scanned colon--now get type */
			pr = scan_keyword(&tbp);
			if (xc_notfound == pr)
				ext_stx_error(ERR_ZCUNTYPE, ext_table_file_name);
			if (xc_status == pr)
			{
				/* Only one type "status" allowed per call */
				if (got_status)
					ext_stx_error(ERR_ZCMLTSTATUS, ext_table_file_name);
				else
					got_status = TRUE;
			}
			parameter_types[parameter_count] = pr;
			if ('[' == *tbp)
			{
				if (star_found && !is_input[parameter_count])
					parameter_alloc_values[parameter_count] = scan_array_bound(&tbp, pr);
				else
					ext_stx_error(ERR_ZCPREALLVALPAR, ext_table_file_name);
				/* We should allow the pre-allocated value upto to the maximum string size (MAX_STRLEN) plus 1 for
				 * the extra terminating NULL. Negative values would have been caught by scan_array_bound() above */
				if (parameter_alloc_values[parameter_count] > MAX_STRLEN + 1)
					ext_stx_error(ERR_ZCPREALLVALINV, ext_table_file_name);
			} else
				parameter_alloc_values[parameter_count] = -1;
			tbp = scan_space(tbp);
		}
		entry_ptr = get_memory(sizeof(*entry_ptr));
		entry_ptr->next_entry = pak->first_entry;
		pak->first_entry = entry_ptr;
		entry_ptr->return_type = ret_tok;
		entry_ptr->ret_pre_alloc_val = ret_pre_alloc_val;
		entry_ptr->argcnt = parameter_count;
		entry_ptr->input_mask = array_to_mask(is_input, parameter_count);
		entry_ptr->output_mask = array_to_mask(is_output, parameter_count);
		entry_ptr->parms = get_memory(parameter_count * sizeof(entry_ptr->parms[0]));
		entry_ptr->param_pre_alloc_size = get_memory(parameter_count * sizeof(intszofptr_t));
		entry_ptr->parmblk_size = (SIZEOF(void *) * parameter_count) + SIZEOF(intszofptr_t);
		for (i = 0 ;  i < parameter_count ;  i++)
		{
			entry_ptr->parms[i] = parameter_types[i];
			entry_ptr->parmblk_size += parm_space_needed[parameter_types[i]];
			entry_ptr->param_pre_alloc_size[i] = parameter_alloc_values[i];
		}
		put_mstr(&rtnnam, &entry_ptr->entry_name);
		put_mstr(&callnam, &entry_ptr->call_name);

		/* the reason for passing INFO severity is that PROFILE has several routines listed in
		 * the external call table that are not in the shared library. PROFILE folks would
		 * rather see info/warning messages for such routines at shared library open time,
		 * than error out. These unimplemented routines, they say were not being called from
		 * the application and wouldn't cause any application failures. If we fail to open
		 * the shared libary, or we fail to locate a routine that is called from the
		 * application, we issue rts_error message (in extab_parse.c) */
		entry_ptr->fcn = fgn_getrtn(pak->package_handle, &entry_ptr->call_name, INFO);
#ifdef DEBUG_EXTCALL
		FPRINTF(stderr, "   package entry point: %s, address: %x\n", entry_ptr->entry_name.addr, entry_ptr->fcn);
#endif
	}
	FCLOSE(ext_table_file_handle, fclose_res);
	return pak;
}
Exemplo n.º 6
0
int scan(scan_info *info)
{
    int err = 0;
    int sym_code = SVO_NONE;
    const char **in = &(info->scanner);
    char tmp[SCAN_SIZE+1];

    while((**in != 0) && (isspace(**in))) (*in)++;

    if(isalpha(**in)){

        scan_ident(in,info->token,SCAN_SIZE);

        sym_code = token_to_id(info->token);
        if(sym_code == SVO_NONE) sym_code = SVO_IDENT;

    } else if(isdigit(**in)){

        scan_number(in,info->token,SCAN_SIZE);
        sym_code = SVO_NUMBER;
    } else{
        switch(**in){
        case '#':
            sym_code = SVO_END;
            break;
        case '>':
        case '<':
        case '=':
        case '!':

            scan_comp(in,info->token,SCAN_SIZE);
            break;

        case '"':

            err = scan_string(info,SCAN_SIZE);

            if(err != SHE_NO_ERROR){
                parse_vars_in_string(info->token,tmp,SCAN_SIZE);
                strncpy(info->token,tmp,SCAN_SIZE);
                info->token[SCAN_SIZE] = 0;
            }

            sym_code = SVO_DQ_STRING;
            break;
        case '\'':

            sym_code = SVO_SQ_STRING;
            err =scan_string(info,SCAN_SIZE);
            break;
        case 0:

            *(info->token) = 0;
            sym_code = SVO_END;
            break;
        default:
            info->token[0] = **in;
            info->token[1] = 0;
            (*in)++;
            break;

        }
        if(sym_code == SVO_NONE) sym_code = token_to_id(info->token);

    }

    info->sym_code = sym_code;

    return err;
}
Exemplo n.º 7
0
int
luna_scan(luna_lexer_t *self) {
  int c;
  token(ILLEGAL);

  // deferred outdents
  if (self->outdents) return outdent(self);

  // scan
  scan:
  switch (c = next) {
    case ' ':
    case '\t': goto scan;
    case '(': return token(LPAREN);
    case ')': return token(RPAREN);
    case '{': return token(LBRACE);
    case '}': return token(RBRACE);
    case '[': return token(LBRACK);
    case ']': return token(RBRACK);
    case ',': return token(COMMA);
    case '.': return token(OP_DOT);
    case '%': return token(OP_MOD);
    case '^': return token(OP_BIT_XOR);
    case '~': return token(OP_BIT_NOT);
    case '?': return token(QMARK);
    case ':': return token(COLON);
    case '@':
      self->tok.value.as_string = "self";
      return token(ID);
    case '+':
      switch (next) {
        case '+': return token(OP_INCR);
        case '=': return token(OP_PLUS_ASSIGN);
        default: return undo, token(OP_PLUS);
      }
    case '-':
      switch (next) {
        case '-': return token(OP_DECR);
        case '=': return token(OP_MINUS_ASSIGN);
        default: return undo, token(OP_MINUS);
      }
    case '*':
      switch (next) {
        case '=': return token(OP_MUL_ASSIGN);
        case '*': return token(OP_POW);
        default: return undo, token(OP_MUL);
      }
    case '/':
      return '=' == next
        ? token(OP_DIV_ASSIGN)
        : (undo, token(OP_DIV));
    case '!':
      return '=' == next
        ? token(OP_NEQ)
        : (undo, token(OP_NOT));
    case '=':
      return '=' == next
        ? token(OP_EQ)
        : (undo, token(OP_ASSIGN));
    case '&':
      switch (next) {
        case '&':
          return '=' == next
            ? token(OP_AND_ASSIGN)
            : (undo, token(OP_AND));
        default:
          return undo, token(OP_BIT_AND);
      }
    case '|':
      switch (next) {
        case '|':
          return '=' == next
            ? token(OP_OR_ASSIGN)
            : (undo, token(OP_OR));
        default:
          return undo, token(OP_BIT_OR);
      }
    case '<':
      switch (next) {
        case '=': return token(OP_LTE);
        case '<': return token(OP_BIT_SHL);
        default: return undo, token(OP_LT);
      }
    case '>':
      switch (next) {
        case '=': return token(OP_GTE);
        case '>': return token(OP_BIT_SHR);
        default: return undo, token(OP_GT);
      }
    case '#':
      while ((c = next) != '\n' && c) ; undo;
      goto scan;
    case '\n':
      return scan_newline(self);
    case '"':
    case '\'':
      return scan_string(self, c);
    case 0:
      if (self->indents) {
        --self->indents;
        return token(OUTDENT);
      }
      token(EOS);
      return 0;
    default:
      if (isalpha(c) || '_' == c) return scan_ident(self, c);
      if (isdigit(c) || '.' == c) return scan_number(self, c);
      error("illegal character");
      return 0;
  }
}