Exemple #1
0
void 
o_doscanf (void)
{
	struct operand o;
	struct operand o_sv[64];
	char	format[SZ_LINE];
	int	nargs, i;

	/* Get number of arguments. */
	o = popop();
	nargs = o.o_val.v_i;

	/* Get scan format.  Unfortunately the way the parser works this
	 * is the last operand on the stack.  We need to pop and save the
	 * first nargs-1 operands and restore them when done.
	 */
	for (i=0;  i < nargs-1;  i++)
	    o_sv[i] = popop();

	o = popop();
	if ((o.o_type & OT_BASIC) != OT_STRING)
	    cl_error (E_UERR, "scanf: bad format string\n");
	strcpy (format, o.o_val.v_s);

	for (--i;  i >= 0;  i--)
	    pushop (&o_sv[i]);

	/* Do the scan. */
	cl_scanf (format, nargs-2, "stdin");
}
Exemple #2
0
/* <value to be concatenated onto named parameter> .
 */
void 
o_catassign (memel *argp)
{
	char	*pname = (char *) argp;
	char	*pk, *t, *p, *f;
	char	s1[1024+1];
	struct	operand o1, o2;
	struct	param *pp;

	breakout (pname, &pk, &t, &p, &f);
	pp = paramsrch (pk, t, p);
	paramget (pp, *f);

	/* If param value is undefined merely assign into it, otherwise
	 * concatenate operand to current value.
	 */
	o1 = popop();
	if (!opundef(&o1)) {
	    /* Must copy string value off of operand stack or the next
	     * pushop below will reuse the space!
	     */
	    o2 = popop();
	    strncpy (s1, o2.o_val.v_s, 1024);
	    s1[1024] = EOS;
	    o2.o_val.v_s = s1;

	    pushop (&o1);
	    pushop (&o2);
	    binop (OP_CONCAT);
	}

	paramset (pp, *f);
	pp->p_flags |= P_SET;
}
Exemple #3
0
/* CL_VOCSTOP --  Stop the VO Client interface.
 */
void
cl_vocstop (void)
{
    register struct pfile *pfp;
    struct  operand o;
    int     n, status;

    if (VOClient_initialized == 1) {
	c_xwhen (X_IPC, old_onipc, &old_onipc);

        pfp = newtask->t_pfp;
        if ((n = nargs (pfp)) > 1) {
            cl_error (E_UERR, e_posargs, "vocstop");
	    return;

        } else if (n < 1) {
            voc_closeVOClient (1);

	} else {
            pushbparams (pfp->pf_pp);
            popop();                    /* discard fake name.           */
            opcast (OT_INT);
            o = popop();                /* get ltask                    */
            voc_closeVOClient (o.o_val.v_i);
	}
	VOClient_initialized = 0;
    }
}
Exemple #4
0
/* CL_VOCINIT --  Initialize the VO Client interface.
 */
void
cl_vocinit (void)
{
    register struct pfile *pfp;
    struct  operand o;
    int     n, status;

    if (VOClient_initialized == 0) {

	c_xwhen (X_IPC, voc_onipc, &old_onipc);

        pfp = newtask->t_pfp;
        if ((n = nargs (pfp)) > 1) {
            cl_error (E_UERR, e_posargs, "vocinit");
	    return;

        } else if (n < 1) {
            status = voc_initVOClient (envget("vo_runid"));

	} else {
            pushbparams (pfp->pf_pp);
            popop();                    /* discard fake name.           */
            opcast (OT_STRING);
            o = popop();                /* get ltask                    */

            status = voc_initVOClient (o.o_val.v_s);
        }

	if (status) {
            cl_error (E_UERR, "Can't init VOClient", "vocinit");
	} else
	    VOClient_initialized = 1;
    }
}
Exemple #5
0
/* <string operand> .
 * if argument to which we are assigning is a simple string or filename (or
 *   list, since assigning to a list sets a filename too), set it to o_val.v_s,
 * else use o_val.v_s as the name of a parameter and use its value as the name
 *   of the variable, that is, do an indirect through o_val.v_s.
 * compiled when the parser sees a simple identifier, not in an expression.
 *   this avoids quotes around simple strings and filenames.
 * if the parameter is to be fake, make it type string and do not do the
 *   indirection.
 */
void 
o_indirabsset (memel *argp)
{
	char	*argname = (char *) argp;
	char	*pk, *t, *p, *f;
	struct	pfile *pfp;
	struct	param *pp;
	int	type, string_len;

	pfp = newtask->t_pfp;
	if (pfp->pf_flags & PF_FAKE) {
	    struct	operand o;
	    o = popop();
	    string_len = strlen (o.o_val.v_s);
	    pp = newfakeparam (pfp, argname, 0, OT_STRING, string_len);
	    f = argname;
	    *f = FN_NULL;
	    pushop (&o);

	} else {
	    breakout (argname, &pk, &t, &p, &f);
	    if (*pk)
		cl_error (E_UERR, e_simplep, p);
	    pp = ppfind (pfp, t, p, 0, NO);
	    if (pp == NULL)
		cl_error (E_UERR, e_pnonexist, p);
	    if ((XINT)pp == ERR)
		cl_error (E_UERR, e_pambig, p, pfp->pf_ltp->lt_lname);
	}

	/* lone identifiers are treated as strings, rather than variables,
	 * if the corresponding parameter is a simple string, filename or list.
	 * note that fakeparams are made as strings.
	 */
	type = pp->p_type;
	if (type & (PT_FILNAM|PT_LIST|PT_PSET)) {
	    struct operand o;
	    o = popop();
	    pushop (&o);
	} else if ((type & OT_BASIC) != OT_STRING ||
	    type & (PT_STRUCT|PT_IMCUR|PT_GCUR|PT_UKEY)) {

	    opindir(); /* replace top op with value of o_val.v_s */
	}

	paramset (pp, *f);
	if (pp->p_type & PT_PSET)
	    psetreload (pfp, pp);
	pp->p_flags |= P_CLSET;
}
Exemple #6
0
/* .
 * given the name of a parameter, print it on t_out, the task pipe channel.
 */
