예제 #1
0
inspect_type WndGetExprSPInspectType( address *paddr )
{
    sym_info    info;
    DIPHDL( sym, sh );

    LValue( ExprSP );
    *paddr = NilAddr;
    if( ExprSP->info.kind == TK_FUNCTION ) {
        ExprValue( ExprSP );
        *paddr = ExprSP->v.addr;
        PopEntry();
        return( INSP_CODE );
    } else if( (ExprSP->flags & SF_LOCATION) && ExprSP->th != NULL && !IsInternalMod( TypeMod( ExprSP->th ) ) ) {
        if( ExprSP->v.loc.num == 1 && ExprSP->v.loc.e[0].type == LT_ADDR ) {
            *paddr = ExprSP->v.loc.e[0].u.addr;
        }
        PopEntry();
        return( INSP_DATA );
    } else {
        if( (ExprSP->flags & SF_LOCATION) && ExprSP->v.loc.e[0].type == LT_ADDR ) {
            *paddr = ExprSP->v.loc.e[0].u.addr;
        } else if( ExprSP->info.kind == TK_ADDRESS
                || ExprSP->info.kind == TK_POINTER ) {
            *paddr = ExprSP->v.addr;
        }
        if( !IS_NIL_ADDR( (*paddr) ) ) {
            AddrFloat( paddr );
            if( DeAliasAddrSym( NO_MOD, *paddr, sh ) != SR_NONE ) {
                SymInfo( sh, ExprSP->lc, &info );
                PopEntry();
                switch( info.kind ) {
                case SK_CODE:
                case SK_PROCEDURE:
                    return( INSP_CODE );
                    break;
                default:
                    return( INSP_RAW_DATA );
                    break;
                }
            }
        }
    }
    ExprValue( ExprSP );
    MakeMemoryAddr( TRUE, EXPR_DATA, paddr );
    return( INSP_RAW_DATA );
}
예제 #2
0
static void GlobalOptInt( char *name, int *value )
    {
    EXPR *expr ;

    expr = Label( name ) ;
    expr = ExprGetDefinition( expr ) ;
    if( !expr )
	return ;
    *value = (int) ExprValue( expr ) ;
    }
예제 #3
0
static void GlobalOptReal( char *name, double *value )
    {
    EXPR *expr ;

    expr = Label( name ) ;
    expr = ExprGetDefinition( expr ) ;
    if( !expr )
	return ;
    *value = ExprValue( expr ) ;
    }
예제 #4
0
// The following routine is cut & pasted verbatim from dbgwvar.c
// (which we really don't want to drag in here)
var_node *VarGetDisplayPiece( var_info *i, int row, int piece, int *pdepth, int *pinherit )
{
    var_node    *row_v;
    var_node    *v;

    if( piece >= VAR_PIECE_LAST ) return( NULL );
    if( VarFirstNode( i ) == NULL ) return( NULL );
    if( row >= VarRowTotal( i ) ) return( NULL );
    row_v = VarFindRowNode( i, row );
    if( !row_v->value_valid ) {
        VarSetValue( row_v, LIT_ENG( Quest_Marks ) );
        row_v->value_valid = false;
    }
    if( !row_v->gadget_valid ) {
        VarSetGadget( row_v, VARGADGET_NONE );
        row_v->gadget_valid = false;
    }
    v = row_v;
    if( piece == VAR_PIECE_NAME ||
        ( piece == VAR_PIECE_GADGET && row_v->gadget_valid ) ||
        ( piece == VAR_PIECE_VALUE && row_v->value_valid ) ) {
        VarError = false;
    } else if( _IsOff( SW_TASK_RUNNING ) ) {
        if( row == i->exprsp_cacherow && i->exprsp_cache != NULL ) {
            VarError = false;
            v = i->exprsp_cache;
        } else if( row == i->exprsp_cacherow && i->exprsp_cache_is_error ) {
            VarError = true;
            v = NULL;
        } else {
            VarErrState();
            v = VarFindRow( i, row );
            VarOldErrState();
            i->exprsp_cacherow = row;
            i->exprsp_cache = v;
            i->exprsp_cache_is_error = VarError;
        }
        if( v == NULL ) {
            if( !VarError ) return( NULL );
            v = row_v;
        }
        VarNodeInvalid( v );
        VarErrState();
        ExprValue( ExprSP );
        VarSetGadget( v, VarGetGadget( v ) );
        VarSetOnTop( v, VarGetOnTop( v ) );
        VarSetValue( v, VarGetValue( i, v ) );
        VarOldErrState();
        VarDoneRow( i );
    }
    VarGetDepths( i, v, pdepth, pinherit );
    return( v );
}
예제 #5
0
파일: cat.c 프로젝트: skewray/skewray_old
double MatCTECat( EXPR *name, EXPR *nothing )
    {
    char *string ;

    string = ExprValueString( name ) ;
    if( !string )
	{
	IOerror( MatBomb, "MatCTECat", "cannot evaluate name" ) ;
	return nan("") ;
	}
    return ExprValue( DbaseGetExpr( string, "CTE" ) ) ;
    }
예제 #6
0
double SystemGetNumber( char *string )
    {
    EXPR *expr ;

    expr = Label( string ) ;
    expr = ExprGetDefinition( expr ) ;
    if( !expr )
	{
	IOerror( IO_WARN, "SystemGetNumber",
	    "no value set for `%s'", string ) ;
	return 0.0 ;
	}
    return ExprValue( expr ) ;
    }
예제 #7
0
static FUNC *ConvertTransform( FUNC *func, EDAT xform[16] )
    {
    int d, which ;
    FUNC *loop ;
    static EDAT gnew[16] = ZERO_EDAT_16 ;
    EXPR *arg, *expr ;

    MatrixMultiInit(4) ;

    for( loop = func ; loop ; loop = OpticForward( FuncNext(loop) ) )
	{
	which = (int) ( ExprValue( FuncArg( loop, 0 ) ) + 0.49 ) ;

	if( which > 5 )				/* surface */
	    break ;

	arg = Copy( FuncArg( loop, 1 ) ) ;
	if( FuncIsReversed( loop ) )
	    arg = Ecc( arg, "u-", Garbage() ) ;

	MatrixIdentity( 4, gnew ) ;
	if( which < 3 )
	    gnew[ RC( which, 3 ) ].E = ECc( arg, "u-", Garbage() ) ;
	else
	    {
	    d = which - 3 ;
	    expr = ECc( arg, "cos", Garbage() ) ;
	    gnew[ RC( (d+1)%3, (d+1)%3 ) ].E = Copy( expr ) ;
	    gnew[ RC( (d+2)%3, (d+2)%3 ) ].E = expr ;
	    expr = ECc( arg, "sin", Garbage() ) ;
	    gnew[ RC( (d+1)%3, (d+2)%3 ) ].E = Copy( expr ) ;
	    expr = Ecc( expr, "u-", Garbage() ) ;
	    gnew[ RC( (d+2)%3, (d+1)%3 ) ].E = expr ;
	    }

	Free( arg ) ;

	MatrixMultiNew( 4, gnew ) ;
	MatrixZero( 4, gnew ) ;			/* free it up */
	}

    MatrixMultiResult( 4, xform ) ;
    MatrixMultiInit(4) ;

    return loop ;
    }
