예제 #1
0
파일: f_justify.c 프로젝트: 5HT/mumps
int f_justify( oprtype *a, opctype op)
{
	triple *ref, *r;
	error_def(ERR_COMMA);

	r = maketriple(op);
	if (!strexpr(&r->operand[0]))
		return FALSE;
	if (window_token != TK_COMMA)
	{
		stx_error(ERR_COMMA);
		return FALSE;
	}
	advancewindow();
	if (!intexpr(&r->operand[1]))
		return FALSE;
	if (window_token == TK_COMMA)
	{
		r->opcode = OC_FNJ3;
		ref = newtriple(OC_PARAMETER);
		ref->operand[0] = r->operand[1];
		r->operand[1] = put_tref(ref);
		advancewindow();
		if (!intexpr(&ref->operand[1]))
			return FALSE;
	}
	ins_triple(r);
	*a = put_tref(r);
	return TRUE;
}
예제 #2
0
int f_extract(oprtype *a, opctype op)
{
	triple *first, *last, *r;

	r = maketriple(op);
	if (!strexpr(&(r->operand[0])))
		return FALSE;
	first = newtriple(OC_PARAMETER);
	last = newtriple(OC_PARAMETER);
	r->operand[1] = put_tref(first);
	first->operand[1] = put_tref(last);
	if (window_token != TK_COMMA)
	{
		first->operand[0] = last->operand[0] = put_ilit(1);
	}
	else
	{
		advancewindow();
		if (!intexpr(&(first->operand[0])))
			return FALSE;
		if (window_token != TK_COMMA)
			last->operand[0] = first->operand[0];
		else
		{
			advancewindow();
			if (!intexpr(&(last->operand[0])))
				return FALSE;
		}
	}
	ins_triple(r);
	*a = put_tref(r);
	return TRUE;
}
예제 #3
0
/*---------------------------------------------------------------------------*/
static void go_statement(void)
{
  int linenum;
  uint8_t t;

  t = accept_either(TOKENIZER_TO, TOKENIZER_SUB);
  if (t == TOKENIZER_TO) {
    linenum = intexpr();
    DEBUG_PRINTF("go_statement: go to %d.\n", linenum);
    if (!statement_end())
      syntax_error();
    DEBUG_PRINTF("go_statement: jumping.\n");
    jump_linenum(linenum);
    return;
  }
  linenum = intexpr();
  if (!statement_end())
    syntax_error();

  if(gosub_stack_ptr < MAX_GOSUB_STACK_DEPTH) {
    gosub_stack[gosub_stack_ptr] = tokenizer_pos();
    gosub_stack_ptr++;
    jump_linenum(linenum);
  } else {
    DEBUG_PRINTF("gosub_statement: gosub stack exhausted\n");
    ubasic_error("Return without gosub");
  }
}
예제 #4
0
static void print_statement(void)
{
  uint8_t nonl;
  uint8_t t;
  uint8_t nv = 0;

  do {
    t = current_token;
    nonl = 0;
    DEBUG_PRINTF("Print loop\n");
    if (nv == 0) {
      if(t == TOKENIZER_STRING) {
        /* Handle string const specially - length rules */
        tokenizer_string_func(charout, NULL);
        tokenizer_next();
        nv = 1;
        continue;
      } else if(TOKENIZER_STRINGEXP(t)) {
        charoutstr(stringexpr());
        nv = 1;
        continue;
      } else if(TOKENIZER_NUMEXP(t)) {
        intout(intexpr());
        nv = 1;
        continue;
      } else if(t == TOKENIZER_TAB) {
        nv = 1;
        accept_tok(TOKENIZER_TAB);
        chartab(bracketed_intexpr());
        continue;
      } else if(t == TOKENIZER_AT) {
        int x,y;
        nv = 1;
        accept_tok(TOKENIZER_AT);
        y = intexpr();
        accept_tok(TOKENIZER_COMMA);
        x = intexpr();
        if (move_cursor(x,y))
          chpos = x;
        continue;
      }
    }
    nv = 0;
    if(t == TOKENIZER_COMMA) {
      charout('\t', NULL);
      nonl = 1;
      tokenizer_next();
    } else if(t == TOKENIZER_SEMICOLON) {
      nonl = 1;
      tokenizer_next();
    } else if (!statement_end()) {
      syntax_error();
      break;
    }
  } while(!statement_end());
  if (!nonl)
    charout('\n', 0);
  DEBUG_PRINTF("End of print\n");
}
예제 #5
0
/*---------------------------------------------------------------------------*/
static void poke_statement(void)
{
  value_t poke_addr;
  value_t value;

  poke_addr = intexpr();
  accept_tok(TOKENIZER_COMMA);
  value = intexpr();

  poke_function(poke_addr, value);
}
예제 #6
0
SNODE *_genwordstmt(void)
/*
 * Insert data in the code stream
 */
{
				SNODE *snp;
				snp = xalloc(sizeof(SNODE));
				snp->next = 0;
				snp->stype = st__genword;
				snp->exp = 0;
				getsym();
				if (lastst != openpa) {
					generror(ERR_PUNCT,openpa,skm_semi);
					getsym();
					snp = 0;
				}
				else {
					getsym();
					snp->exp = (ENODE *) intexpr(0);
					if (lastst != closepa) {
						generror(ERR_PUNCT,closepa,skm_semi);
						snp = 0;
					}
					getsym();
				}
				if (lastst != eof)
					needpunc(semicolon,0);
				return(snp);
}
예제 #7
0
파일: decl.c 프로젝트: JamesLinus/mcc
static void ids(node_t *sym)
{
    if (token->id == ID) {
        int val = 0;
        do {
            node_t *s = lookup(token->name, identifiers);
            if (s && is_current_scope(s))
                redefinition_error(source, s);

            s = install(token->name, &identifiers, SCOPE);
            SYM_TYPE(s) = SYM_TYPE(sym);
            AST_SRC(s) = source;
            SYM_SCLASS(s) = ENUM;
            expect(ID);
            if (token->id == '=') {
                expect('=');
                val = intexpr();
            }
            SYM_VALUE_U(s) = val++;
            if (token->id != ',')
                break;
            expect(',');
        } while (token->id == ID);
    } else {
        error("expect identifier");
    }
}
예제 #8
0
파일: decl.c 프로젝트: JamesLinus/mcc
static void bitfield(node_t *field)
{
    AST_SRC(field) = source;
    expect(':');
    FIELD_BITSIZE(field) = intexpr();
    FIELD_ISBIT(field) = true;
}
예제 #9
0
SNODE    *casestmt(SNODE *lst) 
/* 
 *      cases are returned as seperate statements. for normal 
 *      cases label is the case value and s2 is zero. for the 
 *      default case s2 is nonzero. 
 */ 
{       SNODE    *snp; 
        SNODE    *head=0, *tail; 
        snp = xalloc(sizeof(SNODE)); 
				snp->next = 0;
        if( lastst == kw_case ) { 
                getsym(); 
                snp->s2 = 0;
                snp->stype = st_case;
                snp->label = (SNODE *)intexpr(0);
                } 
        else if( lastst == kw_default) { 
								goodcode |= GF_DEF;
                getsym(); 
                snp->stype = st_case;
                snp->s2 = (SNODE *)1; 
                } 
        else    { 
                generror(ERR_NOCASE,0,0); 
                return 0; 
                } 
        needpunc(colon,0); 
        head = 0; 
				if (lst) {
					head = tail = lst;
					lst->next = 0;
				}
        while( lastst != end && lastst != eof &&
                lastst != kw_case && 
                lastst != kw_default ) { 
								if (goodcode & (GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO)) {
									if (lastst == id) {
                    while( isspace(lastch) ) 
                      getch(); 
										if (lastch != ':')
											generror(ERR_UNREACHABLE,0,0);
											
									}
									else
										generror(ERR_UNREACHABLE,0,0);
								}
								goodcode &= ~(GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO);
                if( head == 0 ) 
                        head = tail = statement(); 
                else    { 
                        tail->next = statement(); 
                        } 
                while( tail->next != 0 ) 
                  tail = tail->next; 
                }
				if (goodcode & GF_BREAK)
					goodcode &= ~GF_UNREACH;
        snp->s1 = head; 
        return snp; 
} 
예제 #10
0
파일: f_ztrnlnm.c 프로젝트: 5HT/mumps
int f_ztrnlnm( oprtype *a, opctype op )
{
	triple *r, *last, *ref;
	int i;
	bool again;

	last = r = maketriple(op);
	if (!strexpr(&r->operand[0]))
		return FALSE;
	ref = newtriple(OC_PARAMETER);
	last->operand[1] = put_tref(ref);
	if (window_token == TK_COMMA)
	{	advancewindow();
		if (window_token == TK_COMMA || window_token == TK_RPAREN)
		{	ref->operand[0] = put_str("",0);
		}else
		{	if (!strexpr(&ref->operand[0]))
				return FALSE;
		}
	}else
	{	ref->operand[0] = put_str("",0);
	}
	last = ref;
	ref = newtriple(OC_PARAMETER);
	last->operand[1] = put_tref(ref);
	if (window_token == TK_COMMA)
	{	advancewindow();
		if (window_token == TK_COMMA || window_token == TK_RPAREN)
		{	ref->operand[0] = put_ilit(0);
		}else
		{	if (!intexpr(&ref->operand[0]))
				return FALSE;
		}
	}else
	{	ref->operand[0] = put_ilit(0);
	}
	last = ref;
	again = TRUE;
	for (i = 0; i < 3; i++)
	{	ref = newtriple(OC_PARAMETER);
		last->operand[1] = put_tref(ref);
		if (again && window_token == TK_COMMA)
		{	advancewindow();
			if (window_token == TK_COMMA || window_token == TK_RPAREN)
			{	ref->operand[0] = put_str("",0);
			}else
			{	if (!strexpr(&ref->operand[0]))
					return FALSE;
			}
		}else
		{	again = FALSE;
			ref->operand[0] = put_str("",0);
		}
		last = ref;
	}
	ins_triple(r);
	*a = put_tref(r);
	return TRUE;
}
예제 #11
0
static void option_statement(void)
{
  value_t r;
  accept_tok(TOKENIZER_BASE);
  r = intexpr();
  if (r < 0 || r > 1)
    ubasic_error("Invalid base");
  array_base = r;
}
예제 #12
0
int f_piece(oprtype *a, opctype op)
{
	mval		*delim_mval;
	triple		*delimiter, *first, *last, *r;
	oprtype		x;
	delimfmt	unichar;

	error_def(ERR_COMMA);

	r = maketriple(op);
	if (!strexpr(&(r->operand[0])))
		return FALSE;
	if (window_token != TK_COMMA)
	{
		stx_error(ERR_COMMA);
		return FALSE;
	}
	advancewindow();
	delimiter = newtriple(OC_PARAMETER);
	r->operand[1] = put_tref(delimiter);
	first = newtriple(OC_PARAMETER);
	delimiter->operand[1] = put_tref(first);
	if (!strexpr(&x))
		return FALSE;
	if (window_token != TK_COMMA)
		first->operand[0] = put_ilit(1);
	else
	{
		advancewindow();
		if (!intexpr(&(first->operand[0])))
			return FALSE;
	}
	assert(x.oprclass == TRIP_REF);
	if (window_token != TK_COMMA && x.oprval.tref->opcode == OC_LIT &&
	    (1 == ((gtm_utf8_mode && OC_FNZPIECE != op) ?  MV_FORCE_LEN(&x.oprval.tref->operand[0].oprval.mlit->v) :
		   x.oprval.tref->operand[0].oprval.mlit->v.str.len)))
	{	/* Potential shortcut to op_fnzp1 or op_fnp1. Make some further checks */
		delim_mval = &x.oprval.tref->operand[0].oprval.mlit->v;
		/* Both valid chars of char_len 1 and invalid chars of byte length 1 get the fast path */
		unichar.unichar_val = 0;
		if (!gtm_utf8_mode || OC_FNZPIECE == op)
		{       /* Single byte delimiter */
			r->opcode = OC_FNZP1;
			unichar.unibytes_val[0] = *delim_mval->str.addr;
		} else
		{       /* Potentially multiple bytes in one int */
			r->opcode = OC_FNP1;
			assert(SIZEOF(int) >= delim_mval->str.len);
			memcpy(unichar.unibytes_val, delim_mval->str.addr, delim_mval->str.len);
		}
		delimiter->operand[0] = put_ilit(unichar.unichar_val);
		ins_triple(r);
		*a = put_tref(r);
		return TRUE;
	}
예제 #13
0
/*---------------------------------------------------------------------------*/
void dim_statement(void)
{
  var_t v = tokenizer_variable_num();
  value_t s1,s2 = 1;
  int n = 1;
  
  accept_either(TOKENIZER_STRINGVAR, TOKENIZER_INTVAR);
  
  /* For now A-Z/A-Z$ only */
  if ((v & ~STRINGFLAG) > 25)
    ubasic_error("invalid array name");
  
  accept_tok(TOKENIZER_LEFTPAREN);
  s1 = intexpr();
  if (accept_either(TOKENIZER_RIGHTPAREN, TOKENIZER_COMMA) == TOKENIZER_COMMA) {
    s2 = intexpr();
    n = 2;
    accept_tok(TOKENIZER_RIGHTPAREN);
  }

  if (v & STRINGFLAG) {
    uint8_t **p;
    v &= ~STRINGFLAG;
    if (stringsubs[v] || strings[v] != nullstr)
      ubasic_error(redimension);
    stringsubs[v] = n;
    stringdim[v][0] = s1;
    stringdim[v][1] = s2;
    p = calloc(s1 * s2, sizeof(uint8_t *));
    strings[v] = (uint8_t *)p;
    for (n = 0; n < s1 * s2; n++)
      *p++ = nullstr;
  } else {
    if (variablesubs[v])
      ubasic_error(redimension);
    variablesubs[v] = n;
    vardim[v][0] = s1;
    vardim[v][1] = s2;
    vararrays[v] = calloc(s1 * s2, sizeof(uint8_t *));
  }
}	
예제 #14
0
int f_mint( oprtype *a, opctype op)
{
    triple *r;

    r = maketriple(op);
    if (!intexpr(&r->operand[0]))
    {   return FALSE;
    }
    ins_triple(r);
    *a = put_tref(r);
    return TRUE;
}
예제 #15
0
/*---------------------------------------------------------------------------*/
static void for_statement(void)
{
  var_t for_variable;
  value_t to, step = 1;
  struct typevalue t;

  for_variable = tokenizer_variable_num();
  accept_tok(TOKENIZER_INTVAR);
  accept_tok(TOKENIZER_EQ);
  expr(&t);
  typecheck_int(&t);
  /* The set also typechecks the variable */
  ubasic_set_variable(for_variable, &t, 0, NULL);
  accept_tok(TOKENIZER_TO);
  to = intexpr();
  if (current_token == TOKENIZER_STEP) {
    accept_tok(TOKENIZER_STEP);
    step = intexpr();
  }
  if (!statement_end())
    syntax_error();
  /* Save a pointer to the : or CR, when we return to statements it
     will do the right thing */
  if(for_stack_ptr < MAX_FOR_STACK_DEPTH) {
    struct for_state *fs = &for_stack[for_stack_ptr];
    fs->resume_token = tokenizer_pos();
    fs->for_variable = for_variable;
    fs->to = to;
    fs->step = step;
    DEBUG_PRINTF("for_statement: new for, var %d to %d step %d\n",
                fs->for_variable,
                fs->to,
                fs->step);

    for_stack_ptr++;
  } else {
    DEBUG_PRINTF("for_statement: for stack depth exceeded\n");
  }
}
예제 #16
0
/*---------------------------------------------------------------------------*/
static void randomize_statement(void)
{
  value_t r = 0;
  time_t t;
  /* FIXME: replace all the CR checks with TOKENIZER_EOS() or similar so we
     can deal with ':' */
  if (current_token != TOKENIZER_CR)
    r = intexpr();
  if (r == 0) {
    time(&t);
    srand(getpid()^getuid()^(unsigned int)t);
  } else
    srand(r);
}
예제 #17
0
/*---------------------------------------------------------------------------*/
void restore_statement(void)
{
  int linenum = 0;
  if (!statement_end())
    linenum = intexpr();
  if (linenum) {
    tokenizer_push();
    jump_linenum(linenum);
    data_position = tokenizer_pos();
    tokenizer_pop();
  } else
    data_position = program_ptr;
  data_seek = 1;
}
예제 #18
0
파일: f_stack.c 프로젝트: 5HT/mumps
int f_stack(oprtype *a, opctype op)
{
	triple *r;

	r = maketriple(op);
	if (!intexpr(&(r->operand[0])))
		return FALSE;
	if (window_token == TK_COMMA)
	{
		advancewindow();
		r->opcode = OC_FNSTACK2;      /*This isn't very good information hiding*/
		if (!strexpr(&(r->operand[1])))
			return FALSE;
	}
	ins_triple(r);
	*a = put_tref(r);
	return TRUE;
}
예제 #19
0
파일: f_fnzbitget.c 프로젝트: 5HT/mumps
int f_fnzbitget( oprtype *a, opctype op)
{
	triple *r;
	error_def(ERR_COMMA);

	r = maketriple(op);
	if (!expr(&(r->operand[0])))      /* bitstring */
		return FALSE;
	if (window_token != TK_COMMA)
	{
		stx_error(ERR_COMMA);
		return FALSE;
	}
	advancewindow();
	if (!intexpr(&(r->operand[1])))    /* position  */
		return FALSE;

	ins_triple(r);
	*a = put_tref(r);
	return TRUE;
}
예제 #20
0
static long ieprimary(TYP **tp)   
/*
 * PRimary integer
 *    defined(MACRO)
 *    id
 *    iconst
 *    (cast )intexpr
 *    (intexpr)
 */
{       long     temp=0;
        SYM     *sp;
				if (tp)
					*tp = &stdint;
        if(lastst == id) {
					char *lid = lastid;
					if (prm_cmangle)
						lid++;
                	sp = gsearch(lastid);
                	if(sp == NULL) {
												gensymerror(ERR_UNDEFINED,lastid);
                        getsym();
                        return 0;
                        }
                	if(sp->storage_class != sc_const && sp->tp->type != bt_enum) {
                        generror(ERR_NEEDCONST,0,0);
                        getsym();
                        return 0;
                        }
                	getsym();
                	return sp->value.i;
        }
        else if(lastst == iconst) {
                temp = ival;
                getsym();
                return temp;
                }
        else if(lastst == lconst) {
								if (tp)
									*tp = &stdlong;
                temp = ival;
                getsym();
                return temp;
                }
        else if(lastst == iuconst) {
								if (tp)
									*tp = &stduns;
                temp = ival;
                getsym();
                return temp;
                }
        else if(lastst == luconst) {
								if (tp)
									*tp = &stdunsigned;
                temp = ival;
                getsym();
                return temp;
                }
        else if(lastst == cconst) {
								if (tp)
									*tp = &stdchar;
                temp = ival;
                getsym();
                return temp;
                }
				else if (lastst == openpa) {
					getsym();
					if (castbegin(lastst)) {
						decl(0);
						decl1();
						needpunc(closepa,0);
						if (tp)
						  *tp = head;
						return intexpr(0);
					}
					else {
				  	temp = intexpr(tp);
						return(temp);
					}
				}
        getsym();
        generror(ERR_NEEDCONST,0,0);
        return 0;
}
예제 #21
0
파일: m_job.c 프로젝트: h4ck3rm1k3/FIS-GT.M
int m_job(void)
{
	int	argcnt;
	triple *ref,*next;
	oprtype label, offset, routine, plist, timeout, arglst, *argptr, argval;
	static readonly unsigned char empty_plist[1] = { jp_eol };
	bool is_timeout,dummybool;

	error_def(ERR_MAXACTARG);
	error_def(ERR_RTNNAME);
	error_def(ERR_COMMAORRPARENEXP);
	error_def(ERR_JOBACTREF);

	label = put_str(zero_ident.c,sizeof(mident));
	offset = put_ilit((mint)0);
	if (!lref(&label, &offset, FALSE, indir_job, TRUE, &dummybool))
		return FALSE;
	if ((TRIP_REF == label.oprclass) && (OC_COMMARG == label.oprval.tref->opcode))
		return TRUE;
	if (TK_CIRCUMFLEX != window_token)
	{
		if (!run_time)
			routine = put_str(routine_name,sizeof(mident));
		else
			routine = put_tref(newtriple(OC_CURRTN));
	} else
	{
		advancewindow();
		switch(window_token)
		{
		case TK_IDENT:
			routine = put_str(window_ident.c,sizeof(mident));
			advancewindow();
			break;
		case TK_ATSIGN:
			if (!indirection(&routine))
				return FALSE;
			break;
		default:
			stx_error(ERR_RTNNAME);
			return FALSE;
		}
	}
	argcnt = 0;
	if (TK_LPAREN == window_token)
	{
		advancewindow();
		argptr = &arglst;
		while(TK_RPAREN != window_token)
		{
			if (argcnt > MAX_ACTUALS)
			{
				stx_error(ERR_MAXACTARG);
				return FALSE;
			}
			if (TK_PERIOD == window_token)
			{
				stx_error(ERR_JOBACTREF);
				return FALSE;
			}
			if (!expr(&argval))
				return FALSE;
			ref = newtriple(OC_PARAMETER);
			ref->operand[0] = argval;
			*argptr = put_tref(ref);
			argptr = &ref->operand[1];
			argcnt++;
			if (TK_COMMA == window_token)
				advancewindow();
			else  if (TK_RPAREN != window_token)
			{
				stx_error(ERR_COMMAORRPARENEXP);
				return FALSE;
			}
		}
		advancewindow();	/* jump over close paren */
	}
	if (TK_COLON == window_token)
	{
		advancewindow();
		if (TK_COLON == window_token)
		{
			is_timeout = TRUE;
			plist = put_str((char *)empty_plist,sizeof(empty_plist));
		} else
		{
			if (!jobparameters(&plist))
				return FALSE;
			is_timeout = (TK_COLON == window_token);
		}
		if (is_timeout)
		{
			advancewindow();
			if (!intexpr(&timeout))
				return FALSE;
		} else
			timeout = put_ilit(NO_M_TIMEOUT);
	} else
	{
		is_timeout = FALSE;
		plist = put_str((char *)empty_plist,sizeof(empty_plist));
		timeout = put_ilit(NO_M_TIMEOUT);
	}

	ref = newtriple(OC_JOB);
	ref->operand[0] = put_ilit(argcnt + 5);		/* parameter list + five fixed arguments */
	next = newtriple(OC_PARAMETER);
	ref->operand[1] = put_tref(next);
	next->operand[0] = label;
	ref = newtriple(OC_PARAMETER);
	next->operand[1] = put_tref(ref);
	ref->operand[0] = offset;
	next = newtriple(OC_PARAMETER);
	ref->operand[1] = put_tref(next);
	next->operand[0] = routine;
	ref = newtriple(OC_PARAMETER);
	next->operand[1] = put_tref(ref);
	ref->operand[0] = plist;
	next = newtriple(OC_PARAMETER);
	ref->operand[1] = put_tref(next);
	next->operand[0] = timeout;
	if (argcnt)
		next->operand[1] = arglst;
	if (is_timeout)
		newtriple(OC_TIMTRU);
	return TRUE;
}
예제 #22
0
int m_zgoto(void)
{
	triple		tmpchain, *oldchain, *obp, *ref0, *ref1, *triptr;
	oprtype		*cr, quits;
	int4		rval;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	dqinit(&tmpchain, exorder);
	oldchain = setcurtchain(&tmpchain);
	if ((TK_EOL == window_token) || (TK_SPACE == window_token))
	{	/* Default zgoto level is 1 */
		quits = put_ilit(1);
		rval = EXPR_GOOD;
	} else if (!(rval = intexpr(&quits)))		/* note assignment */
	{
		setcurtchain(oldchain);
		return FALSE;
	}
	if ((EXPR_INDR != rval) && ((TK_EOL == window_token) || (TK_SPACE == window_token)))
	{	/* Only level parm supplied (no entry ref) - job for op_zg1 */
		setcurtchain(oldchain);
		obp = oldchain->exorder.bl;
		dqadd(obp, &tmpchain, exorder);		/* this is a violation of info hiding */
		ref0 = newtriple(OC_ZG1);
		ref0->operand[0] = quits;
		return TRUE;
	}
	if (TK_COLON != window_token)
	{	/* First arg parsed, not ending in ":". Better have been indirect */
		setcurtchain(oldchain);
		if (EXPR_INDR != rval)
		{
			stx_error(ERR_COLON);
			return FALSE;
		}
		make_commarg(&quits, indir_zgoto);
		obp = oldchain->exorder.bl;
		dqadd(obp, &tmpchain, exorder);		/* this is a violation of info hiding */
	 	return TRUE;
	}
	advancewindow();
	if (TK_COLON != window_token)
	{
		if (!entryref(OC_NOOP, OC_PARAMETER, (mint)indir_goto, FALSE, FALSE, TRUE))
		{
			setcurtchain(oldchain);
			return FALSE;
		}
		ref0 = maketriple(OC_ZGOTO);
		ref0->operand[0] = quits;
		ref0->operand[1] = put_tref(tmpchain.exorder.bl);
		ins_triple(ref0);
		setcurtchain(oldchain);
	} else
	{
		ref0 = maketriple(OC_ZG1);
		ref0->operand[0] = quits;
		ins_triple(ref0);
		setcurtchain(oldchain);
	}
	if (TK_COLON == window_token)
	{	/* post conditional expression */
		advancewindow();
		cr = (oprtype *)mcalloc(SIZEOF(oprtype));
		if (!bool_expr((bool)FALSE, cr))
			return FALSE;
		if (TREF(expr_start) != TREF(expr_start_orig))
		{
			triptr = newtriple(OC_GVRECTARG);
			triptr->operand[0] = put_tref(TREF(expr_start));
		}
		obp = oldchain->exorder.bl;
		dqadd(obp, &tmpchain, exorder);		 /* this is a violation of info hiding */
		if (TREF(expr_start) != TREF(expr_start_orig))
		{
			ref0 = newtriple(OC_JMP);
			ref1 = newtriple(OC_GVRECTARG);
			ref1->operand[0] = put_tref(TREF(expr_start));
			*cr = put_tjmp(ref1);
			tnxtarg(&ref0->operand[0]);
		} else
			tnxtarg(cr);
		return TRUE;
	}
	obp = oldchain->exorder.bl;
	dqadd(obp, &tmpchain, exorder);			/* this is a violation of info hiding */
	return TRUE;
}
예제 #23
0
파일: m_set.c 프로젝트: h4ck3rm1k3/fis-gtm
int m_set(void)
{
	/* Some comment on "parse_warn". It is set to TRUE whenever the parse encounters an
	   invalid setleft target.

	   * Note that even if "parse_warn" is TRUE, we should not return FALSE right away but need to continue the parse
	   * until the end of the current SET command. This way any remaining commands in the current parse line will be
	   * parsed and triples generated for them. This is necessary just in case the currently parsed invalid SET command
	   * does not get executed at runtime (due to postconditionals etc.)
	   *
	   * Some comment on the need for "first_setleft_invalid". This variable is needed only in the
	   * case we encounter an invalid-SVN/invalid-FCN/unsettable-SVN as a target of the SET. We need to evaluate the
	   * right-hand-side of the SET command only if at least one valid setleft target is parsed before an invalid setleft
	   * target is encountered. This is because we still need to execute the valid setlefts at runtime before triggering
	   * a runtime error for the invalid setleft. If the first setleft target is an invalid one, then there is no need
	   * to evaluate the right-hand-side. In fact, in this case, adding triples (corresponding to the right hand side)
	   * to the execution chain could cause problems with emit_code later in the compilation as the destination
	   * for the right hand side triples could now be undefined (for example a valid SVN on the left side of the
	   * SET would have generated an OC_SVPUT triple with one of its operands holding the result of the right
	   * hand side evaluation, but an invalid SVN on the left side which would have instead caused an OC_RTERROR triple
	   * to have been generated leaving no triple to receive the result of the right hand side evaluation thus causing
	   * emit_code to be confused and GTMASSERT). Therefore discard all triples generated by the right hand side in this case.
	   * By the same reasoning, discard all triples generated by setleft targets AFTER this invalid one as well.
	   * "first_setleft_invalid" is set to TRUE if the first setleft target is invalid and set to FALSE if the first setleft
	   * target is valid. It is initialized to -1 before the start of the parse.
	   */

	int		index, setop, delimlen;
	int		first_val_lit, last_val_lit, nakedzalias;
	boolean_t	first_is_lit, last_is_lit, got_lparen, delim1char, is_extract, valid_char;
	boolean_t 	alias_processing, have_lh_alias;
	opctype		put_oc;
	oprtype		v, delimval, firstval, lastval, *result, resptr;
	triple		*curtargchain, *delimiter, discardcurtchain, *first, *get, *jmptrp1, *jmptrp2, *last, *obp, *put;
	triple		*s, *s0, *s1, save_targchain, *save_curtchain, *save_curtchain1, *sub, targchain, *tmp;
	mint		delimlit;
	mval		*delim_mval;
	mvar		*mvarptr;
	boolean_t	parse_warn;	/* set to TRUE in case of an invalid SVN etc. */
	boolean_t	curtchain_switched;	/* set to TRUE if a setcurtchain was done */
	int		first_setleft_invalid;	/* set to TRUE if the first setleft target is invalid */
	boolean_t	temp_subs_was_FALSE;
	union
	{
		uint4		unichar_val;
		unsigned char	unibytes_val[4];
	} unichar;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	TREF(temp_subs) = FALSE;
	dqinit(&targchain, exorder);
	result = (oprtype *)mcalloc(SIZEOF(oprtype));
	resptr = put_indr(result);
	delimiter = sub = last = NULL;
	/* A SET clause must be entirely alias related or a normal set. Parenthized multiple sets of aliases are not allowed
	 * and will trigger an error. This is because the source and targets of aliases require different values and references
	 * than normal sets do and thus cannot be mixed.
	 */
	if (alias_processing = (TK_ASTERISK == window_token))
		advancewindow();
	if (got_lparen = (TK_LPAREN == window_token))
	{
		if (alias_processing)
			stx_error(ERR_NOALIASLIST);
		advancewindow();
		TREF(temp_subs) = TRUE;
	}
	/* Some explanation: The triples from the left hand side of the SET expression that are
	 * expressly associated with fetching (in case of set $piece/$extract) and/or storing of
	 * the target value are removed from curtchain and placed on the targchain. Later, these
	 * triples will be added to the end of curtchain to do the finishing store of the target
	 * after the righthand side has been evaluated. This is per the M standard.
	 *
	 * Note that SET $PIECE/$EXTRACT have special conditions in which the first argument is not referenced at all.
	 * (e.g. set $piece(^a," ",3,2) in this case 3 > 2 so this should not evaluate ^a and therefore should not
	 * modify the naked indicator). That is, the triples that do these conditional checks need to be inserted
	 * ahead of the OC_GVNAME of ^a, all of which need to be inserted on the targchain. But the conditionalization
	 * can be done only after parsing the first argument of the SET $PIECE and examining the remaining arguments.
	 * Therefore we maintain the "curtargchain" variable which stores the value of the "targchain" at the beginning
	 * of the iteration (at the start of the $PIECE parsing) and all the conditionalization will be inserted right
	 * here which is guaranteed to be ahead of where the OC_GVNAME gets inserted.
	 *
	 * For example, SET $PIECE(^A(x,y),delim,first,last)=RHS will generate a final triple chain as follows
	 *
	 *	A - Triples to evaluate subscripts (x,y) of the global ^A
	 *	A - Triples to evaluate delim
	 *	A - Triples to evaluate first
	 *	A - Triples to evaluate last
	 *	B - Triples to evaluate RHS
	 *	C - Triples to do conditional check (e.g. first > last etc.)
	 *	C - Triples to branch around if the checks indicate this is a null operation SET $PIECE
	 *	D - Triple that does OC_GVNAME of ^A
	 *	D - Triple that does OC_SETPIECE to determine the new value
	 *	D - Triple that does OC_GVPUT of the new value into ^A(x,y)
	 *	This is the point where the conditional check triples will branch around to if they chose to.
	 *
	 *	A - triples that evaluates the arguments/subscripts in the left-hand-side of the SET command
	 *		These triples are built in "curtchain"
	 *	B - triples that evaluates the arguments/subscripts in the right-hand-side of the SET command
	 *		These triples are built in "curtchain"
	 *	C - triples that do conditional check for any $PIECE/$EXTRACT in the left side of the SET command.
	 *		These triples are built in "curtargchain"
	 *	D - triples that generate the reference to the target of the SET and the store into the target.
	 *		These triples are built in "targchain"
	 *
	 * Note alias processing does not support the SET *(...)=.. type syntax because the type of argument
	 * created for RHS processing is dependent on the LHS receiver type and we do not support more than one
	 * type of source argument in a single SET.
	 */
	first_setleft_invalid = FIRST_SETLEFT_NOTSEEN;
	curtchain_switched = FALSE;
	nakedzalias = have_lh_alias = FALSE;
	save_curtchain = NULL;
	assert(FIRST_SETLEFT_NOTSEEN != TRUE);
	assert(FIRST_SETLEFT_NOTSEEN != FALSE);
	for (parse_warn = FALSE; ; parse_warn = FALSE)
	{
		curtargchain = targchain.exorder.bl;
		jmptrp1 = jmptrp2 = NULL;
		delim1char = is_extract = FALSE;
		allow_dzwrtac_as_mident();	/* Allows $ZWRTACxxx as target to be treated as an mident */
		switch (window_token)
		{
			case TK_IDENT:
				/* A slight diversion first. If this is a $ZWRTAC set (indication of $ in first char
				 * is currently enough to signify that), then we need to check a few conditions first.
				 * If this is a "naked $ZWRTAC", meaning no numeric suffix, then this is a flag that
				 * all the $ZWRTAC vars in the local variable tree need to be kill *'d which will not
				 * be generating a SET instruction. First we need to verify that fact and make sure
				 * we are not in PARENs and not doing alias processing. Note *any* value can be
				 * specified as the source but while it will be evaluated, it is NOT stored anywhere.
				 */
				if ('$' == *window_ident.addr)
				{	/* We have a $ZWRTAC<xx> target */
					if (got_lparen)
						/* We don't allow $ZWRTACxxx to be specified in a parenthesized list.
						 * Verify that first
						 */
						SYNTAX_ERROR(ERR_DZWRNOPAREN);
					if (STR_LIT_LEN(DOLLAR_ZWRTAC) == window_ident.len)
					{	/* Ok, this is a naked $ZWRTAC targeted set */
						if (alias_processing)
							SYNTAX_ERROR(ERR_DZWRNOALIAS);
						nakedzalias = TRUE;
						/* This opcode doesn't really need args but it is easier to fit in with the rest
						 * of m_set processing to pass it the result arg, which there may actually be
						 * a use for someday..
						 */
						put = maketriple(OC_CLRALSVARS);
						put->operand[0] = resptr;
						dqins(targchain.exorder.bl, exorder, put);
						advancewindow();
						break;
					}
				}
				/* If we are doing alias processing, there are two possibilities:
				 *  1) LHS is unsubscripted - it is an alias variable being created or replaced. Need to parse
				 *  the varname as if this were a regular set.
				 *  2) LHS is subscripted - it is an alias container variable being created or replaced. The
				 *  processing here is to pass the base variable index to the store routine so bypass the
				 *  lvn() call.
				 */
				if (!alias_processing || TK_LPAREN == director_token)
				{	/* Normal variable processing or we have a lh alias container */
					if (!lvn(&v, OC_PUTINDX, 0))
						SYNTAX_ERROR_NOREPORT_HERE;
					if (OC_PUTINDX == v.oprval.tref->opcode)
					{
						dqdel(v.oprval.tref, exorder);
						dqins(targchain.exorder.bl, exorder, v.oprval.tref);
						sub = v.oprval.tref;
						put_oc = OC_PUTINDX;
						if (TREF(temp_subs))
							m_set_create_temporaries(sub, put_oc);
					}
				} else
				{	/* Have alias variable. Argument is index into var table rather than pointer to var */
					have_lh_alias = TRUE;
					/* We only want the variable index in this case. Since the entire hash structure to which
					 * this variable is going to be pointing to is changing, doing anything that calls fetch()
					 * is somewhat pointless so we avoid it by just accessing the variable information
					 * directly.
					 */
					mvarptr = get_mvaddr(&window_ident);
					v = put_ilit(mvarptr->mvidx);
					advancewindow();
				}
				/* Determine correct storing triple */
				put = maketriple((!alias_processing ? OC_STO :
						  (have_lh_alias ? OC_SETALS2ALS : OC_SETALSIN2ALSCT)));
				put->operand[0] = v;
				put->operand[1] = resptr;
				dqins(targchain.exorder.bl, exorder, put);
				break;
			case TK_CIRCUMFLEX:
				if (alias_processing)
					SYNTAX_ERROR(ERR_ALIASEXPECTED);
				s1 = curtchain->exorder.bl;
				if (!gvn())
					SYNTAX_ERROR_NOREPORT_HERE;
				for (sub = curtchain->exorder.bl; sub != s1; sub = sub->exorder.bl)
				{
					put_oc = sub->opcode;
					if (OC_GVNAME == put_oc || OC_GVNAKED == put_oc || OC_GVEXTNAM == put_oc)
						break;
				}
				assert(OC_GVNAME == put_oc || OC_GVNAKED == put_oc || OC_GVEXTNAM == put_oc);
				dqdel(sub, exorder);
				dqins(targchain.exorder.bl, exorder, sub);
				if (TREF(temp_subs))
					m_set_create_temporaries(sub, put_oc);
				put = maketriple(OC_GVPUT);
				put->operand[0] = resptr;
				dqins(targchain.exorder.bl, exorder, put);
				break;
			case TK_ATSIGN:
				if (alias_processing)
					SYNTAX_ERROR(ERR_ALIASEXPECTED);
				if (!indirection(&v))
					SYNTAX_ERROR_NOREPORT_HERE;
				if (!got_lparen && TK_EQUAL != window_token)
				{
					assert(!curtchain_switched);
					put = newtriple(OC_COMMARG);
					put->operand[0] = v;
					put->operand[1] = put_ilit(indir_set);
					return TRUE;
				}
				put = maketriple(OC_INDSET);
				put->operand[0] = v;
				put->operand[1] = resptr;
				dqins(targchain.exorder.bl, exorder, put);
				break;
			case TK_DOLLAR:
				if (alias_processing)
					SYNTAX_ERROR(ERR_ALIASEXPECTED);
				advancewindow();
				if (TK_IDENT != window_token)
					SYNTAX_ERROR(ERR_VAREXPECTED);
				if (TK_LPAREN != director_token)
				{	/* Look for intrinsic special variables */
					s1 = curtchain->exorder.bl;
					if (0 > (index = namelook(svn_index, svn_names, window_ident.addr, window_ident.len)))
					{
						STX_ERROR_WARN(ERR_INVSVN);	/* sets "parse_warn" to TRUE */
					} else if (!svn_data[index].can_set)
					{
						STX_ERROR_WARN(ERR_SVNOSET);	/* sets "parse_warn" to TRUE */
					}
					advancewindow();
					if (!parse_warn)
					{
						if (SV_ETRAP != svn_data[index].opcode && SV_ZTRAP != svn_data[index].opcode)
						{	/* Setting of $ZTRAP or $ETRAP must go through opp_svput because they
							 * may affect the stack pointer. All others directly to op_svput().
							 */
							put = maketriple(OC_SVPUT);
						} else
							put = maketriple(OC_PSVPUT);
						put->operand[0] = put_ilit(svn_data[index].opcode);
						put->operand[1] = resptr;
						dqins(targchain.exorder.bl, exorder, put);
					} else
					{	/* OC_RTERROR triple would have been inserted in curtchain by ins_errtriple
						 * (invoked by stx_error). To maintain consistency with the "if" portion of
						 * this code, we need to move this triple to the "targchain".
						 */
						tmp = curtchain->exorder.bl; /* corresponds to put_ilit(FALSE) in ins_errtriple */
						tmp = tmp->exorder.bl;	/* corresponds to put_ilit(in_error) in ins_errtriple */
						tmp = tmp->exorder.bl;	/* corresponds to newtriple(OC_RTERROR) in ins_errtriple */
						assert(OC_RTERROR == tmp->opcode);
						dqdel(tmp, exorder);
						dqins(targchain.exorder.bl, exorder, tmp);
						CHKTCHAIN(&targchain);
					}
					break;
				}
				/* Only 4 function names allowed on left side: $[Z]Piece and $[Z]Extract */
				index = namelook(fun_index, fun_names, window_ident.addr, window_ident.len);
				if (0 > index)
				{
					STX_ERROR_WARN(ERR_INVFCN);	/* sets "parse_warn" to TRUE */
					/* OC_RTERROR triple would have been inserted in "curtchain" by ins_errtriple
					 * (invoked by stx_error). We need to switch it to "targchain" to be consistent
					 * with every other codepath in this module.
					 */
					tmp = curtchain->exorder.bl; /* corresponds to put_ilit(FALSE) in ins_errtriple */
					tmp = tmp->exorder.bl;	/* corresponds to put_ilit(in_error) in ins_errtriple */
					tmp = tmp->exorder.bl;	/* corresponds to newtriple(OC_RTERROR) in ins_errtriple */
					assert(OC_RTERROR == tmp->opcode);
					dqdel(tmp, exorder);
					dqins(targchain.exorder.bl, exorder, tmp);
					CHKTCHAIN(&targchain);
					advancewindow();	/* skip past the function name */
					advancewindow();	/* skip past the left paren */
					/* Parse the remaining arguments until corresponding RIGHT-PAREN/SPACE/EOL is reached */
					if (!parse_until_rparen_or_space())
						SYNTAX_ERROR_NOREPORT_HERE;
				} else
				{
					switch(fun_data[index].opcode)
					{
						case OC_FNPIECE:
							setop = OC_SETPIECE;
							break;
						case OC_FNEXTRACT:
							is_extract = TRUE;
							setop = OC_SETEXTRACT;
							break;
						case OC_FNZPIECE:
							setop = OC_SETZPIECE;
							break;
						case OC_FNZEXTRACT:
							is_extract = TRUE;
							setop = OC_SETZEXTRACT;
							break;
						default:
							SYNTAX_ERROR(ERR_VAREXPECTED);
					}
					advancewindow();
					advancewindow();
					/* Although we see the get (target) variable first, we need to save it's processing
					 * on another chain -- the targchain -- because the retrieval of the target is bypassed
					 * and the naked indicator is not reset if the first/last parameters are not set in a
					 * logical manner (must be > 0 and first <= last). So the evaluation order is
					 * delimiter (if $piece), first, last, RHS of the set and then the target if applicable.
					 * Set up primary action triple now since it is ref'd by the put triples generated below.
					 */
					s = maketriple(setop);
					/* Even for SET[Z]PIECE and SET[Z]EXTRACT, the SETxxxxx opcodes
					 * do not do the final store, they only create the final value TO be
					 * stored so generate the triples that will actually do the store now.
					 * Note we are still building triples on the original curtchain.
					 */
					switch (window_token)
					{
						case TK_IDENT:
							if (!lvn(&v, OC_PUTINDX, 0))
								SYNTAX_ERROR(ERR_VAREXPECTED);
							if (OC_PUTINDX == v.oprval.tref->opcode)
							{
								dqdel(v.oprval.tref, exorder);
								dqins(targchain.exorder.bl, exorder, v.oprval.tref);
								sub = v.oprval.tref;
								put_oc = OC_PUTINDX;
								if (TREF(temp_subs))
									m_set_create_temporaries(sub, put_oc);
							}
							get = maketriple(OC_FNGET);
							get->operand[0] = v;
							put = maketriple(OC_STO);
							put->operand[0] = v;
							put->operand[1] = put_tref(s);
							break;
						case TK_ATSIGN:
							if (!indirection(&v))
								SYNTAX_ERROR(ERR_VAREXPECTED);
							get = maketriple(OC_INDGET);
							get->operand[0] = v;
							get->operand[1] = put_str(0, 0);
							put = maketriple(OC_INDSET);
							put->operand[0] = v;
							put->operand[1] = put_tref(s);
							break;
						case TK_CIRCUMFLEX:
							s1 = curtchain->exorder.bl;
							if (!gvn())
								SYNTAX_ERROR_NOREPORT_HERE;
							for (sub = curtchain->exorder.bl; sub != s1 ; sub = sub->exorder.bl)
							{
								put_oc = sub->opcode;
								if ((OC_GVNAME == put_oc) || (OC_GVNAKED == put_oc)
								    || (OC_GVEXTNAM == put_oc))
									break;
							}
							assert((OC_GVNAME == put_oc) || (OC_GVNAKED == put_oc)
							       || (OC_GVEXTNAM == put_oc));
							dqdel(sub, exorder);
							dqins(targchain.exorder.bl, exorder, sub);
							if (TREF(temp_subs))
								m_set_create_temporaries(sub, put_oc);
							get = maketriple(OC_FNGVGET);
							get->operand[0] = put_str(0, 0);
							put = maketriple(OC_GVPUT);
							put->operand[0] = put_tref(s);
							break;
						default:
							SYNTAX_ERROR(ERR_VAREXPECTED);
					}
					s->operand[0] = put_tref(get);
					/* Code to fetch args for target triple are on targchain. Put get there now too. */
					dqins(targchain.exorder.bl, exorder, get);
					CHKTCHAIN(&targchain);
					if (!is_extract)
					{	/* Set $[z]piece */
						delimiter = newtriple(OC_PARAMETER);
						s->operand[1] = put_tref(delimiter);
						first = newtriple(OC_PARAMETER);
						delimiter->operand[1] = put_tref(first);
						/* Process delimiter string ($[z]piece only) */
						if (TK_COMMA != window_token)
							SYNTAX_ERROR(ERR_COMMA);
						advancewindow();
						if (!strexpr(&delimval))
							SYNTAX_ERROR_NOREPORT_HERE;
						assert(TRIP_REF == delimval.oprclass);
					} else
					{	/* Set $[Z]Extract */
						first = newtriple(OC_PARAMETER);
						s->operand[1] = put_tref(first);
					}
					/* Process first integer value */
					if (window_token != TK_COMMA)
						firstval = put_ilit(1);
					else
					{
						advancewindow();
						if (!intexpr(&firstval))
							SYNTAX_ERROR(ERR_COMMA);
						assert(firstval.oprclass == TRIP_REF);
					}
					first->operand[0] = firstval;
					if (first_is_lit = (OC_ILIT == firstval.oprval.tref->opcode))
					{
						assert(ILIT_REF ==firstval.oprval.tref->operand[0].oprclass);
						first_val_lit = firstval.oprval.tref->operand[0].oprval.ilit;
					}
					if (TK_COMMA != window_token)
					{	/* There is no "last" value. Only if 1 char literal delimiter and
						 * no "last" value can we generate shortcut code to op_set[z]p1 entry
						 * instead of op_set[z]piece. Note if UTF8 mode is in effect, then this
						 * optimization applies if the literal is one unicode char which may in
						 * fact be up to 4 bytes but will still be passed as a single unsigned
						 * integer.
						 */
						if (!is_extract)
						{
							delim_mval = &delimval.oprval.tref->operand[0].oprval.mlit->v;
							valid_char = TRUE;	/* Basic assumption unles proven otherwise */
							if (delimval.oprval.tref->opcode == OC_LIT &&
							    (1 == (gtm_utf8_mode ?
								   MV_FORCE_LEN(delim_mval) : delim_mval->str.len)))
							{	/* Single char delimiter for set $piece */
								UNICODE_ONLY(
									if (gtm_utf8_mode)
									{	/*  We have a supposed single char delimiter but it
										 *  must be a valid utf8 char to be used by
										 *  op_setp1() and MV_FORCE_LEN won't tell us that.
										 */
										valid_char = UTF8_VALID(delim_mval->str.addr,
													(delim_mval->str.addr
													 + delim_mval->str.len),
													delimlen);
										if (!valid_char && !badchar_inhibit)
											UTF8_BADCHAR(0, delim_mval->str.addr,
												     (delim_mval->str.addr
												      + delim_mval->str.len),
												     0, NULL);
									}
									     );
								if (valid_char || 1 == delim_mval->str.len)
								{	/* This reference to a one character literal or a single
									 * byte invalid utf8 character that needs to be turned into
									 * an explict formated integer literal instead
									 */
									unichar.unichar_val = 0;
									if (!gtm_utf8_mode)
									{	/* Single byte delimiter */
										assert(1 == delim_mval->str.len);
										UNIX_ONLY(s->opcode = OC_SETZP1);
										VMS_ONLY(s->opcode = OC_SETP1);
										unichar.unibytes_val[0] = *delim_mval->str.addr;
									}
									UNICODE_ONLY(
								        else
									{	/* Potentially multiple bytes in one int */
										assert(SIZEOF(int) >= delim_mval->str.len);
										memcpy(unichar.unibytes_val,
										       delim_mval->str.addr,
										       delim_mval->str.len);
										s->opcode = OC_SETP1;
									}
										     );
									delimlit = (mint)unichar.unichar_val;
									delimiter->operand[0] = put_ilit(delimlit);
									delim1char = TRUE;
								}
							}
						}
예제 #24
0
파일: f_text.c 프로젝트: h4ck3rm1k3/fis-gtm
int f_text(oprtype *a, opctype op)
{
	int	implicit_offset = 0;
	triple	*r, *label;

	error_def(ERR_TEXTARG);
	error_def(ERR_RTNNAME);

	r = maketriple(op);
	switch (window_token)
	{
		case TK_CIRCUMFLEX:
			implicit_offset = 1;
			/* CAUTION - fall-through */
		case TK_PLUS:
			r->operand[0] = put_str(zero_mstr.addr, 0);	/* Null label - top of routine */
			break;
		case TK_INTLIT:
			int_label();
			/* CAUTION - fall through */
		case TK_IDENT:
			if (!(cmd_qlf.qlf & CQ_LOWER_LABELS))
				lower_to_upper((uchar_ptr_t)window_ident.addr, (uchar_ptr_t)window_ident.addr, window_ident.len);
			r->operand[0] = put_str(window_ident.addr, window_ident.len);
			advancewindow();
			break;
		case TK_ATSIGN:
			if (!indirection(&(r->operand[0])))
				return FALSE;
			r->opcode = OC_INDTEXT;
			break;
		default:
			stx_error(ERR_TEXTARG);
			return FALSE;
	}
	assert(TK_PLUS == window_token || TK_CIRCUMFLEX == window_token || TK_RPAREN == window_token || TK_EOL == window_token);
	if (OC_INDTEXT != r->opcode || TK_PLUS == window_token || TK_CIRCUMFLEX == window_token)
	{	/* Need another parm chained in to deal with offset and routine name except for the case where an
		 * indirect specifies the entire argument.
		 */
		label = newtriple(OC_PARAMETER);
		r->operand[1] = put_tref(label);
	}
	if (TK_PLUS != window_token)
	{
		if (OC_INDTEXT != r->opcode || TK_CIRCUMFLEX == window_token)
			/* Set default offset (0 or 1 as computed above) when offset not specified */
			label->operand[0] = put_ilit(implicit_offset);
		else
		{	/* Fill in indirect text for case where indirect specifies entire operand */
			r->opcode = OC_INDFUN;
			r->operand[1] = put_ilit((mint)indir_fntext);
		}
	} else
	{	/* Process offset */
		advancewindow();
		if (!intexpr(&(label->operand[0])))
			return FALSE;
	}
	if (TK_CIRCUMFLEX != window_token)
	{	/* No routine specified - default to current routine */
		if (OC_INDFUN != r->opcode)
		{
			if (!run_time)
				label->operand[1] = put_str(routine_name.addr, routine_name.len);
			else
				label->operand[1] = put_tref(newtriple(OC_CURRTN));
		}
	} else
	{	/* Routine has been specified - pull it */
		advancewindow();
		switch(window_token)
		{
			case TK_IDENT:
#				ifdef GTM_TRIGGER
				if (TK_HASH == director_token)
					/* Coagulate tokens as necessary (and available) to allow '#' in the routine name */
					advwindw_hash_in_mname_allowed();
#				endif
				label->operand[1] = put_str(window_ident.addr, window_ident.len);
				advancewindow();
				break;
			case TK_ATSIGN:
				if (!indirection(&label->operand[1]))
					return FALSE;
				r->opcode = OC_INDTEXT;
				break;
			default:
				stx_error(ERR_RTNNAME);
				return FALSE;
		}
	}
	ins_triple(r);
	*a = put_tref(r);
	return TRUE;
}
예제 #25
0
파일: m_zallocate.c 프로젝트: 5HT/mumps
int m_zallocate(void)
{

	triple *ref;
	oprtype indopr;
	bool indirect;

	error_def(ERR_RPARENMISSING);

	newtriple(OC_RESTARTPC);
	indirect = FALSE;
	newtriple(OC_LKINIT);
	switch(window_token)
	{
		case TK_ATSIGN:
			if (!indirection(&indopr))
				return FALSE;
			ref = newtriple(OC_COMMARG);
			ref->operand[0] = indopr;
			if (TK_COLON != window_token)
			{
				ref->operand[1] = put_ilit((mint)indir_zallocate);
				return TRUE;
			}
			ref->operand[1] = put_ilit((mint)indir_nref);
			indirect = TRUE;
			break;
		case TK_LPAREN:
			do
			{
				advancewindow();
				if (EXPR_FAIL == nref())
					return FALSE;
			} while (TK_COMMA == window_token);
			if (TK_RPAREN != window_token)
			{
				stx_error(ERR_RPARENMISSING);
				return FALSE;
			}
			advancewindow();
			break;
		default:
			if (EXPR_FAIL == nref())
				return FALSE;
			break;
	}
	ref = maketriple(OC_ZALLOCATE);
	if (TK_COLON != window_token)
	{
		ref->operand[0] = put_ilit(NO_M_TIMEOUT);
		ins_triple(ref);
	} else
	{
		advancewindow();
		if (!intexpr(&(ref->operand[0])))
			return EXPR_FAIL;
		ins_triple(ref);
		newtriple(OC_TIMTRU);
	}
	return EXPR_GOOD;
}
예제 #26
0
int m_zbreak(void)
{
	triple	*ref, *next;
	oprtype label, offset, routine, action, count;
	bool 	cancel, cancel_all, is_count, dummybool;
	error_def(ERR_LABELEXPECTED);
	error_def(ERR_RTNNAME);

	label = put_str((char *)&zero_ident.c[0], sizeof(mident));
	cancel_all = FALSE;
	action = put_str("B", 1);
	if (window_token == TK_MINUS)
	{
		advancewindow();
		cancel = TRUE;
		count = put_ilit((mint)CANCEL_ONE);
	} else
	{
		cancel = FALSE;
		count = put_ilit((mint)0);
	}
	if (window_token == TK_ASTERISK)
	{
		if (cancel)
		{
			advancewindow();
			cancel_all = TRUE;
			if (!run_time)
				routine = put_str(&routine_name[0], sizeof(mident));
			else
				routine = put_tref(newtriple(OC_CURRTN));
			offset = put_ilit((mint) 0);
			count = put_ilit((mint) CANCEL_ALL);
		} else
		{
			stx_error(ERR_LABELEXPECTED);
			return FALSE;
		}
	} else
	{
		offset = put_ilit((mint) 0);
		if (!lref(&label,&offset, TRUE, indir_zbreak, !cancel, &dummybool))
			return FALSE;
		if (label.oprclass == TRIP_REF && label.oprval.tref->opcode == OC_COMMARG)
			return TRUE;
		if (window_token != TK_CIRCUMFLEX)
		{
			if (!run_time)
				routine = put_str(&routine_name[0], sizeof(mident));
			else
				routine = put_tref(newtriple(OC_CURRTN));
		} else
		{
			advancewindow();
			switch(window_token)
			{
			case TK_IDENT:
				routine = put_str(&window_ident.c[0], sizeof(mident));
				advancewindow();
				break;
			case TK_ATSIGN:
				if (!indirection(&routine))
					return FALSE;
				break;
			default:
				stx_error(ERR_RTNNAME);
				return FALSE;
			}
		}
		if (!cancel && window_token == TK_COLON)
		{
			advancewindow();
			if (window_token == TK_COLON)
			{
				is_count = TRUE;
				action = put_str("B",1);
			} else
			{
				if (!strexpr(&action))
					return FALSE;
				is_count = window_token == TK_COLON;
			}
			if (is_count)
			{
				advancewindow();
				if (!intexpr(&count))
					return FALSE;
			}
		}
	}
	ref = newtriple(OC_SETZBRK);
	ref->operand[0] = label;
	next = newtriple(OC_PARAMETER);
	ref->operand[1] = put_tref(next);
	next->operand[0] = offset;
	ref = newtriple(OC_PARAMETER);
	next->operand[1] = put_tref(ref);
	ref->operand[0] = routine;
	next = newtriple(OC_PARAMETER);
	ref->operand[1] = put_tref(next);
	next->operand[0] = action;
	ref = newtriple(OC_PARAMETER);
	next->operand[1] = put_tref(ref);
	ref->operand[0] = count;
	return TRUE;
}
예제 #27
0
파일: f_char.c 프로젝트: h4ck3rm1k3/fis-gtm
int f_char(oprtype *a, opctype op)
{
	triple 		*root, *last, *curr;
	oprtype 	argv[CHARMAXARGS], *argp;
	mval		 v;
	boolean_t 	all_lits;
	unsigned char 	*base, *outptr, *tmpptr;
	int 		argc, ch, size, char_len;

	error_def(ERR_FCHARMAXARGS);
	error_def(ERR_INVDLRCVAL);

	/* If we are not in UTF8 mode, we need to reroute to the $ZCHAR function to
	   handle things correctly.
	*/
	if (!gtm_utf8_mode)
		return f_zchar(a, op);

	all_lits = TRUE;
	argp = &argv[0];
	argc = 0;
	for (;;)
	{
		if (!intexpr(argp))
			return FALSE;
		assert(argp->oprclass == TRIP_REF);
		if (argp->oprval.tref->opcode != OC_ILIT)
			all_lits = FALSE;
		argc++;
		argp++;
		if (window_token != TK_COMMA)
			break;
		advancewindow();
		if (argc >= CHARMAXARGS)
		{
			stx_error(ERR_FCHARMAXARGS);
			return FALSE;
		}
	}
	if (all_lits)
	{	/* All literals, build the function inline */
		size = argc * GTM_MB_LEN_MAX;
		ENSURE_STP_FREE_SPACE(size);
		base = stringpool.free;
		argp = &argv[0];
		for (outptr = base, char_len = 0; argc > 0; --argc, argp++)
		{	/* For each wide char value, convert to unicode chars in stringpool buffer */
			ch = argp->oprval.tref->operand[0].oprval.ilit;
			if (ch >= 0)
			{ /* As per the M standard, negative code points should map to no characters */
				tmpptr = UTF8_WCTOMB(ch, outptr);
				assert(tmpptr - outptr <= 4);
				if (tmpptr != outptr)
					++char_len; /* yet another valid character. update the character length */
				else if (!badchar_inhibit)
					stx_error(ERR_INVDLRCVAL, 1, ch);
				outptr = tmpptr;
			}
		}
		stringpool.free = outptr;
		MV_INIT_STRING(&v, outptr - base, base);
		v.str.char_len = char_len;
		v.mvtype |= MV_UTF_LEN;
		s2n(&v);
		*a = put_lit(&v);
		return TRUE;
	}
	root = maketriple(op);
	root->operand[0] = put_ilit(argc + 1);
	last = root;
	argp = &argv[0];
	for (; argc > 0 ;argc--, argp++)
	{
		curr = newtriple(OC_PARAMETER);
		curr->operand[0] = *argp;
		last->operand[1] = put_tref(curr);
		last = curr;
	}
	ins_triple(root);
	*a = put_tref(root);
	return TRUE;
}
예제 #28
0
파일: m_write.c 프로젝트: 5HT/mumps
int m_write(void)
{
	error_def(ERR_STRINGOFLOW);
	oprtype x,*oprptr;
	mval lit;
	mstr *msp;
	int  lnx;
	char *cp;
	triple *ref, *t1;
	triple *litlst[128], **llptr, **ptx, **ltop;

	llptr = litlst;
	ltop = 0;
	*llptr = 0;
	for (;;)
	{
		devctlexp = FALSE;
		switch(window_token)
		{
		case TK_ASTERISK:
			advancewindow();
			if (!intexpr(&x))
				return FALSE;
			assert(x.oprclass == TRIP_REF);
			ref = newtriple(OC_WTONE);
			ref->operand[0] = x;
			STO_LLPTR((x.oprval.tref->opcode == OC_ILIT) ? ref : 0);
			break;
		case TK_QUESTION:
		case TK_EXCLAIMATION:
		case TK_HASH:
		case TK_SLASH:
			if (!rwformat())
				return FALSE;
			STO_LLPTR(0);
			break;
		default:
			switch (strexpr(&x))
			{
			case EXPR_FAIL:
				return FALSE;
			case EXPR_GOOD:
				assert(x.oprclass == TRIP_REF);
				if (devctlexp)
				{
					ref = newtriple(OC_WRITE);
					ref->operand[0] = x;
					STO_LLPTR(0);
				} else if (x.oprval.tref->opcode == OC_CAT)
				{
					wrtcatopt(x.oprval.tref,&llptr,LITLST_TOP);
				} else
				{
					ref = newtriple(OC_WRITE);
					ref->operand[0] = x;
					STO_LLPTR((x.oprval.tref->opcode == OC_LIT) ? ref : 0);
				}
				break;
			case EXPR_INDR:
				make_commarg(&x,indir_write);
				STO_LLPTR(0);
				break;
			default:
				assert(FALSE);
			}
			break;
		}
		if (window_token != TK_COMMA)
			break;
		advancewindow();
		if (llptr >= LITLST_TOP)
		{
			*++llptr = 0;
			ltop = llptr;
			llptr = 0;
		}
	}
	STO_LLPTR(0);
	if (ltop)
		llptr = ltop;
	for (ptx = litlst ; ptx < llptr ; ptx++)
	{
		if (*ptx && *(ptx + 1))
		{
			lit.mvtype = MV_STR;
			lit.str.addr = cp = (char * ) stringpool.free;
			for (t1 = ref = *ptx++ ; ref ; ref = *ptx++)
			{
				if (ref->opcode == OC_WRITE)
				{
					msp = &(ref->operand[0].oprval.tref->operand[0].oprval.mlit->v.str);
					lnx = msp->len;
					if ( cp + lnx > (char *) stringpool.top)
					{	stx_error(ERR_STRINGOFLOW);
						return FALSE;
					}
					memcpy(cp, msp->addr, lnx);
					cp += lnx;
				}
				else
				{
					assert(ref->opcode == OC_WTONE);
					if (cp + 1 > (char *) stringpool.top)
					{	stx_error(ERR_STRINGOFLOW);
						return FALSE;
					}
					*cp++ = ref->operand[0].oprval.tref->operand[0].oprval.ilit;
				}
				ref->operand[0].oprval.tref->opcode = OC_NOOP;
				ref->opcode = OC_NOOP;
				ref->operand[0].oprval.tref->operand[0].oprclass = OC_NOOP;
				ref->operand[0].oprclass = 0;
			}
			ptx--;
			stringpool.free = (unsigned char *) cp;
			lit.str.len = INTCAST(cp - lit.str.addr);
			s2n(&lit);
			t1->opcode = OC_WRITE;
			t1->operand[0] = put_lit(&lit);
		}
	}
	return TRUE;
}
예제 #29
0
triple *entryref(opctype op1, opctype op2, mint commargcode, boolean_t can_commarg, boolean_t labref, boolean_t textname)
{
	oprtype 	offset, label, routine, rte1;
	char		rtn_text[SIZEOF(mident_fixed)], lab_text[SIZEOF(mident_fixed)];
	mident		rtnname, labname;
	mstr 		rtn_str, lbl_str;
	triple 		*ref, *next, *rettrip;
	boolean_t	same_rout;

	rtnname.len = labname.len = 0;
	rtnname.addr = &rtn_text[0];
	labname.addr = &lab_text[0];
	/* These cases don't currently exist but if they start to exist, the code in this
	 * routine needs to be revisited for proper operation as the textname conditions
	 * were assumed not to happen if can_commarg was FALSE (which it is in the one
	 * known use of textname TRUE - in m_zgoto).
	 */
	assert(!(can_commarg && textname));
	switch (window_token)
	{
		case TK_INTLIT:
			int_label();
			/* caution: fall through */
		case TK_IDENT:
			memcpy(labname.addr, window_ident.addr, window_ident.len);
			labname.len = window_ident.len;
			advancewindow();
			if ((TK_PLUS != window_token) && (TK_CIRCUMFLEX != window_token) && !IS_MCODE_RUNNING && can_commarg)
			{
				rettrip = newtriple(op1);
				rettrip->operand[0] =  put_mlab(&labname);
				return rettrip;
			}
			label.oprclass = 0;
			break;
		case TK_ATSIGN:
			if(!indirection(&label))
				return NULL;
			if ((TK_PLUS != window_token) && (TK_CIRCUMFLEX != window_token) && (TK_COLON != window_token)
			    && can_commarg)
			{
				rettrip = ref = maketriple(OC_COMMARG);
				ref->operand[0] = label;
				ref->operand[1] = put_ilit(commargcode);
				ins_triple(ref);
				return rettrip;
			}
			labname.len = 0;
			break;
		case TK_PLUS:
			stx_error(ERR_LABELEXPECTED);
			return NULL;
		default:
			labname.len = 0;
			label.oprclass = 0;
			break;
	}
	if (!labref && (TK_PLUS == window_token))
	{	/* Have line offset specified */
		advancewindow();
		if (!intexpr(&offset))
			return NULL;
	} else
		offset.oprclass = 0;
	if (TK_CIRCUMFLEX == window_token)
	{	/* Have a routine name specified */
		advancewindow();
		switch(window_token)
		{
			case TK_IDENT:
				MROUT2XTERN(window_ident.addr, rtnname.addr, window_ident.len);
				rtn_str.len = rtnname.len = window_ident.len;
				rtn_str.addr = rtnname.addr;
				advancewindow();
				if (!IS_MCODE_RUNNING)
				{	/* Triples for indirect code */
					same_rout = (MIDENT_EQ(&rtnname, &routine_name) && can_commarg);
					if (!textname)
					{	/* Resolve routine and label names to addresses for most calls */
						if (!label.oprclass && !offset.oprclass)
						{	/* Routine only (no label or offset) */
							if (same_rout)
							{
								rettrip = newtriple(op1);
								rettrip->operand[0] =  put_mlab(&labname);
							} else
							{
								rettrip = maketriple(op2);
								if (rtnname.addr[0] == '%')
									rtnname.addr[0] = '_';
								rettrip->operand[0] = put_cdlt(&rtn_str);
								mlabel2xtern(&lbl_str, &rtnname, &labname);
								rettrip->operand[1] = put_cdlt(&lbl_str);
								ins_triple(rettrip);
							}
							return rettrip;
						} else if (!same_rout)
						{
							rte1 = put_str(rtn_str.addr, rtn_str.len);
							if (rtnname.addr[0] == '%')
								rtnname.addr[0] = '_';
							routine = put_cdlt(&rtn_str);
							ref = newtriple(OC_RHDADDR);
							ref->operand[0] = rte1;
							ref->operand[1] = routine;
							routine = put_tref(ref);
						} else
							routine = put_tref(newtriple(OC_CURRHD));
					} else
					{	/* Return the actual names used */
						if (!label.oprclass && !offset.oprclass)
						{	/* Routine only (no label or offset) */
							rettrip = maketriple(op2);
							rettrip->operand[0] = put_str(rtn_str.addr, rtn_str.len);
							ref = newtriple(OC_PARAMETER);
							ref->operand[0] = put_str(labname.addr, labname.len);
							ref->operand[1] = put_ilit(0);
							rettrip->operand[1] = put_tref(ref);
							ins_triple(rettrip);
							return rettrip;
						} else
							routine = put_str(rtn_str.addr, rtn_str.len);
					}

				} else
				{	/* Triples for normal compiled code */
					routine = put_str(rtn_str.addr, rtn_str.len);
					if (!textname)
					{	/* If not returning text name, convert text name to routine header address */
						ref = newtriple(OC_RHDADDR1);
						ref->operand[0] = routine;
						routine = put_tref(ref);
					}
				}
				break;
			case TK_ATSIGN:
				if (!indirection(&routine))
					return NULL;
				if (!textname)
				{	/* If not returning text name, convert text name to routine header address */
					ref = newtriple(OC_RHDADDR1);
					ref->operand[0] = routine;
					routine = put_tref(ref);
				}
				break;
			default:
				stx_error(ERR_RTNNAME);
				return NULL;
		}
	} else
	{
		if (!label.oprclass && (0 == labname.len))
		{
			stx_error(ERR_LABELEXPECTED);
			return NULL;
		}
		if (!textname)
			routine = put_tref(newtriple(OC_CURRHD));
		else
		{	/* If we need a name, the mechanism to retrieve it differs between normal and indirect compilation */
			if (!IS_MCODE_RUNNING)
				/* For normal compile, use routine name set when started compile */
				routine = put_str(routine_name.addr, routine_name.len);
			else
				/* For an indirect compile, obtain the currently running routine header and pull the routine
				 * name out of that.
				 */
				routine = put_str(frame_pointer->rvector->routine_name.addr,
						  frame_pointer->rvector->routine_name.len);
		}
	}
	if (!offset.oprclass)
		offset = put_ilit(0);
	if (!label.oprclass)
		label = put_str(labname.addr, labname.len);
	ref = textname ? newtriple(OC_PARAMETER) : newtriple(OC_LABADDR);
	ref->operand[0] = label;
	next = newtriple(OC_PARAMETER);
	ref->operand[1] = put_tref(next);
	next->operand[0] = offset;
	if (!textname)
		next->operand[1] = routine;	/* Not needed if giving text names */
	rettrip = next = newtriple(op2);
	next->operand[0] = routine;
	next->operand[1] = put_tref(ref);
	return rettrip;
}
예제 #30
0
int f_char(oprtype *a, opctype op)
{
	triple *root, *last, *curr;
	oprtype argv[CHARMAXARGS], *argp;
	mval v;
	bool all_lits;
	char *c;
	int argc, i;
	error_def(ERR_FCHARMAXARGS);

	all_lits = TRUE;
	argp = &argv[0];
	argc = 0;
	for (;;)
	{
		if (!intexpr(argp))
			return FALSE;
		assert(argp->oprclass == TRIP_REF);
		if (argp->oprval.tref->opcode != OC_ILIT)
			all_lits = FALSE;
		argc++;
		argp++;
		if (window_token != TK_COMMA)
			break;
		advancewindow();
		if (argc >= CHARMAXARGS)
		{	stx_error(ERR_FCHARMAXARGS);
			return FALSE;
		}
	}
	if (all_lits)
	{
		if (stringpool.top - stringpool.free < argc)
			stp_gcol(argc);
		v.mvtype = MV_STR;
		v.str.addr = c = (char *) stringpool.free;
		argp = &argv[0];
		for (; argc > 0 ;argc--, argp++)
		{
			i = argp->oprval.tref->operand[0].oprval.ilit;
			if ((i >= 0) && (i < 256))	/* only true for single byte character set */
				*c++ = i;
		}
		v.str.len = c - v.str.addr;
		stringpool.free =(unsigned char *)  c;
		s2n(&v);
		*a = put_lit(&v);
		return TRUE;
	}
	root = maketriple(op);
	root->operand[0] = put_ilit(argc + 2);
	curr = newtriple(OC_PARAMETER);
	curr->operand[0] = put_ilit(0);
	root->operand[1] = put_tref(curr);
	last = curr;
	argp = &argv[0];
	for (; argc > 0 ;argc--, argp++)
	{
		curr = newtriple(OC_PARAMETER);
		curr->operand[0] = *argp;
		last->operand[1] = put_tref(curr);
		last = curr;
	}
	ins_triple(root);
	*a = put_tref(root);
	return TRUE;
}