void 
o_inspect (memel *argp)
{
	char *pname = (char *) argp;
	char *pk, *t, *p, *f;
	struct param *pp;
	struct operand o;

	breakout (pname, &pk, &t, &p, &f);
	pp = paramsrch (pk, t, p);

	if (*f == FN_NULL && (pp->p_type & PT_LIST)) {
	    /* Hitting EOF from a list is ok during an inspect stmt so
	     * avoid using paramget() with its EOF error.
	     * readlist() may set P_LEOF.
	     */
	    o = readlist (pp);
	    if ((pp->p_flags & P_LEOF) || inrange (pp, &o))
		pushop (&o);
	    else
		query (pp);
	} else
	    validparamget (pp, *f);

	o = popop();

	if (cldebug && (o.o_type & OT_BASIC) == OT_STRING)
	    eprintf ("Inspect--%s\n", o.o_val.v_s);

	prop (&o);
	tprintf ("\n");
}
Exemple #7
0
/* <name of file to be used as stderr> .
 * redirect everything, including the stderr channel.
 */
void 
o_allredir (void)
{
	struct	operand o;
	char	*fname, *mode;

	opcast (OT_STRING);
	o = popop();
	fname = (o.o_val.v_s);

	if (newtask->t_flags & T_FOREIGN &&
	    newtask->t_stdout == stdout && newtask->t_stderr == stderr) {

	    /* If foreign task and i/o has not already been redirected by
	     * the parent, let ZOSCMD open the spool file.
	     */
	    newtask->ft_out = newtask->ft_err = comdstr (fname);

	} else {
	    mode = (newtask->t_flags & T_STDOUTB) ? "wb" : "w";

	    if ((newtask->t_stderr = fopen (fname, mode)) == NULL)
		cl_error (E_UERR, e_wopen, fname);

	    newtask->t_stdout = newtask->t_stderr;
	    newtask->t_flags |= (T_MYOUT|T_MYERR);
	}
}
Exemple #8
0
/* <new value for argument at command position *argp> .
 */
void 
o_posargset (memel *argp)
{
	int	pos = (int) *argp;
	struct	pfile *pfp;
	struct	param *pp;
	struct	operand o;
	int	string_len=0;

	pfp = newtask->t_pfp;

	if (pos < 0) {
	    /* Lone comma in arg list, merely bump nargs counter */
	    pfp->pf_n++;
	    return;
	}

	if (pfp->pf_flags & PF_FAKE) {
	    o = popop();
	    if ((o.o_type & OT_BASIC) == OT_STRING)
		string_len = strlen (o.o_val.v_s);
	    pp = newfakeparam (pfp, (char *) NULL, pos, o.o_type, string_len);
	    pushop (&o);
	} else {
	    pp = paramfind (pfp, (char *) NULL, pos, NO);
	    if (pp == NULL)
		cl_error (E_UERR, e_posargs, newtask->t_ltp->lt_lname);
	}

	paramset (pp, FN_NULL);
	pfp->pf_n++;
	pp->p_flags |= P_CLSET;
}
Exemple #9
0
/* <name of file to be used as stdout> .
 */
void 
o_redir (void)
{
	struct	operand o;
	char	*fname, *mode;

	opcast (OT_STRING);
	o = popop();
	fname = (o.o_val.v_s);

	if (newtask->t_flags & T_FOREIGN && newtask->t_stdout == stdout) {
	    /* If foreign task let ZOSCMD open the spool file.
	     */
	    newtask->ft_out = comdstr (fname);

	} else if (strcmp (fname, IPCOUT) == 0) {
	    /* Redirect the task stdout via IPC to a subprocess. */
	    newtask->t_stdout = newtask->t_out;
	    newtask->t_flags |= T_IPCIO;

	} else {
	    mode = (newtask->t_flags & T_STDOUTB) ? "wb" : "w";

	    if ((newtask->t_stdout = fopen (fname, mode)) == NULL)
		cl_error (E_UERR, e_wopen, fname);

	    newtask->t_flags |= T_MYOUT;
	}
}
Exemple #10
0
/* <paramn> ... <param1> <source> <n> .
 * Do the fscan function.  First op on stack is number of string ops to
 * follow.  Next one is the name of the source parameter, rest are names of
 * destination params.
 */
void 
o_dofscan (void)
{
	struct operand o;

	o = popop();
	cl_scan (o.o_val.v_i - 1, "");
}
Exemple #11
0
void 
o_dofscanf (void)
{
	struct operand o, o_sv[64];
	char	format[SZ_LINE];
	char	pname[SZ_FNAME];
	int	nargs, i;

	/* Get number of arguments. */
	o = popop();
	nargs = o.o_val.v_i;

	/* Get scan format and input parameter name.  The arguments on the
	 * stack are pushed in the order input param name, format string,
	 * and then the output arguments.
	 */

	/* Get output arguments. */
	for (i=0;  i < nargs-2;  i++)
	    o_sv[i] = popop();

	/* Get format string. */
	o = popop();
	if ((o.o_type & OT_BASIC) != OT_STRING)
	    cl_error (E_UERR, "fscanf: bad format string\n");
	strcpy (format, o.o_val.v_s);

	/* Get parameter name. */
	o = popop();
	if ((o.o_type & OT_BASIC) != OT_STRING)
	    cl_error (E_UERR, "fscanf: bad input parameter specification\n");
	strcpy (pname, o.o_val.v_s);

	/* Restore the output argument operands. */
	for (--i;  i >= 0;  i--)
	    pushop (&o_sv[i]);

	/* Restore the input parameter name operand. */
	o.o_type = OT_STRING;
	o.o_val.v_s = pname;
	pushop (&o);

	/* Do the scan. */
	cl_scanf (format, nargs-2, "");
}
Exemple #12
0
/* <value to be printed> .
 * used to print an operand on the stack. not to be confused with doprint.
 */