예제 #8
0
static FUNC *OpticForward( FUNC *func )
    {
    int which ;

    func = FuncForward( func ) ;
    if( func )
	{
	which = (int) ( ExprValue( FuncArg( func, 0 ) ) + 0.49 ) ;
	if( (which == 13) || (which == 19) || (which == 21) )
				/* print, bound, or merit */
	    {
	    OpticRegister( func ) ;
	    return OpticForward( FuncNext( func ) ) ;
	    }
	}

    return func ;
    }
예제 #9
0
    void ArrayAdapter::llvmThrowOutOfRangeException(
      BasicBlockBuilder &basicBlockBuilder,
      llvm::Value *itemDescRValue,
      llvm::Value *indexRValue,
      llvm::Value *sizeRValue,
      llvm::Value *errorDescRValue
      ) const
    {
      RC::Handle<Context> context = basicBlockBuilder.getContext();
      RC::ConstHandle<SizeAdapter> sizeAdapter = basicBlockBuilder.getManager()->getSizeAdapter();
      RC::ConstHandle<StringAdapter> stringAdapter = basicBlockBuilder.getManager()->getStringAdapter();
      RC::ConstHandle<ConstStringAdapter> constStringAdapter = basicBlockBuilder.getManager()->getConstStringAdapter();

      std::vector<llvm::Type const *> argTypes;
      argTypes.push_back( constStringAdapter->llvmRType( context ) );
      argTypes.push_back( sizeAdapter->llvmRType( context ) );
      argTypes.push_back( sizeAdapter->llvmRType( context ) );
      argTypes.push_back( constStringAdapter->llvmRType( context ) );
      llvm::FunctionType const *funcType = llvm::FunctionType::get( basicBlockBuilder->getVoidTy(), argTypes, false );
      
      llvm::AttributeWithIndex AWI[1];
      AWI[0] = llvm::AttributeWithIndex::get( ~0u, 0 /*llvm::Attribute::InlineHint | llvm::Attribute::NoUnwind*/ );
      llvm::AttrListPtr attrListPtr = llvm::AttrListPtr::get( AWI, 1 );

      std::string name = "__ThrowOutOfRangeException";
      llvm::Function *func = llvm::cast<llvm::Function>( basicBlockBuilder.getModuleBuilder()->getFunction( name ) );
      if ( !func )
      {
        ModuleBuilder &mb = basicBlockBuilder.getModuleBuilder();
        
        func = llvm::cast<llvm::Function>( mb->getOrInsertFunction( name, funcType, attrListPtr ) ); 
        func->setLinkage( llvm::GlobalValue::PrivateLinkage );
        
        FunctionBuilder fb( mb, funcType, func );
        llvm::Argument *itemRValue = fb[0];
        itemRValue->setName( "itemRValue" );
        itemRValue->addAttr( llvm::Attribute::NoCapture );
        llvm::Argument *indexRValue = fb[1];
        indexRValue->setName( "indexRValue" );
        llvm::Argument *sizeRValue = fb[2];
        sizeRValue->setName( "sizeRValue" );
        llvm::Argument *errorDescRValue = fb[3];
        errorDescRValue->setName( "errorDescRValue" );
        errorDescRValue->addAttr( llvm::Attribute::NoCapture );
        
        BasicBlockBuilder bbb( fb );
        llvm::BasicBlock *entryBB = fb.createBasicBlock( "entry" );
        bbb->SetInsertPoint( entryBB );

        llvm::Value *errorMsg1PlusIndexPlusErrorMsg2PlusSizePlusErrorMsg3LValue;
        {
          Scope subScope( bbb.getScope() );
          BasicBlockBuilder subBasicBlockBuilder( bbb, subScope );

          llvm::BasicBlock *haveErrorDescBB = fb.createBasicBlock( "haveErrorDescBB" );
          llvm::BasicBlock *noErrorDescBB = fb.createBasicBlock( "noErrorDescBB" );
          llvm::BasicBlock *goBB = fb.createBasicBlock( "goBB" );

          subBasicBlockBuilder->CreateCondBr(
            subBasicBlockBuilder->CreateIsNotNull( errorDescRValue ),
            haveErrorDescBB,
            noErrorDescBB
            );
            
          subBasicBlockBuilder->SetInsertPoint( haveErrorDescBB );
          llvm::Value *haveErrorDescConstStringRValue = errorDescRValue;
          subBasicBlockBuilder->CreateBr( goBB );
            
          subBasicBlockBuilder->SetInsertPoint( noErrorDescBB );
          llvm::Value *noErrorDescConstStringRValue = constStringAdapter->llvmConst( subBasicBlockBuilder, "KL" );
          subBasicBlockBuilder->CreateBr( goBB );

          subBasicBlockBuilder->SetInsertPoint( goBB );
          llvm::PHINode *errorDescConstStringRValue = subBasicBlockBuilder->CreatePHI( haveErrorDescConstStringRValue->getType(), "errorDescConstStringRValue" );
          errorDescConstStringRValue->addIncoming( haveErrorDescConstStringRValue, haveErrorDescBB );
          errorDescConstStringRValue->addIncoming( noErrorDescConstStringRValue, noErrorDescBB );

          llvm::Value *errorMsg0RValue = stringAdapter->llvmCast(
            subBasicBlockBuilder,
            ExprValue( constStringAdapter, USAGE_RVALUE, context, errorDescConstStringRValue )
            );
          
          llvm::Value *errorMsgARValue = stringAdapter->llvmCast( subBasicBlockBuilder,
            ExprValue( constStringAdapter, USAGE_RVALUE, context, constStringAdapter->llvmConst( subBasicBlockBuilder, ": " ) )
            );
          
          llvm::Value *errorMsgALValue = stringAdapter->llvmAlloca( subBasicBlockBuilder, "errorMsgA" );
          stringAdapter->llvmInit( subBasicBlockBuilder, errorMsgALValue );
          stringAdapter->llvmCallConcat(
            subBasicBlockBuilder,
            errorMsg0RValue,
            errorMsgARValue,
            errorMsgALValue
            );
          
          llvm::Value *errorMsgBRValue = stringAdapter->llvmCast( subBasicBlockBuilder,
            ExprValue( constStringAdapter, USAGE_RVALUE, context, itemRValue )
            );
          
          llvm::Value *errorMsgBLValue = stringAdapter->llvmAlloca( subBasicBlockBuilder, "errorMsgB" );
          stringAdapter->llvmInit( subBasicBlockBuilder, errorMsgBLValue );
          stringAdapter->llvmCallConcat(
            subBasicBlockBuilder,
            stringAdapter->llvmLValueToRValue( subBasicBlockBuilder, errorMsgALValue ),
            errorMsgBRValue,
            errorMsgBLValue
            );
          stringAdapter->llvmDispose( subBasicBlockBuilder, errorMsgALValue );
          
          llvm::Value *errorMsgCRValue = stringAdapter->llvmCast( subBasicBlockBuilder,
            ExprValue( constStringAdapter, USAGE_RVALUE, context, constStringAdapter->llvmConst( subBasicBlockBuilder, " (" ) )
            );
          
          llvm::Value *errorMsgCLValue = stringAdapter->llvmAlloca( subBasicBlockBuilder, "errorMsgC" );
          stringAdapter->llvmInit( subBasicBlockBuilder, errorMsgCLValue );
          stringAdapter->llvmCallConcat(
            subBasicBlockBuilder,
            stringAdapter->llvmLValueToRValue( subBasicBlockBuilder, errorMsgBLValue ),
            errorMsgCRValue,
            errorMsgCLValue
            );
          stringAdapter->llvmDispose( subBasicBlockBuilder, errorMsgBLValue );
          
          llvm::Value *indexStringRValue = stringAdapter->llvmCast(
            subBasicBlockBuilder,
            ExprValue( sizeAdapter, USAGE_RVALUE, context, indexRValue )
            );
            
          llvm::Value *errorMsg1PlusIndexLValue = stringAdapter->llvmAlloca( subBasicBlockBuilder, "errorMsg1PlusIndex" );
          stringAdapter->llvmInit( subBasicBlockBuilder, errorMsg1PlusIndexLValue );
          stringAdapter->llvmCallConcat(
            subBasicBlockBuilder,
            stringAdapter->llvmLValueToRValue( subBasicBlockBuilder, errorMsgCLValue ),
            indexStringRValue,
            errorMsg1PlusIndexLValue
            );
          stringAdapter->llvmDispose( subBasicBlockBuilder, errorMsgCLValue );
          
          llvm::Value *errorMsg2RValue = stringAdapter->llvmCast(
            subBasicBlockBuilder,
            ExprValue( constStringAdapter, USAGE_RVALUE, context, constStringAdapter->llvmConst( subBasicBlockBuilder, ") out of range (" ) )
            );
            
          llvm::Value *errorMsg1PlusIndexPlusErrorMsg2LValue = stringAdapter->llvmAlloca( subBasicBlockBuilder, "errorMsg1PlusIndexPlusErrorMsg2" );
          stringAdapter->llvmInit( subBasicBlockBuilder, errorMsg1PlusIndexPlusErrorMsg2LValue );
          stringAdapter->llvmCallConcat(
            subBasicBlockBuilder,
            stringAdapter->llvmLValueToRValue( subBasicBlockBuilder, errorMsg1PlusIndexLValue ),
            errorMsg2RValue,
            errorMsg1PlusIndexPlusErrorMsg2LValue
            );
          stringAdapter->llvmDispose( subBasicBlockBuilder, errorMsg1PlusIndexLValue );

          llvm::Value *sizeStringRValue = stringAdapter->llvmCast(
            subBasicBlockBuilder,
            ExprValue( sizeAdapter, USAGE_RVALUE, context, sizeRValue )
            );
            
          llvm::Value *errorMsg1PlusIndexPlusErrorMsg2PlusSizeLValue = stringAdapter->llvmAlloca( subBasicBlockBuilder, "errorMsg1PlusIndexPlusErrorMsg2PlusSize" );
          stringAdapter->llvmInit( subBasicBlockBuilder, errorMsg1PlusIndexPlusErrorMsg2PlusSizeLValue );
          stringAdapter->llvmCallConcat(
            subBasicBlockBuilder,
            stringAdapter->llvmLValueToRValue( subBasicBlockBuilder, errorMsg1PlusIndexPlusErrorMsg2LValue ),
            sizeStringRValue,
            errorMsg1PlusIndexPlusErrorMsg2PlusSizeLValue
            );
          stringAdapter->llvmDispose( subBasicBlockBuilder, errorMsg1PlusIndexPlusErrorMsg2LValue );

          llvm::Value *errorMsg3RValue = stringAdapter->llvmCast(
            subBasicBlockBuilder,
            ExprValue( constStringAdapter, USAGE_RVALUE, context, constStringAdapter->llvmConst( subBasicBlockBuilder, ")" ) )
            );
            
          errorMsg1PlusIndexPlusErrorMsg2PlusSizePlusErrorMsg3LValue = stringAdapter->llvmAlloca( subBasicBlockBuilder, "errorMsg1PlusIndexPlusErrorMsg2PlusSizePlusErrorMsg3" );
          stringAdapter->llvmInit( subBasicBlockBuilder, errorMsg1PlusIndexPlusErrorMsg2PlusSizePlusErrorMsg3LValue );
          stringAdapter->llvmCallConcat(
            subBasicBlockBuilder,
            stringAdapter->llvmLValueToRValue( subBasicBlockBuilder, errorMsg1PlusIndexPlusErrorMsg2PlusSizeLValue ),
            errorMsg3RValue,
            errorMsg1PlusIndexPlusErrorMsg2PlusSizePlusErrorMsg3LValue
            );
          stringAdapter->llvmDispose( subBasicBlockBuilder, errorMsg1PlusIndexPlusErrorMsg2PlusSizeLValue );
          
          subScope.llvmUnwind( subBasicBlockBuilder );
        }
        llvmThrowException( bbb, errorMsg1PlusIndexPlusErrorMsg2PlusSizePlusErrorMsg3LValue );
        bbb->CreateRetVoid();
      }
      
      std::vector<llvm::Value *> args;
      args.push_back( itemDescRValue );
      args.push_back( indexRValue );
      args.push_back( sizeRValue );
      args.push_back( errorDescRValue );
      basicBlockBuilder->CreateCall( func, args.begin(), args.end() );
    }
