void XmdsExprSetDefaultNid(Widget w,int nid) { XmdsExprWidget ew = (XmdsExprWidget) w; if (nid != ew->expr.default_nid) { ew->expr.default_nid = nid; LoadExpr(ew,(struct descriptor *) ew->expr.xd); Resize((Widget) ew); } }
void XmdsExprReset(Widget w) { XmdsExprWidget ew = (XmdsExprWidget) w; if (ew->expr.nid) XmdsExprSetNid(w,ew->expr.nid,ew->expr.nid_offset); else { LoadExpr(ew,(struct descriptor *) ew->expr.xd); Resize((Widget) ew); } }
unsigned Test (unsigned Label, int Invert) /* Evaluate a boolean test expression and jump depending on the result of ** the test and on Invert. The function returns one of the TESTEXPR_xx codes ** defined above. If the jump is always true, a warning is output. */ { ExprDesc Expr; unsigned Result; /* Read a boolean expression */ BoolExpr (hie0, &Expr); /* Check for a constant expression */ if (ED_IsConstAbs (&Expr)) { /* Result is constant, so we know the outcome */ Result = (Expr.IVal != 0); /* Constant rvalue */ if (!Invert && Expr.IVal == 0) { g_jump (Label); Warning ("Unreachable code"); } else if (Invert && Expr.IVal != 0) { g_jump (Label); } } else { /* Result is unknown */ Result = TESTEXPR_UNKNOWN; /* If the expr hasn't set condition codes, set the force-test flag */ if (!ED_IsTested (&Expr)) { ED_MarkForTest (&Expr); } /* Load the value into the primary register */ LoadExpr (CF_FORCECHAR, &Expr); /* Generate the jump */ if (Invert) { g_truejump (CF_NONE, Label); } else { g_falsejump (CF_NONE, Label); } } /* Return the result */ return Result; }
void XmdsExprSetXd(Widget w,struct descriptor *dsc) { XmdsExprWidget ew = (XmdsExprWidget) w; if (ew->expr.xd) MdsFree1Dx(ew->expr.xd, 0); else { ew->expr.xd = (struct descriptor_xd *) XtMalloc(sizeof(struct descriptor_xd)); *ew->expr.xd = empty_xd; } MdsCopyDxXd(dsc,ew->expr.xd); LoadExpr(ew,(struct descriptor *) ew->expr.xd); Resize((Widget) ew); }
void XmdsExprSetNid(Widget w,int nid,int offset) { XmdsExprWidget ew = (XmdsExprWidget) w; int new_nid; int status; if (ew->expr.xd) MdsFree1Dx(ew->expr.xd, 0); else { ew->expr.xd = (struct descriptor_xd *) XtMalloc(sizeof(struct descriptor_xd)); *ew->expr.xd = empty_xd; } if (nid == -1) ew->expr.nid = XmdsGetDeviceNid(); new_nid = ew->expr.nid + offset; status = TreeGetRecord(new_nid,ew->expr.xd); if (status & 1) LoadExpr(ew,(struct descriptor *) ew->expr.xd); else LoadExpr(ew,0); Resize((Widget) ew); ew->expr.nid_offset = offset; }
static void ParseArg (ArgDesc* Arg, Type* Type) /* Parse one argument but do not push it onto the stack. Make all fields in * Arg valid. */ { /* We have a prototype, so chars may be pushed as chars */ Arg->Flags = CF_FORCECHAR; /* Remember the required argument type */ Arg->ArgType = Type; /* Read the expression we're going to pass to the function */ MarkedExprWithCheck (hie1, &Arg->Expr); /* Remember the actual argument type */ Arg->Type = Arg->Expr.Type; /* Convert this expression to the expected type */ TypeConversion (&Arg->Expr, Type); /* Remember the following code position */ GetCodePos (&Arg->Load); /* If the value is a constant, set the flag, otherwise load it into the * primary register. */ if (ED_IsConstAbsInt (&Arg->Expr) && ED_CodeRangeIsEmpty (&Arg->Expr)) { /* Remember that we have a constant value */ Arg->Flags |= CF_CONST; } else { /* Load into the primary */ LoadExpr (CF_NONE, &Arg->Expr); } /* Remember the following code position */ GetCodePos (&Arg->Push); GetCodePos (&Arg->End); /* Use the type of the argument for the push */ Arg->Flags |= TypeOf (Arg->Expr.Type); }
static void ReturnStatement (void) /* Handle the 'return' statement */ { ExprDesc Expr; NextToken (); if (CurTok.Tok != TOK_SEMI) { /* Evaluate the return expression */ hie0 (&Expr); /* If we return something in a void function, print an error and ** ignore the value. Otherwise convert the value to the type of the ** return. */ if (F_HasVoidReturn (CurrentFunc)) { Error ("Returning a value in function with return type void"); } else { /* Convert the return value to the type of the function result */ TypeConversion (&Expr, F_GetReturnType (CurrentFunc)); /* Load the value into the primary */ LoadExpr (CF_NONE, &Expr); } } else if (!F_HasVoidReturn (CurrentFunc) && !F_HasOldStyleIntRet (CurrentFunc)) { Error ("Function `%s' must return a value", F_GetFuncName (CurrentFunc)); } /* Mark the function as having a return statement */ F_ReturnFound (CurrentFunc); /* Cleanup the stack in case we're inside a block with locals */ g_space (StackPtr - F_GetTopLevelSP (CurrentFunc)); /* Output a jump to the function exit code */ g_jump (F_GetRetLab (CurrentFunc)); }
int Statement (int* PendingToken) /* Statement parser. Returns 1 if the statement does a return/break, returns ** 0 otherwise. If the PendingToken pointer is not NULL, the function will ** not skip the terminating token of the statement (closing brace or ** semicolon), but store true if there is a pending token, and false if there ** is none. The token is always checked, so there is no need for the caller to ** check this token, it must be skipped, however. If the argument pointer is ** NULL, the function will skip the token. */ { ExprDesc Expr; int GotBreak; CodeMark Start, End; /* Assume no pending token */ if (PendingToken) { *PendingToken = 0; } /* Check for a label. A label is always part of a statement, it does not ** replace one. */ while (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) { /* Handle the label */ DoLabel (); if (CheckLabelWithoutStatement ()) { return 0; } } switch (CurTok.Tok) { case TOK_LCURLY: NextToken (); GotBreak = CompoundStatement (); CheckTok (TOK_RCURLY, "`{' expected", PendingToken); return GotBreak; case TOK_IF: return IfStatement (); case TOK_WHILE: WhileStatement (); break; case TOK_DO: DoStatement (); break; case TOK_SWITCH: SwitchStatement (); break; case TOK_RETURN: ReturnStatement (); CheckSemi (PendingToken); return 1; case TOK_BREAK: BreakStatement (); CheckSemi (PendingToken); return 1; case TOK_CONTINUE: ContinueStatement (); CheckSemi (PendingToken); return 1; case TOK_FOR: ForStatement (); break; case TOK_GOTO: GotoStatement (); CheckSemi (PendingToken); return 1; case TOK_SEMI: /* Ignore it */ CheckSemi (PendingToken); break; case TOK_PRAGMA: DoPragma (); break; case TOK_CASE: CaseLabel (); CheckLabelWithoutStatement (); break; case TOK_DEFAULT: DefaultLabel (); CheckLabelWithoutStatement (); break; default: /* Remember the current code position */ GetCodePos (&Start); /* Actual statement */ ExprWithCheck (hie0, &Expr); /* Load the result only if it is an lvalue and the type is ** marked as volatile. Otherwise the load is useless. */ if (ED_IsLVal (&Expr) && IsQualVolatile (Expr.Type)) { LoadExpr (CF_NONE, &Expr); } /* If the statement didn't generate code, and is not of type ** void, emit a warning. */ GetCodePos (&End); if (CodeRangeIsEmpty (&Start, &End) && !IsTypeVoid (Expr.Type) && IS_Get (&WarnNoEffect)) { Warning ("Statement has no effect"); } CheckSemi (PendingToken); } return 0; }
static void DoConversion (ExprDesc* Expr, const Type* NewType) /* Emit code to convert the given expression to a new type. */ { Type* OldType; unsigned OldSize; unsigned NewSize; /* Remember the old type */ OldType = Expr->Type; /* If we're converting to void, we're done. Note: This does also cover a * conversion void -> void. */ if (IsTypeVoid (NewType)) { ED_MakeRVal (Expr); /* Never an lvalue */ goto ExitPoint; } /* Don't allow casts from void to something else. */ if (IsTypeVoid (OldType)) { Error ("Cannot convert from `void' to something else"); goto ExitPoint; } /* Get the sizes of the types. Since we've excluded void types, checking * for known sizes makes sense here. */ OldSize = CheckedSizeOf (OldType); NewSize = CheckedSizeOf (NewType); /* lvalue? */ if (ED_IsLVal (Expr)) { /* We have an lvalue. If the new size is smaller than the new one, * we don't need to do anything. The compiler will generate code * to load only the portion of the value that is actually needed. * This works only on a little endian architecture, but that's * what we support. * If both sizes are equal, do also leave the value alone. * If the new size is larger, we must convert the value. */ if (NewSize > OldSize) { /* Load the value into the primary */ LoadExpr (CF_NONE, Expr); /* Emit typecast code */ g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR); /* Value is now in primary and an rvalue */ ED_MakeRValExpr (Expr); } } else if (ED_IsLocAbs (Expr)) { /* A cast of a constant numeric value to another type. Be sure * to handle sign extension correctly. */ /* Get the current and new size of the value */ unsigned OldBits = OldSize * 8; unsigned NewBits = NewSize * 8; /* Check if the new datatype will have a smaller range. If it * has a larger range, things are ok, since the value is * internally already represented by a long. */ if (NewBits <= OldBits) { /* Cut the value to the new size */ Expr->IVal &= (0xFFFFFFFFUL >> (32 - NewBits)); /* If the new type is signed, sign extend the value */ if (IsSignSigned (NewType)) { if (Expr->IVal & (0x01UL << (NewBits-1))) { /* Beware: Use the safe shift routine here. */ Expr->IVal |= shl_l (~0UL, NewBits); } } } } else {
ObjectExpression_BranchIf(ObjectLoad &arc) : Super(arc), exprC(LoadExpr(arc)) {}