Пример #1
0
int main()
{
    struct sigaction sigact;
    struct itimerval itval;
    double fact;
    char buf[100];
    char *point;


    printf("Before sigaction call\n");
    sigact.sa_handler = handle1;
    sigact.sa_flags = 0;
    sigemptyset(&sigact.sa_mask);
    if (sigaction(SIGNAL_TYPE, &sigact, 0) == -1)
    {
        fprintf(stderr, "Unable to set up handler\n");
        return 1;
    }

    printf("Before setitimer\n");
    itval.it_interval.tv_sec = 0;
    itval.it_interval.tv_usec = 100000;
    itval.it_value.tv_sec = 0;
    itval.it_value.tv_usec = 100000;
    if (setitimer(ITIMER_TYPE, &itval, 0) == -1)
    {
        fprintf(stderr, "Unable to set up timer\n");
        return 1;
    }

    printf("Before fpcheck\n");
    fact = fpcheck();
    printf("After fpcheck\n");

    itval.it_value.tv_sec = 0;
    itval.it_value.tv_usec = 0;
    if (setitimer(ITIMER_TYPE, &itval, 0) == -1)
    {
        fprintf(stderr, "Unable to disable timer\n");
        return 1;
    }

    sprintf(buf, "%.0f", fact);
    point = strchr(buf, '.');
    if (point)
        *point = '\0';
    if (strcmp(buf, "1307674368000") != 0)
    {
        fprintf(stderr, "15! should be 1307674368000, but computed as '%s'\n", buf);
        return 1;
    }
    printf("15! = %s\n", buf);
    return 0;
}
Пример #2
0
void test(double n1, double n2)
{
    double r;
    int jmpret;
    /* Save stack environment for return in case of error. First 
     * time through, jmpret is 0, so true conditional is executed. 
     * If an error occurs, jmpret will be set to -1 and false 
     * conditional will be executed.
     */
    jmpret = setjmp(mark);
    if (jmpret == 0) {
	r = n1 / n2;
	/* This won't be reached if error occurs. */
	printf("\n\n%4.3g / %4.3g = %4.3g\n", n1, n2, r);
	r = n1 * n2;
	/* This won't be reached if error occurs. */
	printf("\n\n%4.3g * %4.3g = %4.3g\n", n1, n2, r);
    }
    else
	fpcheck();
}
Пример #3
0
void
execute(INST * cdp,		/* code ptr, start execution here */
	CELL *sp,		/* eval_stack pointer */
	CELL *fp)		/* frame ptr into eval_stack for
				   user defined functions */
{
    /* some useful temporaries */
    CELL *cp;
    int t;
    unsigned tu;

    /* save state for array loops via a stack */
    ALOOP_STATE *aloop_state = (ALOOP_STATE *) 0;

    /* for moving the eval stack on deep recursion */
    CELL *old_stack_base = 0;
    CELL *old_sp = 0;

#ifdef	DEBUG
    CELL *entry_sp = sp;
#endif
    int force_exit = (end_start == 0);

    if (fp) {
	/* we are a function call, check for deep recursion */
	if (sp > stack_danger) {	/* change stacks */
	    old_stack_base = stack_base;
	    old_sp = sp;
	    stack_base = (CELL *) zmalloc(sizeof(CELL) * EVAL_STACK_SIZE);
	    stack_danger = stack_base + DANGER;
	    sp = stack_base;
	    /* waste 1 slot for ANSI, actually large model msdos breaks in
	       RET if we don't */
#ifdef	DEBUG
	    entry_sp = sp;
#endif
	} else
	    old_stack_base = (CELL *) 0;
    }

    while (1) {

	TRACE(("execute %s sp(%ld:%s)\n",
	       da_op_name(cdp),
	       (long) (sp - stack_base),
	       da_type_name(sp)));

	switch ((cdp++)->op) {

/* HALT only used by the disassemble now ; this remains
   so compilers don't offset the jump table */
	case _HALT:

	case _STOP:		/* only for range patterns */
#ifdef	DEBUG
	    if (sp != entry_sp + 1)
		bozo("stop0");
#endif
	    return;

	case _PUSHC:
	    inc_sp();
	    cellcpy(sp, (cdp++)->ptr);
	    break;

	case _PUSHD:
	    inc_sp();
	    sp->type = C_DOUBLE;
	    sp->dval = *(double *) (cdp++)->ptr;
	    break;

	case _PUSHS:
	    inc_sp();
	    sp->type = C_STRING;
	    sp->ptr = (cdp++)->ptr;
	    string(sp)->ref_cnt++;
	    break;

	case F_PUSHA:
	    cp = (CELL *) cdp->ptr;
	    if (cp != field) {
		if (nf < 0)
		    split_field0();

		if (!(cp >= NF && cp <= LAST_PFIELD)) {
		    /* it is a real field $1, $2 ...
		       If it is greater than $NF, we have to
		       make sure it is set to ""  so that
		       (++|--) and g?sub() work right
		     */
		    t = field_addr_to_index(cp);
		    if (t > nf) {
			cp->type = C_STRING;
			cp->ptr = (PTR) & null_str;
			null_str.ref_cnt++;
		    }
		}
	    }
	    /* fall thru */

	case _PUSHA:
	case A_PUSHA:
	    inc_sp();
	    sp->ptr = (cdp++)->ptr;
	    break;

	case _PUSHI:
	    /* put contents of next address on stack */
	    inc_sp();
	    cellcpy(sp, (cdp++)->ptr);
	    break;

	case L_PUSHI:
	    /* put the contents of a local var on stack,
	       cdp->op holds the offset from the frame pointer */
	    inc_sp();
	    cellcpy(sp, fp + (cdp++)->op);
	    break;

	case L_PUSHA:
	    /* put a local address on eval stack */
	    inc_sp();
	    sp->ptr = (PTR) (fp + (cdp++)->op);
	    break;

	case F_PUSHI:

	    /* push contents of $i
	       cdp[0] holds & $i , cdp[1] holds i */

	    inc_sp();
	    if (nf < 0)
		split_field0();
	    cp = (CELL *) cdp->ptr;
	    t = (cdp + 1)->op;
	    cdp += 2;

	    if (t <= nf)
		cellcpy(sp, cp);
	    else {		/* an unset field */
		sp->type = C_STRING;
		sp->ptr = (PTR) & null_str;
		null_str.ref_cnt++;
	    }
	    break;

	case NF_PUSHI:

	    inc_sp();
	    if (nf < 0)
		split_field0();
	    cellcpy(sp, NF);
	    break;

	case FE_PUSHA:

	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);

	    tu = d_to_index(sp->dval);
	    if (tu && nf < 0)
		split_field0();
	    sp->ptr = (PTR) field_ptr((int) tu);
	    if ((int) tu > nf) {
		/* make sure it is set to "" */
		cp = (CELL *) sp->ptr;
		cell_destroy(cp);
		cp->type = C_STRING;
		cp->ptr = (PTR) & null_str;
		null_str.ref_cnt++;
	    }
	    break;

	case FE_PUSHI:

	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);

	    tu = d_to_index(sp->dval);

	    if (nf < 0)
		split_field0();
	    if ((int) tu <= nf) {
		cellcpy(sp, field_ptr((int) tu));
	    } else {
		sp->type = C_STRING;
		sp->ptr = (PTR) & null_str;
		null_str.ref_cnt++;
	    }
	    break;

	case AE_PUSHA:
	    /* top of stack has an expr, cdp->ptr points at an
	       array, replace the expr with the cell address inside
	       the array */

	    cp = array_find((ARRAY) (cdp++)->ptr, sp, CREATE);
	    cell_destroy(sp);
	    sp->ptr = (PTR) cp;
	    break;

	case AE_PUSHI:
	    /* top of stack has an expr, cdp->ptr points at an
	       array, replace the expr with the contents of the
	       cell inside the array */

	    cp = array_find((ARRAY) (cdp++)->ptr, sp, CREATE);
	    cell_destroy(sp);
	    cellcpy(sp, cp);
	    break;

	case LAE_PUSHI:
	    /*  sp[0] is an expression
	       cdp->op is offset from frame pointer of a CELL which
	       has an ARRAY in the ptr field, replace expr
	       with  array[expr]
	     */
	    if (fp != 0) {
		cp = array_find((ARRAY) fp[(cdp++)->op].ptr, sp, CREATE);
		cell_destroy(sp);
		cellcpy(sp, cp);
	    }
	    break;

	case LAE_PUSHA:
	    /*  sp[0] is an expression
	       cdp->op is offset from frame pointer of a CELL which
	       has an ARRAY in the ptr field, replace expr
	       with  & array[expr]
	     */
	    if (fp != 0) {
		cp = array_find((ARRAY) fp[(cdp++)->op].ptr, sp, CREATE);
		cell_destroy(sp);
		sp->ptr = (PTR) cp;
	    }
	    break;

	case LA_PUSHA:
	    /*  cdp->op is offset from frame pointer of a CELL which
	       has an ARRAY in the ptr field. Push this ARRAY
	       on the eval stack
	     */
	    if (fp != 0) {
		inc_sp();
		sp->ptr = fp[(cdp++)->op].ptr;
	    }
	    break;

	case SET_ALOOP:
	    {
		ALOOP_STATE *ap = ZMALLOC(ALOOP_STATE);
		size_t vector_size;

		ap->var = (CELL *) sp[-1].ptr;
		ap->base = ap->ptr = array_loop_vector((ARRAY) sp->ptr, &vector_size);
		ap->limit = ap->base + vector_size;
		sp -= 2;

		/* push onto aloop stack */
		ap->link = aloop_state;
		aloop_state = ap;
		cdp += cdp->op;
	    }
	    break;

	case ALOOP:
	    {
		ALOOP_STATE *ap = aloop_state;
		if (ap != 0 && (ap->ptr < ap->limit)) {
		    cell_destroy(ap->var);
		    ap->var->type = C_STRING;
		    ap->var->ptr = (PTR) * ap->ptr++;
		    cdp += cdp->op;
		} else {
		    cdp++;
		}
	    }
	    break;

	case POP_AL:
	    {
		/* finish up an array loop */
		ALOOP_STATE *ap = aloop_state;
		if (ap != 0) {
		    aloop_state = ap->link;
		    while (ap->ptr < ap->limit) {
			free_STRING(*ap->ptr);
			ap->ptr++;
		    }
		    if (ap->base < ap->limit) {
			zfree(ap->base,
			      ((unsigned) (ap->limit - ap->base)
			       * sizeof(STRING *)));
		    }
		    ZFREE(ap);
		}
	    }
	    break;

	case _POP:
	    cell_destroy(sp);
	    sp--;
	    break;

	case _ASSIGN:
	    /* top of stack has an expr, next down is an
	       address, put the expression in *address and
	       replace the address with the expression */

	    /* don't propagate type C_MBSTRN */
	    if (sp->type == C_MBSTRN)
		check_strnum(sp);
	    sp--;
	    cell_destroy(((CELL *) sp->ptr));
	    cellcpy(sp, cellcpy(sp->ptr, sp + 1));
	    cell_destroy(sp + 1);
	    break;

	case F_ASSIGN:
	    /* assign to a field  */
	    if (sp->type == C_MBSTRN)
		check_strnum(sp);
	    sp--;
	    field_assign((CELL *) sp->ptr, sp + 1);
	    cell_destroy(sp + 1);
	    cellcpy(sp, (CELL *) sp->ptr);
	    break;

	case _ADD_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);

