/* <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; }
/* <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; }
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"); }
/* . * 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"); }
/* <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; }
void o_swon (memel *argp) { register char *pname = (char *)argp; register struct param *pp; struct pfile *pfp; struct operand o; char *pk, *t, *p, *f; breakout (pname, &pk, &t, &p, &f); if (*pk) cl_error (E_UERR, e_simplep, p); pfp = newtask->t_pfp; 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, newtask->t_ltp->lt_lname); o.o_type = OT_BOOL; o.o_val.v_i = YES; pushop (&o); paramset (pp, FN_VALUE); if (pp->p_type & PT_PSET) psetreload (pfp, pp); pp->p_flags |= P_CLSET; }
void o_doaddpipe (memel *argp) { XINT getpipe_pc = *argp; char *x1, *pk, *t, *x2; char *ltname; struct operand o; struct ltask *ltp; char *addpipe(); /* ADDPIPE is called immediately before REDIR and before EXEC so we * do not have to worry about storing the pipefile name in the dict. * Our argument is the PC of the GETPIPE instruction, the args field * of which is the taskname of the second task in the pipe. If either * the new task (first task in the pipe) or the second task is a * FOREIGN task, the pipe must be created as a text file. */ ltname = (char *)&(coderef(getpipe_pc)->c_args); if (*ltname == '$') ltname++; breakout (ltname, &x1, &pk, &t, &x2); ltp = cmdsrch (pk, t); binpipe = ((ltp == NULL || !(ltp->lt_flags & LT_FOREIGN)) && !(newtask->t_flags & T_FOREIGN)); if (binpipe) newtask->t_flags |= T_STDOUTB; o.o_type = OT_STRING; o.o_val.v_s = comdstr (addpipe()); pushop (&o); }
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, ""); }
/* <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; }
/* . <new constant> * The "illegal constant" business comes from the possibility of syntactically * correct but valuely wrong sexagesimal constants, such as 1:222:1. * We don't want to abort in sexa() because it may be used to digest a query * response and producing a quiet undefined op there is correct. */ void o_pushconst (memel *argp) { /* argument is pointer to an operand */ struct operand *op; op = (struct operand *) argp; if (opundef (op)) cl_error (E_UERR, "illegal constant"); pushop (op); }
/* <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; }
/* <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; }
/* ** 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); }
void o_dogetpipe ( memel *argp /* name of ltask (not used) */ ) { struct operand o; char *getpipe(), *comdstr(); /* GETPIPE is called immediately before REDIRIN and before EXEC so we * do not have to worry about storing the pipefile name in the dict. * The flag binpipe is set by the last ADDPIPE if the pipe is a binary * file. */ if (binpipe) newtask->t_flags |= T_STDINB; o.o_type = OT_STRING; o.o_val.v_s = comdstr (getpipe()); pushop (&o); }
/* <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; }
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); }
/* 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++; } }
/* 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"); }