예제 #10
0
    ExprValue Function::llvmCreateCall( BasicBlockBuilder &basicBlockBuilder, std::vector<ExprValue> &args ) const
    {
      RC::Handle<Context> context = basicBlockBuilder.getContext();
      
      if ( m_params.size() != args.size() )
        throw Exception( "incorrect number of arguments (expected %u, actual %u)", (unsigned)m_params.size(), (unsigned)args.size() );

      for ( size_t i=0; i<args.size(); ++i )
      {
        FunctionParam const &param = m_params[i];
        ExprValue &arg = args[i];

        if( !arg.isValid() )
          throw Exception( "expression is invalid" );
        
        try
        {
          arg.castTo( basicBlockBuilder, param.getExprType() );
        }
        catch ( Exception e )
        {
          throw Exception( "argument %u ('%s'): %s", (unsigned)(i + 1), param.getName().c_str(), (const char*)e.getDesc() );
        }
      }

      llvm::Value *returnValue = 0;
      if ( m_returnInfo.usesReturnLValue() )
      {
        RC::ConstHandle<Adapter> returnAdapter = m_returnInfo.getAdapter();
        returnValue = returnAdapter->llvmAlloca( basicBlockBuilder, "resultLValue" );
        returnAdapter->llvmInit( basicBlockBuilder, returnValue );
        args.resize( args.size() + 1, ExprValue(context) );
        for ( size_t i=1; i<args.size(); ++i )
          args[args.size()-i] = args[args.size()-i-1];
        args[0] = ExprValue( returnAdapter, USAGE_LVALUE, context, returnValue );
        basicBlockBuilder.getScope().put( CG::VariableSymbol::Create( args[0] ) );
      }
      
      std::vector<llvm::Value *> argValues;
      for ( size_t i=0; i<args.size(); ++i )
        argValues.push_back( args[i].getValue() );
      /*
      llvm::BasicBlock *lpbb = basicBlockBuilder.getFunctionBuilder()->createBasicBlock( "lpbb" );
      llvm::BasicBlock *normalbb = basicBlockBuilder.getFunctionBuilder()->createBasicBlock( "normalbb" );

      llvm::Value *resultValue = basicBlockBuilder->CreateInvoke( m_llvmFunction, normalbb, lpbb, argValues );

      if( !m_returnInfo.usesReturnLValue() )
        returnValue = resultValue;

      basicBlockBuilder->SetInsertPoint( lpbb );
      basicBlockBuilder->CreateLandingPad();
      basicBlockBuilder->CreateBr( normalbb );

      basicBlockBuilder->SetInsertPoint( normalbb );
      */

      llvm::Value *resultValue = basicBlockBuilder->CreateCall( m_llvmFunction, argValues );
      if( !m_returnInfo.usesReturnLValue() )
        returnValue = resultValue;

      return CG::ExprValue( m_returnInfo.getExprType(), context, returnValue );
    }