#ifdef SW_FP_CHECK		/* specific to V7 and XNX23A */
	    clrerr();
#endif
	    cp->dval += (sp--)->dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    sp->type = C_DOUBLE;
	    sp->dval = cp->dval;
	    break;

	case _SUB_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);
#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    cp->dval -= (sp--)->dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    sp->type = C_DOUBLE;
	    sp->dval = cp->dval;
	    break;

	case _MUL_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);
#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    cp->dval *= (sp--)->dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    sp->type = C_DOUBLE;
	    sp->dval = cp->dval;
	    break;

	case _DIV_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);

#ifdef  NOINFO_SIGFPE
	    CHECK_DIVZERO(sp->dval);
#endif

#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    cp->dval /= (sp--)->dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    sp->type = C_DOUBLE;
	    sp->dval = cp->dval;
	    break;

	case _MOD_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);

#ifdef  NOINFO_SIGFPE
	    CHECK_DIVZERO(sp->dval);
#endif

	    cp->dval = fmod(cp->dval, (sp--)->dval);
	    sp->type = C_DOUBLE;
	    sp->dval = cp->dval;
	    break;

	case _POW_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);
	    cp->dval = pow(cp->dval, (sp--)->dval);
	    sp->type = C_DOUBLE;
	    sp->dval = cp->dval;
	    break;

	    /* will anyone ever use these ? */

	case F_ADD_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    cast1_to_d(cellcpy(&tc, cp));
#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    tc.dval += (sp--)->dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    sp->type = C_DOUBLE;
	    sp->dval = tc.dval;
	    field_assign(cp, &tc);
	    break;

	case F_SUB_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    cast1_to_d(cellcpy(&tc, cp));
#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    tc.dval -= (sp--)->dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    sp->type = C_DOUBLE;
	    sp->dval = tc.dval;
	    field_assign(cp, &tc);
	    break;

	case F_MUL_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    cast1_to_d(cellcpy(&tc, cp));
#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    tc.dval *= (sp--)->dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    sp->type = C_DOUBLE;
	    sp->dval = tc.dval;
	    field_assign(cp, &tc);
	    break;

	case F_DIV_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    cast1_to_d(cellcpy(&tc, cp));

#ifdef  NOINFO_SIGFPE
	    CHECK_DIVZERO(sp->dval);
#endif

#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    tc.dval /= (sp--)->dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    sp->type = C_DOUBLE;
	    sp->dval = tc.dval;
	    field_assign(cp, &tc);
	    break;

	case F_MOD_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    cast1_to_d(cellcpy(&tc, cp));

#ifdef  NOINFO_SIGFPE
	    CHECK_DIVZERO(sp->dval);
#endif

	    tc.dval = fmod(tc.dval, (sp--)->dval);
	    sp->type = C_DOUBLE;
	    sp->dval = tc.dval;
	    field_assign(cp, &tc);
	    break;

	case F_POW_ASG:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    cp = (CELL *) (sp - 1)->ptr;
	    cast1_to_d(cellcpy(&tc, cp));
	    tc.dval = pow(tc.dval, (sp--)->dval);
	    sp->type = C_DOUBLE;
	    sp->dval = tc.dval;
	    field_assign(cp, &tc);
	    break;

	case _ADD:
	    sp--;
	    if (TEST2(sp) != TWO_DOUBLES)
		cast2_to_d(sp);