void 
o_immed (void)
{
	struct operand o;

	o = popop();
	prop (&o);
	tprintf ("\n");
}
Exemple #13
0
/* <truth value> .
 * branch if false (or INDEF).
 */
void 
o_biff (memel *argp)
{
	extern XINT pc;
	struct operand o;

	opcast (OT_BOOL);
	o = popop();
	if (!o.o_val.v_i || opindef (&o))
	    pc += (int)*argp;
}
Exemple #14
0
/* <value to be divided into named parameter> .
 */
void 
o_divassign (memel *argp)
{
	char	*pname = (char *) argp;
	char	*pk, *t, *p, *f;
	struct	param *pp;
	struct	operand o1, o2;

	breakout (pname, &pk, &t, &p, &f);
	pp = paramsrch (pk, t, p);

	validparamget (pp, *f);		/* get param value on stack	*/
	o1 = popop();			/* swap operands		*/
	o2 = popop();
	pushop (&o1);
	pushop (&o2);
	binop (OP_DIV);			/* perform the division		*/
	paramset (pp, *f);
	pp->p_flags |= P_SET;
}
Exemple #15
0
/* <increment to be added to named parameter> .
 */
void 
o_addassign (memel *argp)
{
	/* order of operands will be incorrect.
	 * strictly speaking, only strings are not commutative but we need
	 * to pop both operands anyway to check.
	 */
	char *pname = (char *) argp;
	char *pk, *t, *p, *f;
	struct param *pp;
	struct operand o1, o2;

	breakout (pname, &pk, &t, &p, &f);
	pp = paramsrch (pk, t, p);
	validparamget (pp, *f);
	o1 = popop();
	o2 = popop();

	if ((o2.o_type & OT_BASIC) == OT_STRING) {
	    /* copy o2 onto dictionary to avoid overwriting it on stack
	     * when o1 is pushed. we can get by with not worrying about o1
	     * as long as whatever code copies the string works when the
	     * strings overlap.
	     */
	    XINT oldtopd = topd;
	    char *s2 = memneed (btoi (strlen (o2.o_val.v_s) + 1));
	    strcpy (s2, o2.o_val.v_s);
	    o2.o_val.v_s = s2;
	    pushop (&o1);
	    pushop (&o2);
	    topd = oldtopd;		/* discard temp string area	*/

	} else {
	    pushop (&o1);
	    pushop (&o2);
	}

	binop (OP_ADD);
	paramset (pp, *f);
	pp->p_flags |= P_SET;
}
Exemple #16
0
/* [<op1> <op2> ... <opn>] <nops> . <result>
 * intrinsic functions, like sin, cos, mod, etc.
 * argp is the name of the function to run and the top operand (we guarantee
 * at least one) is the number of remaining operands to be used.
 * all the defines are in operand.h. the function names and running them is
 * done by intrfunc() in gram.c.
 */
void 
o_intrinsic (memel *argp)
{
	char *funcname = (char *) argp;
	struct operand o;
	int nargs;

	o = popop();
	nargs = o.o_val.v_i;

	intrfunc (funcname, nargs);
}
Exemple #17
0
/* <string operand> .
 * if argument to which we are assigning is a simple string or filename (or
 *   list, since assigning to a list sets a filename too), set it to o_val.v_s,
 * else use o_val.v_s as the name of a parameter and use its value as the name
 *   of the variable, that is, do an indirect through o_val.v_s.
 * compiled when the parser sees a simple identifier, not in an expression.
 *   this avoids quotes around simple strings and filenames.
 */