예제 #11
0
static int FuncCompileIfElse( FUNC *func )
    {
    FUNC *table[100], *loop, *temp ;
    int i, j, count, unknown ;
    ifelsedir direction ;

    for( loop = func ; loop ; loop = loop->next )
	loop->unknown = 0 ;

/*
 *  First find an if/else tree
 *
 */

    count = 0 ;
    direction = DIR_UNKNOWN ;
    for( loop = func ; loop ; loop = loop->next )
	{
	if( !loop->ignore && ExprLabelEqual(loop->label, iif) )
	    {
	    if( count && (direction == DIR_FORWARD) )
		break ;
	    if( !count )
		direction = DIR_FORWARD ;
	    table[count] = loop ;
	    loop = SetSkip( loop ) ;
	    count++ ;
	    if( direction == DIR_REVERSE )
		break ;					/* final $if */
	    }
	else
	if( !loop->ignore &&
		( ExprLabelEqual( loop->label, ielse ) || ExprLabelEqual( loop->label, ielseif ) ) )
	    {
	    if( !count )
		direction = DIR_REVERSE ;
	    table[count] = loop ;
	    loop = SetSkip( loop ) ;
	    count++ ;
	    if( (direction == DIR_FORWARD) && ExprLabelEqual(loop->label, ielse) )
		break ;					/* final $else */
	    }
	else
	if( count && !ExprLabelEqual(loop->label, imacro) )
	    break ;
	}
    if( !count )
	return 0 ;

    if( count >= 100 )
	IOerror( FuncBomb, "FuncCompileIfElse", "internal table exceeded" ) ;

    if( direction == DIR_UNKNOWN )
	IOerror( FuncBomb, "FuncCompileIfElse", "cannot determine direction" ) ;

/*
 *  Swap ends if tree is reversed
 *
 */

    if( direction == DIR_REVERSE )
	{
	for( i = 0 ; i < count / 2 ; i++ )
	    {
	    temp = table[i] ;
	    table[i] = table[ count - i - 1 ] ;
	    table[ count - i - 1 ] = temp ;
	    }
    if( !ExprLabelEqual( table[0]->label, iif ) )
	IOerror( FuncBomb, "FuncCompileIfElse", "if/else tree has no if" ) ;
    }

/*
 *  Check some syntax
 *
 */

    if( FuncArgCount( table[0] ) != 1 )
	{
	IOerror( FuncBomb, "FuncCompileIfElse",
	    "wrong number of arguments to $if" ) ;
	}
    for( i = 1 ; i < count - 1 ; i++ )
	{
	if( FuncArgCount( table[i] ) != 1 )
	    {
	    IOerror( FuncBomb, "FuncCompileIfElse",
		"wrong number of arguments to $elseif" ) ;
	    }
	if( ExprLabelEqual( table[i]->label, ielse ) )
	    {
	    IOerror( FuncBomb, "FuncCompileIfElse",
		"$else embedded in $if/$else tree" ) ;
	    }
	}
    if( ExprLabelEqual(table[count - 1]->label, ielse) && (FuncArgCount( table[count - 1] ) != 0) )
	IOerror( FuncBomb, "FuncCompileIfElse",
	    "wrong number of arguments to $else" ) ;

/*
 *  Find the true branch
 *
 */

    unknown = 0 ;
    for( i = 0 ; i < count ; i++ )
	{
	if( ExprNonDepend( FuncArg( table[i], 0 ), VAR_SET, 0 ) )
	    {
	    unknown = 1 ;
	    break ;
	    }
	if( ExprLabelEqual( table[i]->label, ielse ) )			/* leftover */
	    break ;
	if( ExprValue( FuncArg( table[i], 0 ) ) )	/* true */
	    break ;
	}

/*
 *  Set the final state
 *
 */

    for( j = 0 ; j < count ; j++ )
	{
	if( unknown )
	    loop = SetUnknown( table[j] ) ;
	else
	    {
	    if( i == j )
		loop = SetTrue( table[j] ) ;
	    else
		loop = SetFalse( table[j] ) ;
	    }
	if( (direction == DIR_REVERSE) && (j == 0) )
	    func = loop ;
	if( (direction == DIR_FORWARD) && (j == count - 1) )
	    func = loop ;
	}

/*
 *  func is now the last FUNC of the tree
 *
 */

    if( func && func->next )
	return !unknown + FuncCompileIfElse( func->next ) ;
    else
	return !unknown ;
    }