#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    sp[0].dval += sp[1].dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    break;

	case _SUB:
	    sp--;
	    if (TEST2(sp) != TWO_DOUBLES)
		cast2_to_d(sp);
#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    sp[0].dval -= sp[1].dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    break;

	case _MUL:
	    sp--;
	    if (TEST2(sp) != TWO_DOUBLES)
		cast2_to_d(sp);
#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    sp[0].dval *= sp[1].dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    break;

	case _DIV:
	    sp--;
	    if (TEST2(sp) != TWO_DOUBLES)
		cast2_to_d(sp);

#ifdef  NOINFO_SIGFPE
	    CHECK_DIVZERO(sp[1].dval);
#endif

#ifdef SW_FP_CHECK
	    clrerr();
#endif
	    sp[0].dval /= sp[1].dval;
#ifdef SW_FP_CHECK
	    fpcheck();
#endif
	    break;

	case _MOD:
	    sp--;
	    if (TEST2(sp) != TWO_DOUBLES)
		cast2_to_d(sp);

#ifdef  NOINFO_SIGFPE
	    CHECK_DIVZERO(sp[1].dval);
#endif

	    sp[0].dval = fmod(sp[0].dval, sp[1].dval);
	    break;

	case _POW:
	    sp--;
	    if (TEST2(sp) != TWO_DOUBLES)
		cast2_to_d(sp);
	    sp[0].dval = pow(sp[0].dval, sp[1].dval);
	    break;

	case _NOT:
	    /* evaluates to 0.0 or 1.0 */
	  reswitch_1:
	    switch (sp->type) {
	    case C_NOINIT:
		sp->dval = 1.0;
		break;
	    case C_DOUBLE:
		sp->dval = sp->dval != 0.0 ? 0.0 : 1.0;
		break;
	    case C_FIELDWIDTHS:
	    case C_STRING:
		sp->dval = string(sp)->len ? 0.0 : 1.0;
		free_STRING(string(sp));
		break;
	    case C_STRNUM:	/* test as a number */
		sp->dval = sp->dval != 0.0 ? 0.0 : 1.0;
		free_STRING(string(sp));
		break;
	    case C_MBSTRN:
		check_strnum(sp);
		goto reswitch_1;
	    default:
		bozo("bad type on eval stack");
	    }
	    sp->type = C_DOUBLE;
	    break;

	case _TEST:
	    /* evaluates to 0.0 or 1.0 */
	  reswitch_2:
	    switch (sp->type) {
	    case C_NOINIT:
		sp->dval = 0.0;
		break;
	    case C_DOUBLE:
		sp->dval = sp->dval != 0.0 ? 1.0 : 0.0;
		break;
	    case C_FIELDWIDTHS:
	    case C_STRING:
		sp->dval = string(sp)->len ? 1.0 : 0.0;
		free_STRING(string(sp));
		break;
	    case C_STRNUM:	/* test as a number */
		sp->dval = sp->dval != 0.0 ? 1.0 : 0.0;
		free_STRING(string(sp));
		break;
	    case C_MBSTRN:
		check_strnum(sp);
		goto reswitch_2;
	    default:
		bozo("bad type on eval stack");
	    }
	    sp->type = C_DOUBLE;
	    break;

	case _UMINUS:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    sp->dval = -sp->dval;
	    break;

	case _UPLUS:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    break;

	case _CAT:
	    {
		size_t len1, len2;
		char *str1, *str2;
		STRING *b;

		sp--;
		if (TEST2(sp) != TWO_STRINGS)
		    cast2_to_s(sp);
		str1 = string(sp)->str;
		len1 = string(sp)->len;
		str2 = string(sp + 1)->str;
		len2 = string(sp + 1)->len;

		b = new_STRING0(len1 + len2);
		memcpy(b->str, str1, len1);
		memcpy(b->str + len1, str2, len2);
		free_STRING(string(sp));
		free_STRING(string(sp + 1));

		sp->ptr = (PTR) b;
		break;
	    }

	case _PUSHINT:
	    inc_sp();
	    sp->type = (short) (cdp++)->op;
	    break;

	case _BUILTIN:
	case _PRINT:
	    sp = (*(PF_CP) (cdp++)->ptr) (sp);
	    break;

	case _POST_INC:
	    cp = (CELL *) sp->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);
	    sp->type = C_DOUBLE;
	    sp->dval = cp->dval;
	    cp->dval += 1.0;
	    break;

	case _POST_DEC:
	    cp = (CELL *) sp->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);
	    sp->type = C_DOUBLE;
	    sp->dval = cp->dval;
	    cp->dval -= 1.0;
	    break;

	case _PRE_INC:
	    cp = (CELL *) sp->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);
	    sp->dval = cp->dval += 1.0;
	    sp->type = C_DOUBLE;
	    break;

	case _PRE_DEC:
	    cp = (CELL *) sp->ptr;
	    if (cp->type != C_DOUBLE)
		cast1_to_d(cp);
	    sp->dval = cp->dval -= 1.0;
	    sp->type = C_DOUBLE;
	    break;

	case F_POST_INC:
	    cp = (CELL *) sp->ptr;
	    cellcpy(&tc, cp);
	    cast1_to_d(&tc);
	    sp->type = C_DOUBLE;
	    sp->dval = tc.dval;
	    tc.dval += 1.0;
	    field_assign(cp, &tc);
	    break;

	case F_POST_DEC:
	    cp = (CELL *) sp->ptr;
	    cellcpy(&tc, cp);
	    cast1_to_d(&tc);
	    sp->type = C_DOUBLE;
	    sp->dval = tc.dval;
	    tc.dval -= 1.0;
	    field_assign(cp, &tc);
	    break;

	case F_PRE_INC:
	    cp = (CELL *) sp->ptr;
	    cast1_to_d(cellcpy(sp, cp));
	    sp->dval += 1.0;
	    field_assign(cp, sp);
	    break;

	case F_PRE_DEC:
	    cp = (CELL *) sp->ptr;
	    cast1_to_d(cellcpy(sp, cp));
	    sp->dval -= 1.0;
	    field_assign(cp, sp);
	    break;

	case _JMP:
	    cdp += cdp->op;
	    break;

	case _JNZ:
	    /* jmp if top of stack is non-zero and pop stack */
	    if (test(sp))
		cdp += cdp->op;
	    else
		cdp++;
	    cell_destroy(sp);
	    sp--;
	    break;

	case _JZ:
	    /* jmp if top of stack is zero and pop stack */
	    if (!test(sp))
		cdp += cdp->op;
	    else
		cdp++;
	    cell_destroy(sp);
	    sp--;
	    break;

	case _LJZ:
	    /* special jump for logical and */
	    /* this is always preceded by _TEST */
	    if (sp->dval == 0.0) {
		/* take jump, but don't pop stack */
		cdp += cdp->op;
	    } else {
		/* pop and don't jump */
		sp--;
		cdp++;
	    }
	    break;

	case _LJNZ:
	    /* special jump for logical or */
	    /* this is always preceded by _TEST */
	    if (sp->dval != 0.0) {
		/* take jump, but don't pop stack */
		cdp += cdp->op;
	    } else {
		/* pop and don't jump */
		sp--;
		cdp++;
	    }
	    break;

	    /*  the relation operations */
	    /*  compare() makes sure string ref counts are OK */
	case _EQ:
	    t = compare(--sp);
	    sp->type = C_DOUBLE;
	    sp->dval = t == 0 ? 1.0 : 0.0;
	    break;

	case _NEQ:
	    t = compare(--sp);
	    sp->type = C_DOUBLE;
	    sp->dval = t ? 1.0 : 0.0;
	    break;

	case _LT:
	    t = compare(--sp);
	    sp->type = C_DOUBLE;
	    sp->dval = t < 0 ? 1.0 : 0.0;
	    break;

	case _LTE:
	    t = compare(--sp);
	    sp->type = C_DOUBLE;
	    sp->dval = t <= 0 ? 1.0 : 0.0;
	    break;

	case _GT:
	    t = compare(--sp);
	    sp->type = C_DOUBLE;
	    sp->dval = t > 0 ? 1.0 : 0.0;
	    break;

	case _GTE:
	    t = compare(--sp);
	    sp->type = C_DOUBLE;
	    sp->dval = t >= 0 ? 1.0 : 0.0;
	    break;

	case _MATCH0:
	    /* does $0 match, the RE at cdp? */

	    inc_sp();
	    if (field->type >= C_STRING) {
		sp->type = C_DOUBLE;
		sp->dval = (REtest(string(field)->str,
				   string(field)->len,
				   cast_to_re((cdp++)->ptr))
			    ? 1.0
			    : 0.0);

		break /* the case */ ;
	    } else {
		cellcpy(sp, field);
		/* and FALL THRU */
	    }

	case _MATCH1:
	    /* does expr at sp[0] match RE at cdp */
	    if (sp->type < C_STRING)
		cast1_to_s(sp);
	    t = REtest(string(sp)->str,
		       string(sp)->len,
		       cast_to_re((cdp++)->ptr));
	    free_STRING(string(sp));
	    sp->type = C_DOUBLE;
	    sp->dval = t ? 1.0 : 0.0;
	    break;

	case _MATCH2:
	    /* does sp[-1] match sp[0] as re */
	    cast_to_RE(sp);

	    if ((--sp)->type < C_STRING)
		cast1_to_s(sp);
	    t = REtest(string(sp)->str,
		       string(sp)->len,
		       cast_to_re((sp + 1)->ptr));

	    free_STRING(string(sp));
	    no_leaks_re_ptr((sp + 1)->ptr);
	    sp->type = C_DOUBLE;
	    sp->dval = t ? 1.0 : 0.0;
	    break;

	case A_LENGTH:
	    sp--;
	    sp->type = C_DOUBLE;
	    sp->dval = (double) (((ARRAY) ((sp + 0)->ptr))->size);
	    break;

	case A_TEST:
	    /* entry :  sp[0].ptr-> an array
	       sp[-1]  is an expression

	       we compute       (expression in array)  */
	    sp--;
	    cp = array_find((sp + 1)->ptr, sp, NO_CREATE);
	    cell_destroy(sp);
	    sp->type = C_DOUBLE;
	    sp->dval = (cp != (CELL *) 0) ? 1.0 : 0.0;
	    break;

	case A_DEL:
	    /* sp[0].ptr ->  array
	       sp[-1] is an expr
	       delete  array[expr]      */

	    array_delete(sp->ptr, sp - 1);
	    cell_destroy(sp - 1);
	    sp -= 2;
	    break;

	case DEL_A:
	    /* free all the array at once */
	    array_clear(sp->ptr);
	    sp--;
	    break;

	    /* form a multiple array index */
	case A_CAT:
	    sp = array_cat(sp, (cdp++)->op);
	    break;

	case _EXIT:
	    if (sp->type != C_DOUBLE)
		cast1_to_d(sp);
	    exit_code = d_to_i(sp->dval);
	    sp--;
	    /* fall thru */

	case _EXIT0:

	    if (force_exit)
		mawk_exit(exit_code);

	    cdp = end_start;
	    force_exit = 1;	/* makes sure next exit exits */

	    if (begin_start) {
		free_codes("BEGIN", begin_start, begin_size);
		begin_start = 0;
		begin_size = 0;
	    }
	    if (main_start) {
		free_codes("MAIN", main_start, main_size);
		main_start = 0;
		main_size = 0;
	    }
	    sp = eval_stack - 1;	/* might be in user function */
	    CLEAR_ALOOP_STACK();	/* ditto */
	    break;

	case _JMAIN:		/* go from BEGIN code to MAIN code */
	    free_codes("BEGIN", begin_start, begin_size);
	    begin_start = 0;
	    begin_size = 0;
	    cdp = main_start;
	    break;

	case _OMAIN:
	    if (!main_fin)
		open_main();
	    restart_label = cdp;
	    cdp = next_label;
	    break;

	case _NEXT:
	    /* next might be inside an aloop -- clear stack */
	    CLEAR_ALOOP_STACK();
	    cdp = next_label;
	    break;

	case _NEXTFILE:
	    /* nextfile might be inside an aloop -- clear stack */
	    CLEAR_ALOOP_STACK();
	    FINsemi_close(main_fin);
	    cdp = next_label;
	    break;

	case OL_GL:
	    {
		char *p;
		size_t len;

		if (!(p = FINgets(main_fin, &len))) {
		    if (force_exit)
			mawk_exit(0);

		    cdp = end_start;
		    zfree(main_start, main_size);
		    main_start = (INST *) 0;
		    force_exit = 1;
		} else {
		    set_field0(p, len);
		    cdp = restart_label;
		    rt_nr++;
		    rt_fnr++;
		}
	    }
	    break;

	    /* two kinds of OL_GL is a historical stupidity from working on
	       a machine with very slow floating point emulation */
	case OL_GL_NR:
	    {
		char *p;
		size_t len;

		if (!(p = FINgets(main_fin, &len))) {
		    if (force_exit)
			mawk_exit(0);

		    cdp = end_start;
		    zfree(main_start, main_size);
		    main_start = (INST *) 0;
		    force_exit = 1;
		} else {
		    set_field0(p, len);
		    cdp = restart_label;

		    if (TEST2(NR) != TWO_DOUBLES)
			cast2_to_d(NR);

		    NR->dval += 1.0;
		    rt_nr++;
		    FNR->dval += 1.0;
		    rt_fnr++;
		}
	    }
	    break;

	case _RANGE:
/* test a range pattern:  pat1, pat2 { action }
   entry :
       cdp[0].op -- a flag, test pat1 if on else pat2
       cdp[1].op -- offset of pat2 code from cdp
       cdp[2].op -- offset of action code from cdp
       cdp[3].op -- offset of code after the action from cdp
       cdp[4] -- start of pat1 code
*/

#define FLAG      cdp[0].op
#define PAT2      cdp[1].op
#define ACTION    cdp[2].op
#define FOLLOW    cdp[3].op
#define PAT1      4

	    if (FLAG)		/* test against pat1 */
	    {
		execute(cdp + PAT1, sp, fp);
		t = test(sp + 1);
		cell_destroy(sp + 1);
		if (t)
		    FLAG = 0;
		else {
		    cdp += FOLLOW;
		    break;	/* break the switch */
		}
	    }

	    /* test against pat2 and then perform the action */
	    execute(cdp + PAT2, sp, fp);
	    FLAG = test(sp + 1);
	    cell_destroy(sp + 1);
	    cdp += ACTION;
	    break;

/* function calls  */

	case _RET0:
	    inc_sp();
	    sp->type = C_NOINIT;
	    /* fall thru */

	case _RET:

#ifdef	DEBUG
	    if (sp != entry_sp + 1)
		bozo("ret");