void 
o_indirposset (memel *argp)
{
	int pos = (int) *argp;
	struct pfile *pfp;
	struct param *pp;
	int type, string_len;

	pfp = newtask->t_pfp;
	if (pfp->pf_flags & PF_FAKE) {
	    struct	operand o;
	    o = popop();
	    string_len = strlen (o.o_val.v_s);
	    pp = newfakeparam (pfp, (char *) NULL, pos, OT_STRING, string_len);
	    pushop (&o);
	} else {
	    pp = paramfind (pfp, (char *) NULL, pos, NO);
	    if (pp == NULL)
		cl_error (E_UERR, e_posargs, newtask->t_ltp->lt_lname);
	}

	/* lone identifiers are treated as strings, rather than variables,
	 * if the corresponding parameter is a simple string, filename or list.
	 * note that fakeparams are made as strings.
	 */
	type = pp->p_type;
	if (type & (PT_FILNAM|PT_LIST|PT_PSET)) {
	    struct operand o;
	    o = popop();
	    pushop (&o);
	} else if ((type & OT_BASIC) != OT_STRING ||
	    type & (PT_STRUCT|PT_IMCUR|PT_GCUR|PT_UKEY)) {

	    opindir(); /* replace top op with value of o_val.v_s */
	}

	paramset (pp, FN_NULL);
	pfp->pf_n++;
	pp->p_flags |= P_CLSET;
}
Exemple #18
0
/*
**  VALOF -- compute value of expression
**
**	This is the real expression processor.  It handles sequencing
**	and precedence.
**
**	Parameters:
**		terminator -- the symbol which should terminate
**			the expression.
**
**	Returns:
**		The value of the expression.
**
**	Side Effects:
**		Gobbles input.
**
**	Requires:
**		exprfind -- to read operands.
**		opfind -- to read operators.
**		exp_op -- to perform operations.
**
**	Called By:
**		expr
**
**	Diagnostics:
**		Extra Parenthesis found: assumed typo
**			An unmatched right parenthesis was read.
**			It was thrown away.
**		Insufficient parenthesis found: assumed zero.
**			An unmatched left parenthesis was left
**			in the operator stack at the end of the
**			expression.  The value zero was taken
**			for the expression.
**
**	Syserrs:
**		none
*/
int
valof(int terminator)
{
	register int	number;
	register int	operator;

	pushop(SEPERATOR);		/* initialize the stack */
	for(;;) {
		number = exprfind();
		if (ExprError) 
			return(0);
		operator = opfind();
		if (ExprError)
			return(0);

		if (operator == RIGHTP || operator == END)
			break;

		/* Do all previous operations with a higher precedence */
		while (ExprPrec[operator] <= ExprPrec[ExprOptr[-1]])	
			number = exp_op(popop(), popnum(), number);
		pushop(operator);
		pushnum(number);
	}
	if (operator != terminator)		/* ExprError in operators */
		if (operator == RIGHTP)
			printf("Extra parenthesis found: assumed typo.\n");
		else {
			ExprError = TRUE;
			printf("Insufficient parenthesis found: Assumed zero.\n");
			return(0);
		}
	/* Empty stack for this call of valof */
	while ((operator = popop()) != SEPERATOR)
		number = exp_op(operator, popnum(), number);

	return(number);
}
Exemple #19
0
/* Push an index value onto the control stack for later use
 * when the parameter is accessed.
 */
void 
o_pushindex (int *mode)
{
	struct operand op;

	 if (cldebug)
	    printf ("PUSHINDEX: mode=%d loopset=%d\n", *mode, imloopset);

	if (*mode == 0) {	/* Normal array index reference. */
	    opcast(OT_INT);
	    op = popop();
	    push (op.o_val.v_i);
	} else if (*mode == -1  ||  imloopset) {
	    /* Array reference in implicit loop. */
	    push (oarr_curr[i_oarr]);
	    i_oarr++;
	    if (i_oarr >= n_oarr)
		i_oarr = 0;
	} else {
	    /* This is the first array reference in an implicit loop.
	     * It must initialize the loop parameters.  The argument
	     * is an offset to the initialization info.
	     */
	    int stk;

	    stk = pc + *mode;

	    n_oarr = stack[stk++];
	    for (i_oarr=0; i_oarr<n_oarr; i_oarr++) {
		oarr_beg[i_oarr] = stack[stk++];
		oarr_curr[i_oarr] = oarr_beg[i_oarr];
		oarr_end[i_oarr] = stack[stk++];
	    }
	    /* Set flag so that we don't do this again. */
	    imloopset++;

	    /* And we still have to push a value. */
	    push (oarr_curr[0]);
	    i_oarr = 1;
	    if (i_oarr >= n_oarr)
		i_oarr = 0;
	}

	/* Increment counter of number of indexes pushed.
	 */
	n_indexes++;
}
Exemple #20
0
/* GSREDIR -- Graphics stream redirection.
 * <filename> .
 */
void 
o_gsredir (memel *argp)
{
	register char	*ip;
	register FILE	*fp;
	char	*streams = (char *)argp;
	struct	operand o;
	char	*fname;
	int	count;

	/* Get the filename.
	 */
	opcast (OT_STRING);
	o = popop();
	fname = o.o_val.v_s;

	/* Scan the redir token to determine the file access mode, e.g., if
	 * ">G", create a new file, and if ">>G", append to a file.
	 */
	for (count=0, ip=streams;  *ip;  ip++)
	    if (*ip == '>')
		count++;

	if ((fp = fopen (fname, count > 1 ? "ab" : "wb")) == NULL)
	    cl_error (E_UERR, e_wopen, fname);

	/* The first string operand on the stack is some combination of the
	 * characters GIP, listing the streams (stdgraph, stdimage, stdplot)
	 * to be redirected to the named file.  The lexical analyzer guarantees
	 * that we will not be called unless the string consists of some
	 * combination of the characters >GIP, hence error checking for other
	 * char, no chars, etc., is not needed.
	 */
	for (ip=streams;  *ip;  ip++)
	    if (*ip == 'G') {
		newtask->t_flags |= T_MYSTDGRAPH;
		newtask->t_stdgraph = fp;
	    } else if (*ip == 'I') {
		newtask->t_flags |= T_MYSTDIMAGE;
		newtask->t_stdimage = fp;
	    } else if (*ip == 'P') {
		newtask->t_flags |= T_MYSTDPLOT;
		newtask->t_stdplot = fp;
	    }
}
Exemple #21
0
/* <new value for named argument> .
 * Assign the top operand to the named parameter.  Also, make the type of the
 * fake parameter the same as the type of the operand.
 */