예제 #12
0
static FUNC *ConvertSurface( FUNC *func, OPTIC *optic )
    {
    FUNC *loop ;
    EXPR *EA0, *separate ;
    int ea0used, which, rev ;

    optic->terms[ TERM_MAT ].E = Copy( MatGet() ) ;
    optic->terms[ TERM_TEMP ].E = Copy( MatGetTemp() ) ;

    for( loop = func ; loop ; loop = OpticForward( FuncNext(loop) ) )
	{
	which = (int) ( ExprValue( FuncArg( loop, 0 ) ) + 0.49 ) ;

	if( which < 6 )
	    break ;

	EA0 = Copy( FuncArg( loop, 1 ) ) ;
	ea0used = 0 ;

	switch( which )
	    {
	    case 6:				/* INDX */
		if( FuncArgCount( loop ) == 4 )
		    {
		    MatPush( EA0, FuncArg( loop, 2 ),
			FuncIsReversed( loop ) ) ;
		    optic->mutant = 1 ;
		    (optic - 1)->mutant = -1 ;		/* kludge-o-rama */
		    optic->terms[TERM_MUTANT].E = Copy( FuncArg( loop, 3 ) ) ;
		    }
		else
		if( FuncArgCount( loop ) == 3 )
		    {
		    MatPush( EA0, FuncArg( loop, 2 ),
			FuncIsReversed( loop ) ) ;
		    }
		else
		if( FuncArgCount( loop ) == 2 )
		    {
		    MatPush( EA0, Label( "MatTemperature" ),
			FuncIsReversed( loop ) ) ;
		    }
		break ;
	    case 7:				/* PARAX */
		optic->terms[TERM_FOCLEN].E = EA0 ;
		optic->function |= FUNCTION_PARAX ;
		ea0used = 1 ;
		break ;
	    case 8:				/* MIRROR */
		optic->function |= FUNCTION_MIRROR ;
		break ;
	    case 9:				/* GRATING */
		optic->function |= FUNCTION_GRATING ;
		optic->terms[TERM_LINES].E = EA0 ;
		optic->terms[TERM_ORDER].E = Copy( FuncArg( loop, 2 ) ) ;
		ea0used = 1 ;
		break ;
	    case 10:				/* VIEW */
		optic->function |= FUNCTION_VIEW ;
		break ;
	    case 11:				/* STOP */
		if( FuncArgCount( loop ) == 1 )			/* EXIT */
		    optic->function |= FUNCTION_EXIT ;
		else
		if( FuncArgCount( loop ) == 7 )			/* STOP */
		    {
		    int i ;
		    EDAT *S ;

		    if( optic->StopCount == NSTOPS )
			{
			IOerror( IO_ERR, "ConvertSurface", "too many stops" ) ;
			failed = 1 ;
			break ;
			}

		    S = &optic->terms[ TERM_STOPS + 6 * optic->StopCount ] ;

		    for( i = 0 ; i < 6 ; i++ )
			S[i].E = Copy( FuncArg( loop, i + 1 ) ) ;
		    optic->StopCount++ ;
		    }
		break ;
	    case 12:				/* PDIST */
		if( FuncIsReversed( loop ) )
		    optic->terms[TERM_PDIST].E = Ecc( EA0, "u-", Garbage() ) ;
		else
		optic->terms[TERM_PDIST].E = EA0 ;
		optic->function |= FUNCTION_PDIST ;
		ea0used = 1 ;
		break ;
	    case 13:				/* PRINT */
		break ;
	    case 14:				/* LABEL */
		separate = String( " & " ) ;
		if( optic->terms[ TERM_LABEL ].E )
		    {
		    optic->terms[ TERM_LABEL ].E = Ecc(
			optic->terms[ TERM_LABEL ].E, "//", separate ) ;
		    optic->terms[ TERM_LABEL ].E = Ecc(
			optic->terms[ TERM_LABEL ].E, "//", EA0 ) ;
		    }
		else
		    optic->terms[ TERM_LABEL ].E = EA0 ;
		ea0used = 1 ;
		break ;
	    case 15:				/* SURF */

		rev = ( FuncIsReversed( loop ) ? -1 : 1 ) ;
		if( optic->reverse != rev )
		    {
		    if( !optic->reverse )
			optic->reverse = rev ;
		    else
			{
			IOerror( IO_ERR, "ConvertSurface",
			    "inconsistent surface reversal on surface #%d",
			    Surface ) ;
			failed = 1 ;
			}
		    }

		if( FuncArgCount( loop ) == 4 )
		    {
		    optic->surface |= SURFACE_SYMBOLIC ;
		    optic->terms[TERM_Sx].E = Copy( FuncArg( loop, 1 ) ) ;
		    optic->terms[TERM_Sy].E = Copy( FuncArg( loop, 2 ) ) ;
		    optic->terms[TERM_Sf].E = Copy( FuncArg( loop, 3 ) ) ;

		    if( !ExprIsVariable( optic->terms[TERM_Sx].E ) )
			IOerror( IO_ERR, "ConvertSurface", "X not a variable" ) ;
		    if( !ExprIsVariable( optic->terms[TERM_Sy].E ) )
			IOerror( IO_ERR, "ConvertSurface", "Y not a variable" ) ;

		    break ;
		    }

		optic->terms[TERM_CURV].E = EA0 ;
		ea0used = 1 ;
		if( FuncArgCount( loop ) == 1 )
		    optic->surface |= SURFACE_FLAT ;
		else
		if( FuncArgCount( loop ) == 2 )
		    optic->surface |= SURFACE_SPHERE ;
		else
		if( FuncArgCount( loop ) == 3 )
		    {
		    optic->surface |= SURFACE_CONIC ;
		    optic->terms[TERM_CONIC].E = Copy( FuncArg( loop, 2 ) ) ;
		    }
		else		/* count = 6 */
		    {
		    optic->surface |= SURFACE_ASPHERE ;
		    optic->terms[TERM_CONIC].E = Copy( FuncArg( loop, 2 ) ) ;
		    optic->terms[TERM_A4].E = Copy( FuncArg( loop, 3 ) ) ;
		    optic->terms[TERM_A6].E = Copy( FuncArg( loop, 4 ) ) ;
		    optic->terms[TERM_A8].E = Copy( FuncArg( loop, 5 ) ) ;
		    optic->terms[TERM_A10].E = Copy( FuncArg( loop, 6 ) ) ;
		    }
		break ;
	    case 16:				/* TRIX */

		rev = ( FuncIsReversed( loop ) ? -1 : 1 ) ;
		if( optic->reverse != rev )
		    {
		    if( !optic->reverse )
			optic->reverse = rev ;
		    else
			{
			IOerror( IO_ERR, "ConvertSurface",
			    "inconsistent surface reversal on surface #%d",
			    Surface ) ;
			failed = 1 ;
			}
		    }

		optic->terms[TERM_Ex].E = EA0 ;
		optic->terms[TERM_Ey].E = Copy( FuncArg( loop, 2 ) ) ;
		optic->terms[TERM_Ez].E = Copy( FuncArg( loop, 3 ) ) ;
		optic->terms[TERM_Eo].E = Copy( FuncArg( loop, 4 ) ) ;
		optic->surface |= SURFACE_TRIAXIAL ;
		ea0used = 1 ;
		break ;

	    case 17:				/* MARK */
		if( FuncArgCount( loop ) == 2 )		/* surface */
		    {
		    optic->terms[TERM_MARK].E = EA0 ;
		    ea0used = 1 ;
		    }
		else
		if( FuncArgCount( loop ) == 3 )		/* variable */
		    {
		    if( !ExprIsVariable( FuncArg( loop, 1 ) ) )
			{
			IOerror( OpticBomb, "ConvertSurface",
			    "EXPR not a VARIABLE" ) ;
			}
		    ExprSetFlags( FuncArg( loop, 1 ),
			(int) ExprValue( FuncArg( loop, 2 ) ) & VAR_OPTIC ) ;
		    }
		break ;
	    case 18:				/* COAT */
		if( optic->terms[ TERM_COATING ].E )
		    {
		    IOerror( IO_ERR, "ConvertSurface",
			"multiple coating declarations on surface %d",
			Surface ) ;
		    failed = 1 ;
		    }
		else
		    {
		    optic->terms[ TERM_COATING ].E = EA0 ;
		    ea0used = 1 ;
		    }
		break ;
	    case 19:				/* BOUND */
		break ;
	    case 20:				/* BAFFLE */
		optic->function |= FUNCTION_BAFFLE ;
		break ;
	    case 21:				/* MERIT */
		break ;
	    case 22:				/* APERTURE */
		optic->function |= FUNCTION_APERTURE ;
		if( aperture_set )
		    {
		    IOerror( IO_ERR, "ConvertSurface", "multiple apertures" ) ;
		    failed = 1 ;
		    }
		aperture_set = 1 ;
		break ;
	    case 23:				/* PINHOLE */
		optic->function |= FUNCTION_PINHOLE ;
		break ;
	    case 24:				/* ORIGIN */
		if( origin_set )
		    {
		    IOerror( IO_WARN, "ConvertSurface", "multiple origins" ) ;
/* EVIL HACK!!!! */
/*		    failed = 1 ; */
		    }
		else
		    {
		    optic->function |= FUNCTION_ORIGIN ;
		    origin_set = 1 ;
		    }
		break ;
	    case 25:					/* FRESNEL */
		rev = ( FuncIsReversed( loop ) ? -1 : 1 ) ;
		if( optic->reverse != rev )
		    {
		    if( !optic->reverse )
			optic->reverse = rev ;
		    else
			{
			IOerror( IO_ERR, "ConvertSurface",
			    "inconsistent surface reversal on surface #%d",
			    Surface ) ;
			failed = 1 ;
			}
		    }

		optic->surface |= SURFACE_FRESNEL ;
		optic->terms[TERM_FOCLEN].E = EA0 ;
		ea0used = 1 ;
		break ;
	    default:
		IOerror( OpticBomb, "ConvertSurface",
		    "unexpected surface function on surface #%d", Surface ) ;
		failed = 1 ;
	    }

	if( !ea0used )
	    Free( EA0 ) ;
	}

    if( !Compare( optic->terms[ TERM_MAT ].E, MatGet() ) )
	optic->function |= FUNCTION_SNELL ;

    return loop ;
    }