#endif
	    if (old_stack_base)	/* reset stack */
	    {
		/* move the return value */
		cellcpy(old_sp + 1, sp);
		cell_destroy(sp);
		zfree(stack_base, sizeof(CELL) * EVAL_STACK_SIZE);
		stack_base = old_stack_base;
		stack_danger = old_stack_base + DANGER;
	    }

	    /* return might be inside an aloop -- clear stack */
	    CLEAR_ALOOP_STACK();

	    return;

	case _CALL:

	    /*  cdp[0] holds ptr to "function block"
	       cdp[1] holds number of input arguments
	     */

	    {
		FBLOCK *fbp = (FBLOCK *) (cdp++)->ptr;
		int a_args = (cdp++)->op;	/* actual number of args */
		CELL *nfp = sp - a_args + 1;	/* new fp for callee */
		CELL *local_p = sp + 1;		/* first local argument on stack */
		char *type_p = 0;	/* pts to type of an argument */

		if (fbp->nargs)
		    type_p = fbp->typev + a_args - 1;

		/* create space for locals */
		t = fbp->nargs - a_args;	/* t is number of locals */
		while (t > 0) {
		    t--;
		    sp++;
		    type_p++;
		    sp->type = C_NOINIT;
		    if ((type_p) != 0 && (*type_p == ST_LOCAL_ARRAY))
			sp->ptr = (PTR) new_ARRAY();
		}

		execute(fbp->code, sp, nfp);

		/* cleanup the callee's arguments */
		/* putting return value at top of eval stack */
		if ((type_p != 0) && (sp >= nfp)) {
		    cp = sp + 1;	/* cp -> the function return */

		    do {
			if (*type_p == ST_LOCAL_ARRAY) {
			    if (sp >= local_p) {
				array_clear(sp->ptr);
				ZFREE((ARRAY) sp->ptr);
			    }
			} else {
			    cell_destroy(sp);
			}

			type_p--;
			sp--;

		    }
		    while (sp >= nfp);

		    cellcpy(++sp, cp);
		    cell_destroy(cp);
		} else
		    sp++;	/* no arguments passed */
	    }
	    break;

	default:
	    bozo("bad opcode");
	}
    }
}
Пример #4
0
static void TranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle)
{
    int integerConstructor = 0;
    bstring glsl = *psContext->currentGLSLString;

    *pui32IgnoreSwizzle = 0;

    if(psOperand->eType != OPERAND_TYPE_IMMEDIATE32 &&
        psOperand->eType != OPERAND_TYPE_IMMEDIATE64 &&
        psOperand->eType != OPERAND_TYPE_CONSTANT_BUFFER)
    {
		const uint32_t swizCount = psOperand->iNumComponents;
		SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand);

		if( (ui32TOFlag & (TO_FLAG_INTEGER|TO_FLAG_UNSIGNED_INTEGER)) == (TO_FLAG_INTEGER|TO_FLAG_UNSIGNED_INTEGER))
		{
			//Can be either int or uint
			if(eType != SVT_INT && eType != SVT_UINT)
			{
				if(swizCount == 1)
					bformata(glsl, "int(");
				else
					bformata(glsl, "ivec%d(", swizCount);

				integerConstructor = 1;
			}
		}
		else
		{
			if((ui32TOFlag & (TO_FLAG_INTEGER|TO_FLAG_DESTINATION))==TO_FLAG_INTEGER &&
				eType != SVT_INT)
			{
				//Convert to int
				if(swizCount == 1)
					bformata(glsl, "int(");
				else
					bformata(glsl, "ivec%d(", swizCount);

				integerConstructor = 1;
			}
			if((ui32TOFlag & (TO_FLAG_UNSIGNED_INTEGER|TO_FLAG_DESTINATION))==TO_FLAG_UNSIGNED_INTEGER &&
				eType != SVT_UINT)
			{
				//Convert to uint
				if(swizCount == 1)
					bformata(glsl, "uint(");
				else
					bformata(glsl, "uvec%d(", swizCount);
				integerConstructor = 1;
			}
		}
    }

    switch(psOperand->eType)
    {
        case OPERAND_TYPE_IMMEDIATE32:
        {
            if(psOperand->iNumComponents == 1)
            {
				if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER)
				{
					bformata(glsl, "%uu",
						*((unsigned int*)(&psOperand->afImmediates[0])));
				}
                else
				if((ui32TOFlag & TO_FLAG_INTEGER) || psOperand->iIntegerImmediate || fpcheck(psOperand->afImmediates[0]))
				{
					bformata(glsl, "%d",
						*((int*)(&psOperand->afImmediates[0])));
				}
				else
				{
					bformata(glsl, "%f",
                    psOperand->afImmediates[0]);
				}
            }
            else
            {
                if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER)
                {
                    bformata(glsl, "uvec4(%uu, %uu, %uu, %uu)",
                        *(unsigned int*)&psOperand->afImmediates[0],
                        *(unsigned int*)&psOperand->afImmediates[1],
                        *(unsigned int*)&psOperand->afImmediates[2],
                        *(unsigned int*)&psOperand->afImmediates[3]);
                }
                else
                if((ui32TOFlag & TO_FLAG_INTEGER) ||
                    psOperand->iIntegerImmediate ||
                    fpcheck(psOperand->afImmediates[0]) ||
                    fpcheck(psOperand->afImmediates[1]) ||
                    fpcheck(psOperand->afImmediates[2]) ||
                    fpcheck(psOperand->afImmediates[3]))
                {
                    bformata(glsl, "ivec4(%d, %d, %d, %d)",
                        *(int*)&psOperand->afImmediates[0],
                        *(int*)&psOperand->afImmediates[1],
                        *(int*)&psOperand->afImmediates[2],
                        *(int*)&psOperand->afImmediates[3]);
                }
                else
                {
                    bformata(glsl, "vec4(%f, %f, %f, %f)",
                        psOperand->afImmediates[0],
                        psOperand->afImmediates[1],
                        psOperand->afImmediates[2],
                        psOperand->afImmediates[3]);
                }
                if(psOperand->iNumComponents != 4)
                {
                    AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents);
                }
            }
            break;
        }
        case OPERAND_TYPE_IMMEDIATE64:
        {
            if(psOperand->iNumComponents == 1)
            {
                bformata(glsl, "%f",
                    psOperand->adImmediates[0]);
            }
            else
            {
                bformata(glsl, "dvec4(%f, %f, %f, %f)",
                    psOperand->adImmediates[0],
                    psOperand->adImmediates[1],
                    psOperand->adImmediates[2],
                    psOperand->adImmediates[3]);
                if(psOperand->iNumComponents != 4)
                {
                    AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents);
                }
            }
            break;
        }
        case OPERAND_TYPE_INPUT:
        {
            switch(psOperand->iIndexDims)
            {
                case INDEX_2D:
                {
                    if(psOperand->aui32ArraySizes[1] == 0)//Input index zero - position.
                    {
                        bcatcstr(glsl, "gl_in");
                        TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE);//Vertex index
                        bcatcstr(glsl, ".gl_Position");
                    }
                    else
                    {
                        const char* name = "Input";
                        if(ui32TOFlag & TO_FLAG_DECLARATION_NAME)
                        {
                            name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand);
                        }
                        
                        bformata(glsl, "%s%d", name, psOperand->aui32ArraySizes[1]);
                        TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE);//Vertex index
                    }
                    break;
                }
                default:
                {
                    if(psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE)
                    {
                        bformata(glsl, "Input%d[int(", psOperand->ui32RegisterNumber);
                        TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE);
                        bcatcstr(glsl, ")]");
                    }
                    else
                    {
                        if(psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0)
                        {
                            const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber];
                            bformata(glsl, "Input%d[%d]", parentIndex,
                                psOperand->ui32RegisterNumber - parentIndex);
                        }
                        else
                        {
                            if(ui32TOFlag & TO_FLAG_DECLARATION_NAME)
                            {
                                const char* name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand);
								bcatcstr(glsl, name);
                            }
							else
							{
								bformata(glsl, "Input%d", psOperand->ui32RegisterNumber);
							}
                        }
                    }
                    break;
                }
            }
            break;
        }
        case OPERAND_TYPE_OUTPUT:
        {
            bformata(glsl, "Output%d", psOperand->ui32RegisterNumber);
            if(psOperand->psSubOperand[0])
            {
                bcatcstr(glsl, "[int("); //Indexes must be integral.
                TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE);
                bcatcstr(glsl, ")]");
            }
            break;
        }
        case OPERAND_TYPE_OUTPUT_DEPTH:
        case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL:
        case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL:
        {
            bcatcstr(glsl, "gl_FragDepth");
            break;
        }
        case OPERAND_TYPE_TEMP:
        {
			SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand);
            bcatcstr(glsl, "Temp");

            if(eType == SVT_INT)
            {
                bcatcstr(glsl, "_int");
            }
            else if(eType == SVT_UINT)
            {
                bcatcstr(glsl, "_uint");
            }
			else if(eType == SVT_DOUBLE)
			{
				bcatcstr(glsl, "_double");
			}
            else if(eType == SVT_VOID ||
                (ui32TOFlag & TO_FLAG_DESTINATION))
            {
                if(ui32TOFlag & TO_FLAG_INTEGER)
                {
                    bcatcstr(glsl, "_int");
                }
                else
                if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER)
                {
                    bcatcstr(glsl, "_uint");
                }
            }

			bformata(glsl, "[%d]", psOperand->ui32RegisterNumber);

            break;
        }
		case OPERAND_TYPE_SPECIAL_IMMCONSTINT:
		{
            bformata(glsl, "IntImmConst%d", psOperand->ui32RegisterNumber);
            break;
		}
        case OPERAND_TYPE_SPECIAL_IMMCONST:
        {
            bformata(glsl, "ImmConst%d", psOperand->ui32RegisterNumber);
            break;
        }
        case OPERAND_TYPE_SPECIAL_OUTBASECOLOUR:
        {
            bcatcstr(glsl, "BaseColour");
            break;
        }
        case OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR:
        {
            bcatcstr(glsl, "OffsetColour");
            break;
        }
        case OPERAND_TYPE_SPECIAL_POSITION:
        {
            bcatcstr(glsl, "gl_Position");
            break;
        }
        case OPERAND_TYPE_SPECIAL_FOG:
        {
            bcatcstr(glsl, "Fog");
            break;
        }
        case OPERAND_TYPE_SPECIAL_POINTSIZE:
        {
            bcatcstr(glsl, "gl_PointSize");
            break;
        }
        case OPERAND_TYPE_SPECIAL_ADDRESS:
        {
            bcatcstr(glsl, "Address");
            break;
        }
		case OPERAND_TYPE_SPECIAL_TEXCOORD:
		{
			bformata(glsl, "TexCoord%d", psOperand->ui32RegisterNumber);
			break;
		}
        case OPERAND_TYPE_CONSTANT_BUFFER:
        {
            const char* StageName = "VS";
            ConstantBuffer* psCBuf = NULL;
            ShaderVarType* psVarType = NULL;
            int32_t index = -1;
            GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf);

            switch(psContext->psShader->eShaderType)
            {
                case PIXEL_SHADER:
                {
                    StageName = "PS";
                    break;
                }
                case HULL_SHADER:
                {
                    StageName = "HS";
                    break;
                }
                case DOMAIN_SHADER:
                {
                    StageName = "DS";
                    break;
                }
                case GEOMETRY_SHADER:
                {
                    StageName = "GS";
                    break;
                }
				case COMPUTE_SHADER:
				{
					StageName = "CS";
					break;
				}
                default:
                {
                    break;
                }
            }

            if(ui32TOFlag & TO_FLAG_DECLARATION_NAME)
            {
                pui32IgnoreSwizzle[0] = 1;
            }

			if((psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT)!=HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT)
			{
				if(psCBuf)
				{
					//$Globals.
					if(psCBuf->Name[0] == '$')
					{
						bformata(glsl, "Globals%s", StageName);
					}
					else
					{
						bformata(glsl, "%s%s", psCBuf->Name, StageName);
					}
					if((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME)
					{
						bcatcstr(glsl, ".");
					}
				}
				else
				{
					//bformata(glsl, "cb%d", psOperand->aui32ArraySizes[0]);
				}
		}

            if((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME)
            {
                //Work out the variable name. Don't apply swizzle to that variable yet.
				int32_t rebase = 0;

				if(psCBuf)
				{
					GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase);

					bformata(glsl, "%s", psVarType->FullName);
				}
				else // We don't have a semantic for this variable, so try the raw dump appoach.
				{
					bformata(glsl, "cb%d.data", psOperand->aui32ArraySizes[0]);//
					index = psOperand->aui32ArraySizes[1];
				}

				//Dx9 only?
				if(psOperand->psSubOperand[0] != NULL)
				{
					SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[0]);
					if(eType != SVT_INT && eType != SVT_UINT)
					{
						bcatcstr(glsl, "[int("); //Indexes must be integral.
						TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE);
						bcatcstr(glsl, ")]");
					}
					else
					{
						bcatcstr(glsl, "["); //Indexes must be integral.
						TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE);
						bcatcstr(glsl, "]");
					}

					ASSERT(index == 0 || index == -1);
				}
				else
				if(index != -1 && psOperand->psSubOperand[1] != NULL)
				{
					//Array of matrices is treated as array of vec4s
					if(index != -1)
					{
						SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[1]);
						if(eType != SVT_INT && eType != SVT_UINT)
						{
							bcatcstr(glsl, "[int(");
							TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE);
							bformata(glsl, ") + %d]", index);
						}
						else
						{
							bcatcstr(glsl, "[");
							TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE);
							bformata(glsl, " + %d]", index);
						}
					}
				}
				else if(index != -1)
                {
                    bformata(glsl, "[%d]", index);
                }
				else if(psOperand->psSubOperand[1] != NULL)
				{
					SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[1]);
					if(eType != SVT_INT && eType != SVT_UINT)
					{
						bcatcstr(glsl, "[");
						TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE);
						bcatcstr(glsl, "]");
					}
					else
					{
						bcatcstr(glsl, "[int(");
						TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE);
						bcatcstr(glsl, ")]");
					}
				}

				if(psVarType && psVarType->Class == SVC_VECTOR)
				{
					switch(rebase)
					{
						case 4:
						{
							if(psVarType->Columns == 2)
							{
								//.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL)
								bcatcstr(glsl, ".xxyx");
							}
							else if(psVarType->Columns == 3)
							{
								//.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) .z(GLSL) is .w(HLSL)
								bcatcstr(glsl, ".xxyz");
							}
							break;
						}
						case 8:
						{
							if(psVarType->Columns == 2)
							{
								//.x(GLSL) is .z(HLSL). .y(GLSL) is .w(HLSL)
								bcatcstr(glsl, ".xxxy");
							}
							break;
						}
						case 0:
						default:
						{
							//No rebase, but extend to vec4.
							if(psVarType->Columns == 2)
							{
								bcatcstr(glsl, ".xyxx");
							}
							else if(psVarType->Columns == 3)
							{
								bcatcstr(glsl, ".xyzx");
							}
							break;
						}

					}
				}

				if(psVarType && psVarType->Class == SVC_SCALAR)
				{
					*pui32IgnoreSwizzle = 1;
				}
            }
            break;
        }
        case OPERAND_TYPE_RESOURCE:
        {
            TextureName(psContext, psOperand->ui32RegisterNumber, 0);
			*pui32IgnoreSwizzle = 1;
            break;
        }
        case OPERAND_TYPE_SAMPLER:
        {
            bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber);
			*pui32IgnoreSwizzle = 1;
            break;
        }
        case OPERAND_TYPE_FUNCTION_BODY:
        {
            const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber;
            const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody];
            //const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable];
            const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable];
            const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0];
            const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++;

            bformata(glsl, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex);
            break;
        }
		case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID:
		{
			bcatcstr(glsl, "forkInstanceID");
            *pui32IgnoreSwizzle = 1;
			return;
		}
		case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER:
		{
            bcatcstr(glsl, "immediateConstBufferF");

            if(psOperand->psSubOperand[0])
            {
                bcatcstr(glsl, "(int("); //Indexes must be integral.
                TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE);
                bcatcstr(glsl, "))");
            }
			break;
		}
		case OPERAND_TYPE_INPUT_DOMAIN_POINT:
		{
			bcatcstr(glsl, "gl_TessCoord");
			break;
		}
		case OPERAND_TYPE_INPUT_CONTROL_POINT:
		{
			if(psOperand->aui32ArraySizes[1] == 0)//Input index zero - position.
			{
				bformata(glsl, "gl_in[%d].gl_Position", psOperand->aui32ArraySizes[0]);
			}
            else
            {
                bformata(glsl, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]);
            }
            break;
		}
		case OPERAND_TYPE_NULL:
		{
			// Null register, used to discard results of operations
			bcatcstr(glsl, "//null");
			break;
		}
        case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID:
        {
            bcatcstr(glsl, "gl_InvocationID");
            *pui32IgnoreSwizzle = 1;
            break;
        }
        case OPERAND_TYPE_OUTPUT_COVERAGE_MASK:
        {
            bcatcstr(glsl, "gl_SampleMask[0]");
            *pui32IgnoreSwizzle = 1;
            break;
        }
        case OPERAND_TYPE_INPUT_COVERAGE_MASK:
        {
            bcatcstr(glsl, "gl_SampleMaskIn[0]");
            //Skip swizzle on scalar types.
            *pui32IgnoreSwizzle = 1;
            break;
        }
		case OPERAND_TYPE_INPUT_THREAD_ID://SV_DispatchThreadID
		{
			bcatcstr(glsl, "gl_GlobalInvocationID");
			break;
		}
		case OPERAND_TYPE_INPUT_THREAD_GROUP_ID://SV_GroupThreadID
		{
			bcatcstr(glsl, "gl_LocalInvocationID");
			break;
		}
		case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP://SV_GroupID
		{
			bcatcstr(glsl, "gl_WorkGroupID");
			break;
		}
		case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED://SV_GroupIndex
		{
			bcatcstr(glsl, "gl_LocalInvocationIndex");
			break;
		}
        case OPERAND_TYPE_UNORDERED_ACCESS_VIEW:
        {
            bformata(glsl, "UAV%d", psOperand->ui32RegisterNumber);
            break;
        }
        case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY:
        {
            bformata(glsl, "TGSM%d", psOperand->ui32RegisterNumber);
            break;
        }
		case OPERAND_TYPE_INPUT_PRIMITIVEID:
		{
			bcatcstr(glsl, "gl_PrimitiveID");
			break;
		}
        case OPERAND_TYPE_INDEXABLE_TEMP:
        {
            bformata(glsl, "TempArray%d", psOperand->aui32ArraySizes[0]);
            bformata(glsl, "[%d", psOperand->aui32ArraySizes[1]);
            
            if(psOperand->psSubOperand[1])
            {
                bcatcstr(glsl, "+");
                TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_NONE);
                
            }
            bcatcstr(glsl, "]");
            break;
        }
		case OPERAND_TYPE_STREAM:
		{
			bformata(glsl, "%d", psOperand->ui32RegisterNumber);
			break;
		}
		case OPERAND_TYPE_INPUT_GS_INSTANCE_ID:
		{
			bcatcstr(glsl, "gl_InvocationID");
			break;
		}
		case OPERAND_TYPE_THIS_POINTER:
		{
			/*
				The "this" register is a register that provides up to 4 pieces of information:
				X: Which CB holds the instance data
				Y: Base element offset of the instance data within the instance CB
				Z: Base sampler index
				W: Base Texture index

				Can be different for each function call
			*/
			break;
		}
        default:
        {
            ASSERT(0);
            break;
        }
    }

    if(integerConstructor)
    {
        bcatcstr(glsl, ")");
    }
}
Пример #5
0
static void TranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle)
{
    bstring glsl = *psContext->currentGLSLString;

    *pui32IgnoreSwizzle = 0;

    switch(psOperand->eType)
    {
        case OPERAND_TYPE_IMMEDIATE32:
        {
            if(psOperand->iNumComponents == 1)
            {
				if((ui32TOFlag & TO_FLAG_INTEGER) || psOperand->iIntegerImmediate || fpcheck(psOperand->afImmediates[0]))
				{
					bformata(glsl, "%d",
						*((int*)(&psOperand->afImmediates[0])));
				}
				else
				{
					bformata(glsl, "%f",
                    psOperand->afImmediates[0]);
				}
            }
            else
            if(psOperand->iNumComponents == 4)
            {
                if((ui32TOFlag & TO_FLAG_INTEGER) ||
                    psOperand->iIntegerImmediate ||
                    fpcheck(psOperand->afImmediates[0]) ||
                    fpcheck(psOperand->afImmediates[1]) ||
                    fpcheck(psOperand->afImmediates[2]) ||
                    fpcheck(psOperand->afImmediates[3]))
                {
                    bformata(glsl, "vec4(%d, %d, %d, %d)",
                        *(int*)&psOperand->afImmediates[0],
                        *(int*)&psOperand->afImmediates[1],
                        *(int*)&psOperand->afImmediates[2],
                        *(int*)&psOperand->afImmediates[3]);
                }
                else
                {
                    bformata(glsl, "vec4(%f, %f, %f, %f)",
                        psOperand->afImmediates[0],
                        psOperand->afImmediates[1],
                        psOperand->afImmediates[2],
                        psOperand->afImmediates[3]);
                }
            }
            break;
        }
        case OPERAND_TYPE_INPUT:
        {
            switch(psOperand->iIndexDims)
            {
                case INDEX_2D:
                {
                    if(psOperand->aui32ArraySizes[1] == 0)//Input index zero - position.
                    {
                        bcatcstr(glsl, "gl_in");
                        TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE);//Vertex index
                        bcatcstr(glsl, ".gl_Position");
                    }
                    else
                    {
                        const char* name = "Input";
                        if(ui32TOFlag & TO_FLAG_DECLARATION_NAME)
                        {
                            name = GetDeclaredName(psContext->psShader->eShaderType, psContext->flags);
                        }
                        
                        bformata(glsl, "%s%d", name, psOperand->aui32ArraySizes[1]);
                        TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE);//Vertex index
                    }
                    break;
                }
                default:
                {
                    if(psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE)
                    {
                        bformata(glsl, "Input%d[int(", psOperand->ui32RegisterNumber);
                        TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE);
                        bcatcstr(glsl, ")]");
                    }
                    else
                    {
                        if(psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0)
                        {
                            const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber];
                            bformata(glsl, "Input%d[%d]", parentIndex,
                                psOperand->ui32RegisterNumber - parentIndex);
                        }
                        else
                        {
                            const char* name = "Input";
                            if(ui32TOFlag & TO_FLAG_DECLARATION_NAME)
                            {
                                name = GetDeclaredName(psContext->psShader->eShaderType, psContext->flags);
                            }

                            bformata(glsl, "%s%d", name, psOperand->ui32RegisterNumber);
                        }
                    }
                    break;
                }
            }
            break;
        }
        case OPERAND_TYPE_OUTPUT:
        {
            bformata(glsl, "Output%d", psOperand->ui32RegisterNumber);
            if(psOperand->psSubOperand[0])
            {
                bcatcstr(glsl, "[int("); //Indexes must be integral.
                TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE);
                bcatcstr(glsl, ")]");
            }
            break;
        }
        case OPERAND_TYPE_OUTPUT_DEPTH:
        case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL:
        case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL:
        {
            bcatcstr(glsl, "gl_FragDepth");
            break;
        }
        case OPERAND_TYPE_TEMP:
        {
            bformata(glsl, "Temp%d", psOperand->ui32RegisterNumber);
            break;
        }
        case OPERAND_TYPE_CONSTANT_BUFFER:
        {
            const char* StageName = "VS";
            ConstantBuffer* psCBuf = NULL;
            GetConstantBufferFromBindingPoint(psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf);

            switch(psContext->psShader->eShaderType)
            {
                case PIXEL_SHADER:
                {
                    StageName = "PS";
                    break;
                }
                case HULL_SHADER:
                {
                    StageName = "HS";
                    break;
                }
                case DOMAIN_SHADER:
                {
                    StageName = "DS";
                    break;
                }
                case GEOMETRY_SHADER:
                {
                    StageName = "GS";
                    break;
                }
                default:
                {
                    break;
                }
            }


#if CBUFFER_USE_STRUCT_AND_NAMES
            {
                char* pszContBuffName;

                pszContBuffName = psCBuf->Name;
                
                if(psCBuf->Name[0] == '$')//$Global or $Param
                    pszContBuffName++;

                ASSERT(psOperand->aui32ArraySizes[1] < psCBuf->ui32NumVars);
                
                bformata(glsl, "%s%s.%s", pszContBuffName, StageName, psCBuf->asVars[psOperand->aui32ArraySizes[1]].Name);
            }
#else
			if(psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT)
			{
                if((psCBuf->Name[0] == '$') && (psContext->flags & HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO))
                {
                    bformata(glsl, "Globals%s[%d]", StageName, psOperand->aui32ArraySizes[1]);
                }
                else
                {
				    //Each uniform block is given the HLSL consant buffer name.
				    //Within each uniform block is a constant array named ConstN
				    bformata(glsl, "Const%d[%d]", psOperand->aui32ArraySizes[0], psOperand->aui32ArraySizes[1]);
                }
			}
			else
			{
				//$Globals.
				if(psCBuf->Name[0] == '$')
				{
					bformata(glsl, "Globals%s[%d]", StageName, psOperand->aui32ArraySizes[1]);
				}
				else
				{
					bformata(glsl, "%s%s[%d]", psCBuf->Name, StageName, psOperand->aui32ArraySizes[1]);
				}
			}
#endif
            break;
        }
        case OPERAND_TYPE_RESOURCE:
        {
            TextureName(psContext, psOperand->ui32RegisterNumber, 0);
            break;
        }
        case OPERAND_TYPE_SAMPLER:
        {
            bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber);
            break;
        }
        case OPERAND_TYPE_FUNCTION_BODY:
        {
            const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber;
            const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody];
            //const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable];
            const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable];
            const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0];
            const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++;

            bformata(glsl, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex);
            break;
        }
		case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID:
		{
			bcatcstr(glsl, "forkInstanceID");
            *pui32IgnoreSwizzle = 1;
			return;
		}
		case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER:
		{
            bcatcstr(glsl, "immediateConstBufferF");

            if(psOperand->psSubOperand[0])
            {
                bcatcstr(glsl, "(int("); //Indexes must be integral.
                TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE);
                bcatcstr(glsl, "))");
            }
			break;
		}
		case OPERAND_TYPE_INPUT_DOMAIN_POINT:
		{
			bcatcstr(glsl, "gl_TessCoord");
			break;
		}
		case OPERAND_TYPE_INPUT_CONTROL_POINT:
		{
			if(psOperand->aui32ArraySizes[1] == 0)//Input index zero - position.
			{
				bformata(glsl, "gl_in[%d].gl_Position", psOperand->aui32ArraySizes[0]);
			}
            else
            {
                bformata(glsl, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]);
            }
            break;
		}
		case OPERAND_TYPE_NULL:
		{
			// Null register, used to discard results of operations
			bcatcstr(glsl, "//null");
			break;
		}
        case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID:
        {
            bcatcstr(glsl, "gl_InvocationID");
            *pui32IgnoreSwizzle = 1;
            break;
        }
        case OPERAND_TYPE_OUTPUT_COVERAGE_MASK:
        {
            bcatcstr(glsl, "gl_SampleMask[0]");
            *pui32IgnoreSwizzle = 1;
            break;
        }
        case OPERAND_TYPE_INPUT_COVERAGE_MASK:
        {
            bcatcstr(glsl, "gl_SampleMaskIn[0]");
            //Skip swizzle on scalar types.
            *pui32IgnoreSwizzle = 1;
            break;
        }
        default:
        {
            ASSERT(0);
            break;
        }
    }
}