void 
o_absargset (memel *argp)
{
	char	*argname = (char *) argp;
	char	*pk, *t, *p, *f;
	struct	pfile *pfp;
	struct	param *pp;

	pfp = newtask->t_pfp;
	if (pfp->pf_flags & PF_FAKE) {
	    /* use full argname and always assign to value field.
	     */
	    struct operand o;
	    int	string_len=0;
	    o = popop();
	    if ((o.o_type & OT_BASIC) == OT_STRING)
		string_len = strlen (o.o_val.v_s);
	    pp = newfakeparam (pfp, argname, 0, o.o_type, string_len);
	    pushop (&o);
	    f = argname;
	    *f = FN_NULL;

	} else {
	    breakout (argname, &pk, &t, &p, &f);
	    if (*pk)
		cl_error (E_UERR, e_simplep, p);
	    pp = ppfind (pfp, t, p, 0, NO);
	    if (pp == NULL)
		cl_error (E_UERR, e_pnonexist, p);
	    if ((XINT)pp == ERR)
		cl_error (E_UERR, e_pambig, p, pfp->pf_ltp->lt_lname);
	}

	paramset (pp, *f);
	if (pp->p_type & PT_PSET)
	    psetreload (pfp, pp);
	pp->p_flags |= P_CLSET;
}
Exemple #22
0
int main()
{	struct node*sv=NULL;
	struct node2*sop=NULL;
	int n,n1,n2,result,i;
	char thisop;
	//scanf("%d",&n);
	char a[100];
	
	scanf("%s",a);
	i=0;
	for(;a[i]!='\0';i++)
	{	if(isdigit(a[i]))
		{	sv=pushval(sv,a[i]);
		}
		else if(a[i]=='+')
		{	if(sop!=NULL)
			{	n1=popval(&sv);
				n2=popval(&sv);
				result=n2+n1;
				//editing required
				sv=pushval(sv,result);
			}	
			else
			{	sop=pushop(sop,a[i]);
			}
		}
	}
	while(sop!=NULL)
	{	thisop=popop(&sop);
			n1=popval(&sv);
				n2=popval(&sv);
				result=n2+n1;//editing required
				sv=pushval(sv,result);
	}
	result=popval(&sv);
	printf("%d",result);
	
}
Exemple #23
0
/* <name of file to be used as stdin> .
 */
void 
o_redirin (void)
{
	struct	operand o;
	char	*fname, *mode;

	opcast (OT_STRING);
	o = popop();
	fname = (o.o_val.v_s);

	if (newtask->t_flags & T_FOREIGN && newtask->t_stdin == stdin) {
	    /* If foreign task let ZOSCMD open the command file.
	     */
	    newtask->ft_in = comdstr (fname);
	} else {
	    mode = (newtask->t_flags & T_STDINB) ? "rb" : "r";

	    if ((newtask->t_stdin = fopen (fname, mode)) == NULL)
		cl_error (E_UERR, e_ropen, fname);

	    newtask->t_flags |= T_MYIN;
	}
}
Exemple #24
0
/* <name of file to be appended> .
 */
void 
o_append (void)
{
	struct	operand o;
	char	*fname, *mode;

	opcast (OT_STRING);
	o = popop();
	fname = (o.o_val.v_s);

	if (newtask->t_flags & T_FOREIGN && newtask->t_stdout == stdout) {
	    /* If foreign task let ZOSCMD open the spool file.
	     */
	    newtask->ft_out = comdstr (fname);
	    newtask->t_flags |= T_APPEND;
	} else {
	    mode = (newtask->t_flags & T_STDOUTB) ? "ab" : "a";

	    if ((newtask->t_stdout = fopen (fname, mode)) == NULL)
		cl_error (E_UERR, e_appopen, fname);

	    newtask->t_flags |= T_MYOUT;
	}
}
Exemple #25
0
/* QUERY -- Query the user for the value of a parameter.  Prompt with the
 *  current value if any.  Keep this up until we can push a reasonable value.
 *  Also, store the new value in the parameter (except for list params, where,
 *  since the values are not kept, all that may change is P_LEOF if seen).
 * Give prompt, or name if none, current value and range if int, real or 
 *   filename.  Accept CR to leave value unchanged, else take the string
 *   entered to be the new value.  Repeat until parameter value is in range.
 * We mean to talk straight to the user here; thus, interact with the real
 *   stdio, not the effective t_stdio, so that redirections do not get in
 *   the way.  In batch mode, a forced query is handled by writing a
 *   message on the terminal of the parent cl (the original stderr), and
 *   leaving some info describing the query in a file in uparm (if there is
 *   no uparm, we abort).  We then loop, waiting for the user to run "service"
 *   in the interactive cl to service the query, leaving the answer in a
 *   another file which we read and then delete.  If we wait a long time and
 *   get no response, we timeout.
 */