예제 #13
0
파일: cat.c 프로젝트: skewray/skewray_old
double MatIndexCat( char *name, double temp, double wl )
    {
    double low, high, S2, index2, Tcat, dndT ;
    int count ;
    char *type ;

    if( wl <= 0.0 )
	{
	IOerror( MatBomb, "MatIndexCat", "invalid wavelength %g", wl ) ;
	return nan("") ;
	}

/*
 *  First get the index at the catalogue temperature
 *
 */

    low = ExprValue( DbaseGetExpr( name, "DispersionLow" ) ) ;
    if( (wl < low) && DbaseCheck( name, "DISP_LOW" ) )
	{
	IOerror( MatBomb, "MatIndexCat", "wavelength %g out of range for %s: lower bound is %g", wl, name, low ) ;
	IOerror( MatBomb, "MatIndexCat", "extrapolating beyond range\n" ) ;
	}
    high = ExprValue( DbaseGetExpr( name, "DispersionHigh" ) ) ;
    if( (wl > high) && DbaseCheck( name, "DISP_HIGH" ) )
	{
	IOerror( MatBomb, "MatIndexCat", "wavelength %g out of range for %s: upper bound is %g", wl, name, high ) ;
	IOerror( MatBomb, "MatIndexCat", "extrapolating beyond range\n" ) ;
	}

    S2 = 1.0 / ( wl * wl ) ;

    type = ExprValueString( DbaseGetExpr( name, "DispersionFormula" ) ) ;

    if( strcmp( type, "sellmeier" ) == 0 )
	{
	EXPR* array = DbaseGetExpr( name, "sellmeier" ) ;
	if( !array )
	    {
	    IOerror( MatBomb, "MatIndexCat", "sellmeier data array not found for %s", name ) ;
	    return nan("") ;
	    }

	count = ExprArrayCount(array) ;
	if( count % 2 )
	    {
	    IOerror( MatBomb, "MatIndexCat", "sellmeier formula has %d terms for %s", count, name ) ;
	    return nan("") ;
	    }

	double table[count] ;
	for( int i = 0 ; i < count ; i++ )
	    table[i] = ExprValue( ExprArrayValue( array, i ) ) ;

	index2 = 1.0 ;
	for( int i = 0 ; i < count / 2 ; i++ )
	    index2 += table[ 2 * i ] / ( 1.0 - table[ 2 * i + 1 ] * S2 ) ;

	if( index2 < 1.0 )
	    {
	    IOerror( MatBomb, "MatIndexCat", "unphysical index of n[%s]^2 = %g at %g microns", name, index2, wl ) ;
	    return nan("") ;
	    }
	}
    else
    if( strcmp( type, "schott" ) == 0 )
	{
	EXPR* array = DbaseGetExpr( name, "schott" ) ;
	if( !array )
	    {
	    IOerror( MatBomb, "MatIndexCat", "schott data array not found for %s", name ) ;
	    return nan("") ;
	    }

	count = ExprArrayCount(array) ;
	if( count != 6 )
	    {
	    IOerror( MatBomb, "MatIndexCat", "Schott formula has %d terms for %s", count, name ) ;
	    return nan("") ;
	    }

	double table[6] ;
	for( int i = 0 ; i < 6 ; i++ )
	    table[i] = ExprValue( ExprArrayValue( array, i ) ) ;

	index2 = table[0]
	     +   table[1] / S2
	     + ( table[2]
	     + ( table[3]
	     + ( table[4]
	     +   table[5] * S2 ) * S2 ) * S2 ) * S2 ;

	if( index2 < 1.0 )
	    {
	    IOerror( MatBomb, "MatIndexCat", "unphysical index of n[%s]^2 = %g at %g microns", name, index2, wl ) ;
	    return nan("") ;
	    }
	}
    else
    if( strcmp( type, "polyindex" ) == 0 )
	{
	EXPR* array = DbaseGetExpr( name, "polyindex" ) ;
	if( !array )
	    {
	    IOerror( MatBomb, "MatIndexCat", "polyindex data array not found for %s", name ) ;
	    return nan("") ;
	    }

	count = ExprArrayCount(array) ;
	if( !count || (count % 3 != 0) )
	    {
	    IOerror( MatBomb, "MatIndexCat", "Poly Index has %d terms for %s", count, name ) ;
	    return nan("") ;
	    }

	double table[count] ;
	for( int i = 0 ; i < count ; i++ )
	    table[i] = ExprValue( ExprArrayValue( array, i ) ) ;

	index2 = 0.0 ;
	for( int i = 0 ; i < count / 3 ; i++ )
	    {
	    index2 += table[ 3 * i + 2 ]
		* pow( S2, table[ 3 * i ] )
		* pow( temp, table[ 3 * i + 1 ] ) ;
	    }

	if( index2 < 1.0 )
	    {
	    IOerror( MatBomb, "MatIndexCat", "unphysical index of n[%s]^2 = %g at %g microns", name, index2, wl ) ;
	    return nan("") ;
	    }

	return sqrt( index2 ) ;			/* TEMP done already! */
	}
    else
	{
	IOerror( MatBomb, "MatIndexCat", "unknown type of dispersion formula for %s", name ) ;
	return nan("") ;
	}

/*
 *  Now adjust for temperature effects
 *
 */

    Tcat = ExprValue( DbaseGetExpr( name, "DispersionTemperature" ) ) ;
    if( Tcat == temp )
	return sqrt( index2 ) ;			/* all done! */

    type = ExprValueString( DbaseGetExpr( name, "dndTFormula" ) ) ;
    if( strcmp( type, "table" ) == 0 )
	{
	EXPR* array = DbaseGetExpr( name, "dndT" ) ;
	if( array )
	    {
	    dndT = ExprInterp( array, wl ) ;
	    if( isnan(dndT) )
		{
		IOerror( MatBomb, "MatIndexCat", "bad dndT data array for %s", name ) ;
		return nan("") ;
		}
	    }
	else
	    {
	    IOerror( MatBomb, "MatIndexCat", "dndT data not found for %s", name ) ;
	    return nan("") ;
	    }

//	if( (ret == 1) && DbaseCheck( name, "DNDT_RANGE" ) )
//	    IOerror( MatBomb, "MatIndexCat", "wavelength %g out of range of dndT table for %s -- extrapolating", wl, name ) ;
	}
    else
    if( strcmp( type, "constant" ) == 0 )
	dndT = ExprValue( DbaseGetExpr( name, "dndTConstant" ) ) ;
    else
	{
	IOerror( MatBomb, "MatIndexCat", "unknown form of dndT table for %s",
	    name ) ;
	return nan("") ;
	}

    return sqrt( index2 ) + dndT * ( temp - Tcat ) ;
    }