void 
query (struct param *pp)
{
	static	char *oormsg =
		"ERROR: Parameter value is out of range; try again";
	register char *ip;
	char	buf[SZ_PROMPTBUF+1];
	struct	operand o;
	int	bastype, batch, arrflag, offset=0, n_ele, max_ele, fd;
	char	*index(), *nlp, *nextstr();
	char	*bkg_query(), *query_status;
	char	*abuf;

	bastype = pp->p_type & OT_BASIC;
	batch = firstask->t_flags & T_BATCH;
	arrflag = pp->p_type & PT_ARRAY;

	if (arrflag) {			/* We may access the array many     */
	    offset = getoffset (pp);	/* times, so save the offset and    */
					/* push it when necessary.	    */
	    poffset (offset);
	    max_ele = size_array (pp) - offset;
	} else
	    max_ele = 1;


	forever {
	    if (batch) {
		/* Query from a background job.
		 */
		query_status = bkg_query (buf, SZ_PROMPTBUF, pp);

	    } else if (pp->p_type & (PT_GCUR|PT_IMCUR)) {
		/* Read a graphics cursor.
		 */
		char	source[33];
		int	cursor;

		/* Determine the source of graphics cursor input, chosen from
		 * either the graphics or image cursor or the terminal.
		 */
		if (pp->p_type & PT_GCUR) {
		    if (c_envfind ("stdgcur", source, 32) <= 0)
			strcpy (source, "stdgraph");
		} else {
		    if (c_envfind ("stdimcur", source, 32) <= 0)
			strcpy (source, "stdimage");
		}

		if (strcmp (source, "stdgraph") == 0)
		    cursor = STDGRAPH;
		else if (strcmp (source, "stdimage") == 0)
		    cursor = STDIMAGE;
		else
		    goto text_query;		/* get value from terminal */

		/* Read a physical graphics cursor.
		 */
		pp->p_flags &= ~P_LEOF;
		if (cursor == STDIMAGE) {
		    /* The following is a kludge used to temporarily implement
		     * the logical image cursor read.  In the future this will
		     * be eliminated, and the c_rcursor call below (cursor
		     * mode) will be used for stdimage as well as for stdgraph.
		     * The present code (IMDRCUR) goes directly to the display
		     * server to get the cursor value, bypassing cursor mode
		     * and the (currently nonexistent) stdimage kernel.
		     */
		    char    str[SZ_LINE+1], keystr[10];
		    int     wcs, key;
		    float   x, y;

		    if (c_imdrcur ("stdimage",
			&x,&y,&wcs,&key,str,SZ_LINE, 1, 1) == EOF) {
			query_status = NULL;

		    } else {
			if (isprint(key) && !isspace(key))
			    sprintf (keystr, "%c", key);
			else
			    sprintf (keystr, "\\%03o", key);
			sprintf (buf, "%.3f %.3f %d %s %s\n",
			    x, y, wcs, keystr, str);
		        query_status = (char *) ((XINT) strlen(buf));
		    }

		} else if (c_rcursor (cursor, buf, SZ_PROMPTBUF) == EOF) {
		    query_status = NULL;
		} else
		    query_status = (char *) ((XINT) strlen(buf));

	    } else if (pp->p_type & PT_UKEY) {
		/* Read a user keystroke command from the terminal.
		 */
		pp->p_flags &= ~P_LEOF;
		if (c_rdukey (buf, SZ_PROMPTBUF) == EOF)
		    query_status = NULL;
		else
		    query_status = (char *) ((XINT) strlen(buf));

	    } else {
text_query:	fd = spf_open (buf, SZ_PROMPTBUF);
		pquery (pp, fdopen(fd,"a"));
		spf_close (fd);

		c_stgputline ((XINT)STDOUT, buf);
		if (c_stggetline ((XINT)STDIN, buf, SZ_PROMPTBUF) > 0)
		    query_status = (char *) ((XINT) strlen(buf));
		else
		    query_status = NULL;
	    }

	    ip = buf;

	    /* Set o to the current value of the parameter.  Beware that some
	     * of the logical branches which follow assume that struct o has
	     * been initialized to the current value of the parameter.
	     */
	    if (pp->p_type & PT_LIST)
		setopundef (&o);
	    else if (arrflag) {
		paramget(pp, FN_VALUE);
		poffset (offset);
		o = popop();
	    } else
		o = pp->p_valo;

	    /* Handle eof, a null-length line (lone carriage return),
	     * and line with more than SZ_LINE chars.  Ignore leading whitespace
	     * if basic type is not string.
	     */
	    if (query_status == NULL) {
		/* Typing eof will use current value (as will a lone
		 * newline) but if param is a list, it is a meaningful
		 * answer.
		 */
		if (pp->p_type & PT_LIST) {
		    closelist (pp);		/* close an existing file */
		    pp->p_flags |= P_LEOF;
		    o = makeop (eofstr, OT_STRING);
		    break;
		}
		goto testval;
	    }

	    /* Ignore leading whitespace if it is not significant for this
	     * datatype.  Do this before testing for empty line, so that a
	     * return such as " \n" is equivalent to "\n".  I.e., do not
	     * penalize the user if they type the space bar by accident before
	     * typing return to accept the default value.
	     */
	    if (bastype != OT_STRING || (pp->p_type & (PT_FILNAM|PT_PSET)))
		while (*ip == ' ' || *ip == '\t')
		    ip++;

	    if (*ip == '\n') {
		/* Blank lines usually just accept the current value
		 * but if the param is a string and is undefined,
		 * it sets the string to a (defined) nullstring.
		 */
		*ip = '\0';
		if (bastype == OT_STRING && opundef (&o))
		    o = makeop (ip, bastype);
		else
		    goto testval;
	    }

	    if ((nlp = index (ip, '\n')) != NULL)
		*nlp = '\0';			/* cancel the newline	*/
	    else
		goto testval;

	    /* Finally, we have handled the pathological cases...
	     */
	    if ((pp->p_type & PT_LIST) &&
		(!strcmp (ip,eofstr) || !strcmp (ip,"eof"))) {

		closelist (pp);
		pp->p_flags |= P_LEOF;
		o = makeop (eofstr, OT_STRING);
		break;

	    } else {
		if (arrflag) {
		    /* In querying for arrays we may set more than one
		     * element of the array in a single query.  However
		     * we must set the first element.  So we will pretend
		     * to be a scalar until that first element is set
		     * and then enter a loop where we may set other
		     * elements.
		     */
		    abuf = ip;
		    ip = nextstr(&abuf, stdin);
		    if (ip == NULL  ||  ip == (char *) ERR  ||  ip == undefval)
			goto testval;
		}

		o = makeop (ip, bastype);
	    }

testval:
	    /* If parameter value is in range, we are done.  If it is out of
	     * range and we are a batch job or an interactive terminal job,
	     * print an error message and request that the user enter a legal
	     * value.  If the CL is being run taking input from a file, abort,
	     * else we will go into a loop reading illegal values from the
	     * input file and printing out lots of error messages.
	     */
	    if (inrange (pp, &o))
		break;
	    else if (batch)
		eprintf ("\n[%d] %s", bkgno, oormsg);
	    else if (isatty (fileno (stdin)))
		eprintf ("%s\n", oormsg);
	    else
		cl_error (E_UERR, oormsg);
	}

	if (!(pp->p_type & PT_LIST)) {
	    /* update param with new value.
	     */
	    if (cldebug) {
		eprintf ("changing `%s.p_val' to ", pp->p_name);
		fprop (stderr, &o);
		eprintf ("\n");
	    }

	    pushop (&o);
	    paramset (pp, FN_VALUE);
	    pp->p_flags |= P_QUERY;
	}

	pushop (&o);

	if (arrflag  &&  query_status != NULL  &&  *ip != '\0') {
	    /* If we have an array assign values until something
	     * is used up or until we hit any error.
	     */
	    n_ele = 1;
	    forever {
		if (n_ele >= max_ele)		/* End of array. */
		    break;
		ip = nextstr(&abuf, stdin);

		if (ip == NULL)			/* End of query line. */
		    break;

		if (ip == (char *) ERR) {	/* Error on query line. */
		    eprintf("Error loading array value.\n");
		    break;
		}

		if (ip != undefval) {
		    o = makeop (ip, bastype);
		    if ( ! inrange (pp, &o) ) {	/* Not in range. */
			eprintf("Array value outside range.\n");
			break;
		    }

		    offset++;			/* Next element in array. */
		    poffset (offset);

		    pushop (&o);
		    paramset (pp, FN_VALUE);
		} else
		    offset++;

		n_ele++;
	    }
	}
Exemple #26
0
/* Calculate the effective mode for the given parameter, considering
 *   its own mode and the modes for the current task and the cl.
 *   Inhibit query mode if set on the command line or hidden but
 *   enable it if the param is not in range.  The range test cannot be done
 *   here for list params because we'd have to read the list to do it.
 * Return a bit-mapped code (built up of M_XXX bits) of the result.
 * Since learn mode is not defined at the parameter level, pp == NULL
 *   is used to indicate we are just interested in M_LEARN info.
 * Local variables cannot be prompted for so it is an error if their
 *   values are undefined.
 */
int 
effmode (struct param *pp)
{
	static	char	*localerr =
		"Attempt to access undefined local variable `%s'.\n";

	register int	mode, modebits;
	struct	operand o;
	int	clmode, ltmode, pkmode, offset;
	int	interactive;


	/* Check if param is a local variable.  If it is undefined
	 * this is an ERR, if defined just return mode 0 to defeat
	 * querying.
	 */
	if (pp != NULL) {
	    if (pp->p_mode & M_LOCAL) {
		if (opundef (&(pp->p_valo)))
		    cl_error (E_UERR, localerr, pp->p_name);
		return (0);
	    }
	}

	/* Determine whether or not the current task was called interactively.
	 * Menu mode is only permitted for tasks called interactively.
	 */
	interactive = 0;
	if (prevtask)
	    interactive = (prevtask->t_flags & (T_INTERACTIVE|T_BATCH));
	if (interactive)
	    modebits = (M_QUERY|M_HIDDEN|M_MENU);
	else
	    modebits = (M_QUERY|M_HIDDEN);

	clmode = scanmode (firstask->t_modep->p_val.v_s);
	ltmode = scanmode (currentask->t_modep->p_val.v_s);
	pkmode = -1;

	mode = 0;
	if (pp != NULL) {
	    /* In determining the effective mode we go up the hierarchy of
	     * parameter, task, package, cl.  The mode is taken from the first
	     * of these which is not automatic.
	     */
	    if ( (mode = (pp->p_mode & modebits)) )
		;
	    else if ( (mode = (ltmode & modebits)) )
		;
	    else {
		/* Check the mode of the package to which the ltask belongs,
		 * which need not be the "current" package.
		 */
		struct pfile *pfp;

		if ( (pfp = currentask->t_ltp->lt_pkp->pk_pfp) ) {
	 	    struct param   *ppx;
	 	    ppx = paramfind (pfp, "mode", 0, YES);
	 	    if ((ppx != NULL)  &&  (ppx != (struct param *)ERR))
	 		pkmode = scanmode (ppx->p_val.v_s);
	 	}

		if (pkmode > 0 && (mode = (pkmode & modebits)))
		    ;
		else if ( (mode = (clmode & modebits)) )
		    ;
		else
		    mode = M_AUTO;
	    }

	    /* Defeat query mode if param set on command line or it's a
	     * hidden param or if menu mode is in effect.
	     */
	    if ((pp->p_flags & P_CLSET) || (pp->p_mode & M_HIDDEN) ||
		(mode & M_MENU))
		mode &= ~M_QUERY;

	    /* Query unconditionally if param is out of range or undefined.
	     */
	    if (!(mode & M_QUERY) && !(pp->p_type & PT_LIST)) {

		/* To check whether an array element is in range we
		 * must get the appropriate element of the array.  However
		 * the stack must be reset so that the element can be accessed
		 * again by the calling routine.
		 */
		if (pp->p_type & PT_ARRAY) {
		    offset = getoffset(pp);

		    poffset (offset);
		    paramget(pp, FN_VALUE);

		    poffset (offset);

		    o = popop();
		    if (!inrange (pp, &o))
			mode |= M_QUERY;

		} else {
		    /* Use temporary scratch variable for range checking in
		     * this case; sometimes the value of an enumerated
		     * parameter would get trashed in the process.  There is
		     * probably some deeper, darker bug lurking down there,
		     * but haven't found it yet, so this will suffice for now.
		     */
		    o = pp->p_valo;
		    if (!inrange (pp, &o))
			mode |= M_QUERY;
		}
	    }
	}

	/* Enable learn mode only for tasks called interactively - don't bother
	 * to learn parameters if the task is called from a script or in batch
	 * mode.
	 */
	if (interactive)
	    mode |= (clmode & M_LEARN) | (ltmode & M_LEARN);

	return (mode);
}
Exemple #27
0
/* GQUERY -- Determine if the value of a parameter given by the user is OK.
 * Also, store the new value in the parameter; in the case of a list
 * structured parameter, the new value is the name of a new list file.
 * This routine is called by EPARAM to verify that the new parameter value
 * is inrange and set the new value if so.
 */
char *
gquery (
  struct param *pp,
  char	*string
)
{
	register char *ip;
	char	buf[SZ_LINE];
	char	*query_status, *nlp, *errmsg;
	int	arrflag, offset, bastype, batch;
	struct	operand o;
	char	*strcpy(), *index();

	bastype = pp->p_type & OT_BASIC;
	batch   = firstask->t_flags & T_BATCH;
	arrflag = pp->p_type & PT_ARRAY;

	if (arrflag)
	    offset = getoffset(pp);

	if (batch) {
	    errmsg = e1;
	    return (errmsg);
	} else
	    query_status = strcpy (buf, string);

	ip = buf;

	/* Set o to the current value of the parameter.  Beware that some
	 * of the logical branches which follow assume that struct o has
	 * been initialized to the current value of the parameter.
	 */
	if (pp->p_type & PT_LIST) {
	    setopundef (&o);
	} else if (arrflag) {
	    poffset (offset);
	    paramget (pp, FN_VALUE);
	    o = popop ();
	} else
	    o = pp->p_valo;

	/* Handle eof, a null-length line (lone carriage return),
	 * and line with more than SZ_LINE chars.  Ignore leading whitespace
	 * if basic type is not string.
	 */
	if (query_status == NULL)
	    goto testval;

	/* Ignore leading whitespace if it is not significant for this
	 * datatype.  Do this before testing for empty line, so that a
	 * return such as " \n" is equivalent to "\n".  I.e., do not
	 * penalize the user if they type the space bar by accident before
	 * typing return to accept the default value.
	 */
	if (bastype != OT_STRING || (pp->p_type & PT_LIST))
	    while (*ip == ' ' || *ip == '\t')
		ip++;

	if (*ip == '\n') {
	    /* Blank lines usually just accept the current value
	     * but if the param in a string and is undefined,
	     * it sets the string to a (defined) nullstring.
	     */
	    if (bastype == OT_STRING && opundef (&o)) {
		*ip = '\0';
		o = makeop (ip, bastype);
	    } else
		goto testval;
	}

	/* Cancel the newline. */
	if ((nlp = index (ip, '\n')) != NULL)
	    *nlp = '\0';

	/* Finally, we have handled the pathological cases.
	 */
	if (pp->p_type & PT_LIST)
	    o = makeop (string, OT_STRING);
	else
	    o = makeop (ip, bastype);

testval:   
	if (*string == '@')
	    errmsg = "OK";
	else if (pp->p_type & PT_LIST)
	    errmsg = "OK";
	else if (inrange (pp, &o))
	    errmsg = "OK";
	else {
	    errmsg = e2;
	    return (errmsg);
	}

	if (cldebug) {
	    eprintf ("changing `%s.p_val' to ", pp->p_name);
	    fprop (stderr, &o);
	    eprintf ("\n");
	}

	/* Update param with new value.
	 */
	pushop (&o);
	if (arrflag)
	    poffset (offset);

	paramset (pp, FN_VALUE);
	pp->p_flags |= P_SET;

	return ("OK");
}
Exemple #28
0
/* Doswitch finds the appropriate location to jump to in the
 * jump table and goes there.
 */
void 
o_doswitch (int *jmpdelta)

{
	int pdft, icase, jmptable;
	int value=0;
	struct operand o;
	memel delta;
	/* Remember to subtract SZ_CE 'cuz PC has already been incremented. */
	jmptable = *jmpdelta + pc - SZ_CE;

	o = popop();
	if (o.o_type == OT_INT)
	    value = o.o_val.v_i;
	else if (o.o_type == OT_STRING) {
	    if (*o.o_val.v_s != '\0'  &&  *(o.o_val.v_s+1) == '\0')
		value = (int) *o.o_val.v_s;
	    else
		cl_error(E_UERR, "Illegal switch value.");
	} else
	    cl_error (E_UERR, "Illegal switch value.");

	pdft = stack[jmptable];

	if (cldebug)
	    eprintf ("doswitch: pdft=%d\n", pdft);

	/* Loop over cases.
	 */
	for (icase= jmptable + 1; stack[icase] != 0; icase++) {
	    int nval, ival, pcase;
	    memel *val;

	    pcase = stack[icase] + pc - SZ_CE;
	    nval = coderef(pcase)->c_length - (SZ_CE - 1);
	    currentline = coderef(pcase)->c_scriptln;

	    /* Loop over all values for a particular case.
	     */
	    val = & (coderef(pcase)->c_args);
	    for (ival=0; ival<nval; ival++, val++) {
		if (*val == value) {
		    /* Remember to skip over the CASE operand itself. */
		    delta =  pcase + (nval+(SZ_CE-1)) - (pc-SZ_CE) - SZ_CE;
		    o_dogoto (&delta);
		    return;
		}
	    }
	}

	/* Default? */
	if (pdft != 0) {
	    pdft = pdft + pc - SZ_CE;
	    /* Skipping over DEFAULT block takes 2 ints.
	     */
	    delta =  (pdft+(SZ_CE-1)) - (pc-SZ_CE) - SZ_CE;
	    o_dogoto (&delta);
	    return;
	}

	/* If there is no default we just drop through to the
	 * next statement which is a branch beyond the SWITCH.
	 */
}