예제 #14
0
파일: cat.c 프로젝트: skewray/skewray_old
double MatOpacityCat( char *name, double wl )
    {
    double low, high, depth, T ;
    char *type ;

    if( wl <= 0.0 )
	{
	IOerror( MatBomb, "MatOpacityCat", "invalid wavelength %g", wl ) ;
	return nan("") ;
	}

    low = ExprValue( DbaseGetExpr( name, "TransmissionLow" ) ) ;
    if( (wl < low) && DbaseCheck( name, "OPACITY_LOW" ) )
	{
	IOerror( MatBomb, "MatOpacityCat", "wavelength %g out of range for %s: lower bound is %g", wl, name, low ) ;
	IOerror( MatBomb, "MatOpacityCat", "extrapolating beyond range\n" ) ;
	wl = low ;
	}
    high = ExprValue( DbaseGetExpr( name, "TransmissionHigh" ) ) ;
    if( (wl > high) && DbaseCheck( name, "OPACITY_HIGH" ) )
	{
	IOerror( MatBomb, "MatOpacityCat", "wavelength %g out of range for %s: upper bound is %g", wl, name, high ) ;
	IOerror( MatBomb, "MatOpacityCat", "extrapolating beyond range\n" ) ;
	wl = high ;
	}

    type = ExprValueString( DbaseGetExpr( name, "TransmissionFormula" ) ) ;
    if( strcmp( type, "table" ) == 0 )
	{
	EXPR* array = DbaseGetExpr( name, "transmission" ) ;
	if( array )
	    {
	    T = ExprInterp( array, wl ) ;
	    if( isnan(T) )
		{
		IOerror( MatBomb, "MatOpacityCat", "bad transmission data array for %s", name ) ;
		return nan("") ;
		}
	    }
	else
	    {
	    IOerror( MatBomb, "MatOpacityCat", "transmission data not found for %s", name ) ;
	    return nan("") ;

// old stuff here that we should incorporate...
//	    if( (ret == 1) && DbaseCheck( name, "OPACITY_RANGE" ) )
//		IOerror( MatBomb, "MatOpacityCat", "wavelength %g out of range for %s -- extrapolating", wl, name ) ;
	    }

	depth = ExprValue( DbaseGetExpr( name, "TransmissionDepth" ) ) ;

	if( T == 1.0 )
	    return 0.0 ;
	else
	if( T <= 0.0 )
	    return HUGE ;
	else
	    return -( depth / 25.4 ) / log(T) ;
	}
    else
    if( strcmp( type, "clear" ) == 0 )
	return 0.0 ;
    else
	{
	IOerror( MatBomb, "MatOpacityCat", "unknown type of transmission formula for %s", name ) ;
	return nan("") ;
	}
    }
예제 #15
0
void EvalExpr( unsigned addr_depth )
{
    EvalLValExpr( addr_depth );
    ExprValue( ExprSP );
}
예제 #16
0
static unsigned MechStack( unsigned select, unsigned parm )
{
    unsigned    result = 0;
    stack_entry *entry;
    sym_info    info;

    switch( select ) {
    case 0:
        SwapStack( parm );
        break;
    case 1:
        MoveSP( parm );
        break;
    case 2:
        entry = StkEntry( parm );
        LValue( entry );
        result = TypeInfoToClass( &entry->info ) & (BASE_TYPE | STK_UNSIGNED);
        break;
    case 3:
        ExprValue( StkEntry( parm ) );
        break;
    case 4:
        LValue( StkEntry( parm ) );
        break;
    case 5:
        RValue( StkEntry( parm ) );
        break;
    case 6:
        LRValue( StkEntry( parm ) );
        break;
    case 7:
        entry = StkEntry( parm );
        LValue( entry );
        result = TI_CREATE( entry->info.kind, TM_NONE, 0 );
        break;
    case 8:
        entry = StkEntry( parm );
        NameResolve( entry, FALSE );
        if( entry->flags & SF_SYM ) {
            SymInfo( entry->v.sh, entry->lc, &info );
            result = info.kind;
        } else {
            result = SK_NONE;
        }
        break;
    case 9:
        entry = StkEntry( parm );
        result = NameResolve( entry, FALSE );
        break;
    case 10:
        entry = StkEntry( parm );
        if( entry->flags & SF_NAME ) {
            result = 0;
        } else if( entry->flags & SF_SYM ) {
            result = 1;
        } else if( entry->flags & SF_LOCATION ) {
            result = 2;
        } else {
            result = 3;
        }
        break;
    }
    return( result );
}
예제 #17
0
static  void    VarModify( a_window *wnd, int row, int piece )
{
    var_node            *v;
    type_kind           class;
    var_window          *var = WndVar( wnd );
    bool                ok;
    bool                followable;
    unsigned            old;

    if( row < 0 ) {
        if( var->vtype == VAR_WATCH || var->vtype == VAR_VARIABLE ) {
            VarMenuItem( wnd, MENU_VAR_NEW_EXPRESSION, row, piece );
        }
        return;
    }
    VarErrState();
    VarKillExprSPCache( &var->i );
    v = VarFindRow( &var->i, row );
    if( v == NULL ) {
        v = VarFindRowNode( &var->i, row );
        if( v == NULL ) return;
        if( piece != VAR_PIECE_GADGET && piece != VAR_PIECE_NAME ) return;
        if( v->expand != NULL || v->node_type == NODE_INHERIT ) {
            VarExpandRow( &var->i, v, row );
            WndNewCurrent( wnd, row, VAR_PIECE_NAME );
            VarRepaint( wnd );
        }
        return;
    }
    followable = VarGetStackClass( &class );
    switch( piece ) {
    case VAR_PIECE_GADGET:
    case VAR_PIECE_NAME:
        if( VarExpandable( class ) || followable || v->expand != NULL ) {
            VarExpandRow( &var->i, v, row );
            WndNewCurrent( wnd, row, VAR_PIECE_NAME );
            VarRepaint( wnd );
        }
        break;
    case VAR_PIECE_VALUE:
        if( !VarExpandable( class ) ) {
            char *value = DbgAlloc( TXT_LEN );
            char *name = DbgAlloc( TXT_LEN );
            old = VarNewCurrRadix( v );
            ExprValue( ExprSP );
            VarBuildName( &var->i, v, FALSE );
            StrCopy( TxtBuff, name );
            VarPrintText( &var->i, value, PrintValue, TXT_LEN );
            VarKillExprSPCache( &var->i );
            v = VarFindRow( &var->i, row );
            FreezeStack();
            ok = DlgAnyExpr( name, value, TXT_LEN );
            UnFreezeStack( FALSE );
            if( ok ) VarDoAssign( &var->i, v, value );
            NewCurrRadix( old );
            WndRowDirty( wnd, row );
            DbgFree( value );
            DbgFree( name );
        }
        break;
    }
    VarDoneRow( &var->i );
    VarOldErrState();
}
예제 #18
0
static int FuncCompileSet0( FUNC *func )
    {
    FUNC *loop ;
    EXPR *var, *value, *arg ;
    int work, flags ;

    work = 0 ;
    for( loop = func ; loop ; loop = loop->next )
	{
	if( loop->ignore || loop->unknown )
	    continue ;
	if( !ExprLabelEqual(loop->label, iset) && !ExprLabelEqual(loop->label, iinit) )
	    continue ;
	var = FuncArg( loop, 0 ) ;
	if( !ExprIsVariable( var ) )
	    {
	    IOerror( FuncBomb, "FuncCompileSet0", "argument not a variable" ) ;
	    continue ;
	    }

	flags = ExprGetFlags( var, VAR_TYPE ) ;
	if( flags == (VAR_INITIAL | VAR_HARD) )
	    continue ;
	if( flags == (VAR_DEPEND | VAR_HARD) )
	    continue ;

	if( ExprLabelEqual( loop->label, iinit ) )
	    {
	    if( flags && ( flags != (VAR_INITIAL | VAR_HARD) ) )
		{
		IOerror( FuncBomb, "FuncCompileSet0",
		    "`%s' is multiply defined", ExprName( var ) ) ;
		loop->ignore = 1 ;
		work++ ;
		continue ;
		}
	    FuncTypeSet( var, VAR_INITIAL | VAR_HARD ) ;
	    work++ ;
	    continue ;
	    }

	if( flags )
	    {
	    IOerror( FuncBomb, "FuncCompileSet0",
		"`%s' is multiply defined", ExprName( var ) ) ;
	    loop->ignore = 1 ;
	    work++ ;
	    continue ;
	    }

	arg = FuncArg( loop, 1 ) ;

	if( ExprDepend( arg, (VAR_INITIAL | VAR_HARD), 0 ) )
	    {
	    FuncTypeSet( var, VAR_DEPEND | VAR_HARD ) ;
	    work++ ;
	    continue ;
	    }
	if( ExprDepend( arg, (VAR_DEPEND | VAR_HARD), 0 ) )
	    {
	    FuncTypeSet( var, VAR_DEPEND | VAR_HARD ) ;
	    work++ ;
	    continue ;
	    }

	    /* is this variable dependent on any others? */
	if( ExprNonDepend( arg, VAR_NEVER, 0 ) )
	    continue ;

/* 
 *  Oops!  What about compound string expressions?
 *
 */

	if( ExprIsString( arg ) )
	    value = arg ;
	else
	    value = Real( ExprValue( arg ), 0 ) ;
	ExprSetDefinition( var, value ) ;
	FuncTypeSet( var, VAR_CONSTANT | VAR_HARD ) ;
	(void) FuncVariableSubstitute( func, var, value, 1 ) ;
	loop->ignore = 1 ;
	work++ ;
	}

    return work ;
    }