This is intb.c in view mode; [Download] [Up]
/* * Copyright (C) 1985-1992 New York University * * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for * warranty (none) and distribution info and also the GNU General Public * License for more details. */ /* Continuation of ada interpreter - auxiliary procedures */ /* Include standard header modules */ #include <stdlib.h> #include <setjmp.h> #include "config.h" #include "int.h" #include "ivars.h" #include "machineprots.h" #include "farithprots.h" #include "taskingprots.h" #include "predefprots.h" #include "intcprots.h" #include "intbprots.h" extern jmp_buf raise_env; static void update_address(int *); static void image_attribute(); static void value_attribute(); static int same_dimensions(int *, int *); static int compare_fields_record(int *, int *, int *); void main_attr(int attribute, int dim) /*;attribute*/ { switch(attribute) { case ATTR_ADDRESS: POP_ADDR(bse, off); create(2, &bas1, &off1, &ptr1);/* ADDRESS is a record */ *ADDR(bas1, off1) = bse; *ADDR(bas1, off1 + 1) = off; PUSH_ADDR(bas1, off1); break; case ATTR_CALLABLE: POP(value); /* task object */ value = (is_callable(value)); PUSH(value); break; case ATTR_COUNT: POP(val2); /* member in family */ POP(val1); /* entry family */ value = count(val1, val2); PUSH(value); break; case ATTR_T_CONSTRAINED: break; case ATTR_O_CONSTRAINED: break; case ATTR_T_FIRST: case ATTR_T_LAST: POP_ADDR(bse, off);/* type */ ptr = ADDR(bse, off); size = SIZE(ptr); if (TYPE(ptr) == TT_FX_RANGE) { if (attribute == ATTR_T_FIRST) PUSHL(FX_RANGE(ptr)->fxlow); else PUSHL(FX_RANGE(ptr)->fxhigh); } else if (TYPE(ptr) == TT_FL_RANGE) { if (attribute == ATTR_T_FIRST) PUSHF(FL_RANGE(ptr)->fllow); else PUSHF(FL_RANGE(ptr)->flhigh); } else if ((TYPE(ptr) == TT_I_RANGE) || (TYPE(ptr) == TT_E_RANGE) || (TYPE(ptr) == TT_ENUM)) { if (attribute == ATTR_T_FIRST) PUSH(I_RANGE(ptr)->ilow); else PUSH(I_RANGE(ptr)->ihigh); } #ifdef LONG_INT else if (TYPE(ptr) == TT_L_RANGE) { if (attribute == ATTR_T_FIRST) PUSHL(L_RANGE(ptr)->llow); else PUSHL(L_RANGE(ptr)->lhigh); } #endif else /* error */ raise(SYSTEM_ERROR,"Unknown type for attribute FIRST or LAST"); break; case ATTR_O_FIRST: case ATTR_O_LAST: POP_ADDR(bse, off);/* type */ ptr = ADDR(bse, off); POP_ADDR(bas1, off1);/* to get rid of array */ val1 = *ptr; /* type of type */ if (val1 == TT_S_ARRAY) { if (attribute == ATTR_O_LAST) value = S_ARRAY(ptr)->sahigh; else value = S_ARRAY(ptr)->salow; PUSH(value); } else if (val1 == TT_C_ARRAY || val1 == TT_U_ARRAY) { /* Beware: indices in reverse order */ ptr += 2 * (ARRAY(ptr)->dim - dim); bse = ARRAY(ptr)->index1_base; off = ARRAY(ptr)->index1_offset; ptr = ADDR(bse, off); if ((TYPE(ptr) == TT_I_RANGE) ||(TYPE(ptr) == TT_E_RANGE) ||(TYPE(ptr) == TT_ENUM)) { if (attribute == ATTR_O_LAST) PUSH(I_RANGE(ptr)->ihigh); else PUSH(I_RANGE(ptr)->ilow); } #ifdef LONG_INT else if (TYPE(ptr) == TT_L_RANGE) { if (attribute == ATTR_O_LAST) PUSHL(L_RANGE(ptr)->lhigh); else PUSHL(L_RANGE(ptr)->llow); } #endif } else if (val1 == TT_D_ARRAY) { bas1 = D_TYPE(ptr)->dbase; off1 = D_TYPE(ptr)->doff; ptr += WORDS_D_TYPE + 4 *(dim - 1); if (attribute == ATTR_O_LAST) ptr += 2; if (*ptr == 0) PUSH(*(ptr + 1)); else raise(SYSTEM_ERROR, "Attribute on discriminant bound"); } break; case ATTR_T_LENGTH: POP_ADDR(bse, off); ptr = ADDR(bse, off); size = SIZE(ptr); if (size == 1) { if (I_RANGE(ptr)->ihigh < I_RANGE(ptr)->ilow) value = 0; else value = I_RANGE(ptr)->ihigh - I_RANGE(ptr)->ilow + 1; PUSH(value); } #ifdef LONG_INT else /* size=2 */ { if (L_RANGE(ptr)->lhigh < L_RANGE(ptr)->llow) lvalue = 0; else lvalue = L_RANGE(ptr)->lhigh - L_RANGE(ptr)->llow; PUSHL(lvalue); } #endif break; case ATTR_O_LENGTH: POP_ADDR(bse, off);/* type */ ptr = ADDR(bse, off); POP_ADDR(bas1, off1);/* to get rid of array */ val1 = TYPE(ptr); /* type of type */ if (val1 == TT_S_ARRAY) { /* the calculation of max is unuseful ! the substraction may * produce an overflow and a positive result */ if (S_ARRAY(ptr)->sahigh < S_ARRAY(ptr)->salow) value = 0; else { /*value=MAX(S_ARRAY(ptr)->sahigh-S_ARRAY(ptr)->salow + 1, 0);*/ value = S_ARRAY(ptr)->sahigh - S_ARRAY(ptr)->salow + 1; } PUSH(value); } else if (val1 == TT_C_ARRAY) { /* Beware: indices in reverse order */ ptr += 2 * (ARRAY(ptr)->dim - dim); bse = ARRAY(ptr)->index1_base; off = ARRAY(ptr)->index1_offset; ptr = ADDR(bse, off); /* value = MAX(I_RANGE(ptr)->ihigh - I_RANGE(ptr)->ilow + 1, 0); */ if (I_RANGE(ptr)->ihigh < I_RANGE(ptr)->ilow) value = 0; else value = I_RANGE(ptr)->ihigh - I_RANGE(ptr)->ilow + 1; PUSH(value); } break; case ATTR_T_RANGE: POP_ADDR(bse, off); ptr = ADDR(bse, off); size = SIZE(ptr); if (size == 1) { PUSH(I_RANGE(ptr)->ilow); PUSH(I_RANGE(ptr)->ihigh); } #ifdef LONG_INT else /* size == 2 */ { lvalue = L_RANGE(ptr)->lhigh - L_RANGE(ptr)->llow; PUSHL(lvalue); } #endif break; case ATTR_O_RANGE: POP_ADDR(bse, off);/* type */ ptr = ADDR(bse, off); POP_ADDR(bas1, off1);/* to get rid of array */ val1 = TYPE(ptr); /* type of type */ if (val1 == TT_S_ARRAY) { val_high = S_ARRAY(ptr)->sahigh; val_low = S_ARRAY(ptr)->salow; PUSH(val_low); PUSH(val_high); } else if (val1 == TT_C_ARRAY) { /* Beware: indices in reverse order */ ptr += 2 * (ARRAY(ptr)->dim - dim); bse = ARRAY(ptr)->index1_base; off = ARRAY(ptr)->index1_offset; ptr = ADDR(bse, off); size = SIZE(ptr); if (size == 1) { PUSH(I_RANGE(ptr)->ilow); PUSH(I_RANGE(ptr)->ihigh); } #ifdef LONG_INT else /*(size == 2)*/ { PUSHL(L_RANGE(ptr)->llow); PUSHL(L_RANGE(ptr)->lhigh); } #endif } break; case ATTR_IMAGE: image_attribute(); break; case ATTR_VALUE: value_attribute(); break; case ATTR_PRED: POP_ADDR(bse, off);/* type */ ptr = ADDR(bse, off); if ((TYPE(ptr) == TT_I_RANGE) ||(TYPE(ptr) == TT_E_RANGE) ||(TYPE(ptr) == TT_ENUM)) { POP(value); if (value <= I_RANGE(ptr)->ilow) raise(CONSTRAINT_ERROR, "Out of range (PRED)"); value--; PUSH(value); } #ifdef LONG_INT else if (TYPE(ptr) == TT_L_RANGE) { POPL(lvalue); if (lvalue <= L_RANGE(ptr)->llow) raise (CONSTRAINT_ERROR, "Out of range (PRED)"); lvalue--; PUSHL(lvalue); } #endif else /* error */ raise(SYSTEM_ERROR,"Unknown type for attribute PRED"); break; case ATTR_SUCC: POP_ADDR(bse, off);/* type */ ptr = ADDR(bse, off); if ((TYPE(ptr) == TT_I_RANGE) ||(TYPE(ptr) == TT_E_RANGE) ||(TYPE(ptr) == TT_ENUM)) { POP(value); if (value >= I_RANGE(ptr)->ihigh) raise(CONSTRAINT_ERROR, "Out of range (SUCC)"); value++; PUSH(value); } #ifdef LONG_INT else if (TYPE(ptr) == TT_L_RANGE) { POPL(lvalue); if (lvalue >= L_RANGE(ptr)->lhigh) raise (CONSTRAINT_ERROR, "Out of range (SUCC)"); lvalue++; PUSHL(lvalue); } #endif else /* error */ raise(SYSTEM_ERROR,"Unknown type for attribute SUCC"); break; case ATTR_SIZE: POP_ADDR(bse, off); ptr1 = ADDR(bse, off); value = SIZE(ptr1); if ((TYPE(ptr1) == TT_RECORD || TYPE(ptr1) == TT_C_RECORD || TYPE(ptr1) == TT_U_RECORD || TYPE(ptr1) == TT_V_RECORD) && (U_RECORD(ptr1)->repr_size != 0)) { PUSH(U_RECORD(ptr1)->repr_size); } else if (TYPE(ptr1) == TT_ACCESS) { PUSH(32); } else { PUSH(value * BITS_SU); } break; case ATTR_STORAGE_SIZE: POP_ADDR(bse, off); ptr1 = ADDR(bse, off); if (TYPE(ptr1) == TT_ACCESS) { value = ACCESS(ptr1)->collection_size; } else { value = TASK(ptr1)->collection_size; } PUSH(value); break; case ATTR_TERMINATED: POP(value); /* task object */ value = (is_terminated(value)); PUSH(value); break; case ATTR_MANTISSA: case ATTR_LARGE: POP_ADDR(bse, off);/* type */ ptr = ADDR(bse, off); if (TYPE(ptr) == TT_FX_RANGE) { long power ; fval1 = FX_RANGE(ptr)->fxlow; fval2 = FX_RANGE(ptr)->fxhigh; fval1 = MAX(fval1, fval2); value = 1; POP(ratio); /* ratio between subtype's and base type's SMALL */ power = 1; /* Compute value s.t. 2 ** value - 1 includes the upper bound -1. * Given that the small of the subtype may be larger than that of * the type, the 'last of the subtype may be -ratio- away from the * given bound. */ while (power * ratio < fval1 - ratio) { power = power + power + 1; value++; } if (attribute == ATTR_MANTISSA) PUSH(value); else { /* attribute = A_LARGE */ lvalue = power * ratio ; PUSHL(lvalue) ; } } else { /* floating point */ /* TBSL */ } break; case ATTR_FORE: POP_ADDR(bse, off);/* type */ ptr = ADDR(bse, off); POP(d); POP(n); fval1 = FX_RANGE(ptr)->fxhigh; fval2 = FX_RANGE(ptr)->fxlow; fval1 = ABS(fval1); fval2 = ABS(fval2); n *= MAX(fval1, fval2); value = 2; while (n / d >= 10) { d *= 10; value++; } PUSH(value); break; case ATTR_WIDTH: POP_ADDR(bse, off);/* type */ ptr = ADDR(bse, off); val1 = TYPE(ptr); /* type of type */ val_low = I_RANGE(ptr)->ilow; val_high = I_RANGE(ptr)->ihigh; if (val1 == TT_I_RANGE) { if (val_low > val_high) value = 0; else { val1 = ABS(val_low); val2 = ABS(val_high); i = MAX(val1, val2); value = 2; while (i > 10) { value += 1; i = i / 10; } } } else { if (val1 == TT_E_RANGE) { bse = E_RANGE(ptr)->ebase;/* Literals are */ off = E_RANGE(ptr)->eoff;/* in base type */ ptr = ADDR(bse, off); } ptr += WORDS_E_RANGE;/* skip litrals not in subtype */ for (i = 0; i <= val_low - 1; i++) ptr += *ptr + 1; value = 0; for (i = val_low; i <= val_high; i++) { if (*ptr > value) value = *ptr; ptr += *ptr + 1; } } PUSH(value); break; default: raise(SYSTEM_ERROR, "Unknown attribute"); } } void convert(int bse, int off) /*;convert*/ { int *ptr_from, *ptr_to, *ptr4, exp2, exp5; int res_sign, exponent; long mul_fact, div_fact; int from_is_empty,to_is_empty; ptr_to = ADDR(bse, off); POP_ADDR(bas1, off1); ptr_from = ADDR(bas1, off1); /* Deal with combinations of from/to (other combinations handled by * codegen) */ if (TYPE(ptr_to) == TT_I_RANGE) { if (TYPE(ptr_from) == TT_FL_RANGE) { POPF(rvalue); if (ABS(rvalue) >(float)(MAX_LONG)) raise(NUMERIC_ERROR, "Integer out of bounds"); else { value = (rvalue + (rvalue > 0.0? 0.5 : -0.5)); PUSH(value); } } /* If fixed range, is always integer_fixed ($FIXED) */ else if (TYPE(ptr_from) == TT_FX_RANGE) { POPL(lvalue); value = lvalue; PUSH(value); if ((long) value != lvalue) /* if overflow */ raise(NUMERIC_ERROR, "fixed_point conversion"); } /* Note: nothing to do if *ptr_from == TT_I_RANGE */ } else if (TYPE(ptr_to) == TT_FL_RANGE) { if (TYPE(ptr_from) == TT_I_RANGE) { POP(value); rvalue = value; PUSHF(rvalue); } else if (TYPE(ptr_from) == TT_FX_RANGE) { POPL(lvalue); ptr = ptr_from; exp2 = FX_RANGE(ptr)->small_exp_2; exp5 = FX_RANGE(ptr)->small_exp_5; if (lvalue == 0) PUSHF(0.0); else { res_sign = SIGN(lvalue);/* sign of result */ mul_fact = ABS(lvalue); div_fact = 1; if (exp5 < 0) { /* take care of powers of 5 */ for (i = exp5; i != 0; i++) div_fact *= 5; } else { for (i = exp5; i != 0; i--) mul_fact *= 5; } /* compute the division as if there were no problem */ /* (convert the two factors to floating points before) */ rvalue = FLOAT(mul_fact) / FLOAT(div_fact); /* expn returns the integer exponent of a positive float */ exponent = expn(rvalue) - 21; /* float'mantissa = 21 */ if (exponent < 0) { /* if not enough bits, get larger num */ for (i = exponent; i != 0; i++) mul_fact *= 2; } else { for (i = exponent; i != 0; i--) div_fact *= 2; } exp2 += exponent; /* adjust the exponent */ lvalue = mul_fact / div_fact; /* compute result */ if (lvalue <(1024L * 1024L)) { /* case of < 21 bits */ mul_fact *= 2; exp2--; } else if (lvalue >(1024L * 2048L) - 1) { /* case of > 21 bits */ div_fact *= 2; exp2++; } else { /* 21 bits exactly */ } /* watch out: we introduced a bias in the exponent */ if (exp2 >(84 - 21)) raise(NUMERIC_ERROR, "Floating point value overflow"); else if (exp2 <(-84 - 21)) PUSHF(0.0); /* underflow */ else { rvalue = FLOAT(res_sign *(mul_fact / div_fact)); if (exp2 < 0) { for (i = exp2; i != 0; i++) rvalue /= 2.0; } else { for (i = exp2; i != 0; i--) rvalue *= 2.0; } PUSHF(rvalue); } } } /* Note: nothing to do in TYPE(ptr_from) == TT_FL_RANGE case */ } else if (TYPE(ptr_to) == TT_FX_RANGE) { if (TYPE(ptr_from) == TT_I_RANGE) { POP(value); /* target type is integer_fixed */ lvalue = (long) value; PUSHL(lvalue); } else if (TYPE(ptr_from) == TT_FL_RANGE) { POPF(rvalue); if (rvalue == 0.0) PUSHL(0); else { res_sign = SIGN(rvalue); rvalue = ABS(rvalue); exp2 = expn(rvalue) - 21; if (exp2 < 0) { for (i = exp2; i != 0; i++) rvalue *= 2.0; } else { for (i = exp2; i != 0; i--) rvalue /= 2.0; } mul_fact = rvalue; /* exactly 21 bits */ div_fact = 1; exp2 = FX_RANGE(ptr_to)->small_exp_2 - exp2; exp5 = FX_RANGE(ptr_to)->small_exp_5; if (exp5 < 0) { /* at most 42 bits */ for (i = exp5; i != 0; i++) mul_fact *= 5; } else { for (i = exp5; i != 0; i--) div_fact *= 5; } if (exp2 < 0) { for (i = exp2; i != 0; i++) mul_fact *= 2; } /* delay div by powers of two to avoid overflows om div_fact */ lvalue = mul_fact / div_fact; if (exp2 > 0) { for (i = exp2; i != 0; i--) lvalue /= 2; } lvalue *= res_sign; if (lvalue < MIN_LONG || lvalue > MAX_LONG) { raise (NUMERIC_ERROR, "Fixed point overflow"); lvalue = 0; } } PUSHL(lvalue); } else if (TYPE(ptr_from) == TT_FX_RANGE) { POPL(lvalue); res_sign = SIGN(lvalue); lvalue = ABS(lvalue); int_tom(fix_val1,lvalue); fix_convert(fix_val1, FX_RANGE(ptr_from), FX_RANGE(ptr_to)); lvalue = int_tol(fix_val1); if(arith_overflow) raise(NUMERIC_ERROR,"Fixed point conversion overflow"); PUSHL(res_sign*lvalue); } else raise(SYSTEM_ERROR,"Conversion from an unknown type"); } else if (TYPE(ptr_to) == TT_U_ARRAY || TYPE(ptr_to) == TT_C_ARRAY) { if (TYPE(ptr_from) == TT_U_ARRAY || TYPE(ptr_from) == TT_C_ARRAY) { nb_dim = ARRAY(ptr_to)->dim; ptr3 = &(ARRAY(ptr_from)->index1_base); ptr4 = &(ARRAY(ptr_to)->index1_base); from_is_empty = FALSE; to_is_empty = FALSE; for (i = 1; i <= nb_dim; i++) { bas1 = *ptr3++; off1 = *ptr3++; ptr1 = ADDR(bas1, off1); bas2 = *ptr4++; off2 = *ptr4++; ptr2 = ADDR(bas2, off2); if (I_RANGE(ptr1)->ilow > I_RANGE(ptr1)->ihigh) from_is_empty = TRUE; if (I_RANGE(ptr2)->ilow > I_RANGE(ptr2)->ihigh) to_is_empty = TRUE; } if (from_is_empty && to_is_empty) { /* both are empty arrays: do not convert */ PUSH_ADDR(bse,off); return; } if (from_is_empty || to_is_empty) { /* one is empty, the other is not */ raise(CONSTRAINT_ERROR, "Array conversion"); return; } /* both have components: do the conversion */ ptr_from = &(ARRAY(ptr_from)->index1_base); ptr_to = &(ARRAY(ptr_to)->index1_base); for (i = 1; i <= nb_dim; i++) { bas1 = *ptr_from++; off1 = *ptr_from++; ptr1 = ADDR(bas1, off1); bas2 = *ptr_to++; off2 = *ptr_to++; ptr2 = ADDR(bas2, off2); if (I_RANGE(ptr1)->ihigh - I_RANGE(ptr1)->ilow !=I_RANGE(ptr2)->ihigh - I_RANGE(ptr2)->ilow) { raise(CONSTRAINT_ERROR, "Array conversion"); return; } } } else if (TYPE(ptr_from) == TT_S_ARRAY) { bas2 = ARRAY(ptr_to)->index1_base; off2 = ARRAY(ptr_to)->index1_offset; ptr2 = ADDR(bas2, off2); from_is_empty = (S_ARRAY(ptr_from)->salow > S_ARRAY(ptr_from)->sahigh); to_is_empty = (I_RANGE(ptr2)->ilow > I_RANGE(ptr2)->ihigh); if (from_is_empty && to_is_empty) { /* both are empty arrays: do not convert */ PUSH_ADDR(bse,off); return; } if (from_is_empty || to_is_empty) { /* one is empty, the other is not */ raise(CONSTRAINT_ERROR, "Array conversion"); return; } /* both have components: do the conversion */ if (S_ARRAY(ptr_from)->sahigh - S_ARRAY(ptr_from)->salow != I_RANGE(ptr2)->ihigh - I_RANGE(ptr2)->ilow) { raise(CONSTRAINT_ERROR, "Array conversion"); return; } } PUSH_ADDR(bse,off); } else if (TYPE(ptr_to) == TT_S_ARRAY) { if (TYPE(ptr_from) == TT_U_ARRAY || TYPE(ptr_from) == TT_C_ARRAY) { bas1 = ARRAY(ptr_from)->index1_base; off1 = ARRAY(ptr_from)->index1_offset; ptr1 = ADDR(bas1, off1); from_is_empty = (I_RANGE(ptr1)->ilow > I_RANGE(ptr1)->ihigh); to_is_empty = (S_ARRAY(ptr_to)->salow > S_ARRAY(ptr_to)->sahigh); if (from_is_empty && to_is_empty) { /* both are empty arrays: do not convert */ PUSH_ADDR(bse,off); return; } if (from_is_empty || to_is_empty) { /* one is empty, the other is not */ raise(CONSTRAINT_ERROR, "Array conversion"); return; } /* both have components: do the conversion */ if (I_RANGE(ptr1)->ihigh - I_RANGE(ptr1)->ilow != S_ARRAY(ptr_to)->sahigh - S_ARRAY(ptr_to)->salow) { raise(CONSTRAINT_ERROR, "Array conversion"); return; } } else if (TYPE(ptr_from) == TT_S_ARRAY) { from_is_empty = (S_ARRAY(ptr_from)->salow > S_ARRAY(ptr_from)->sahigh); to_is_empty = (S_ARRAY(ptr_to)->salow > S_ARRAY(ptr_to)->sahigh); if (from_is_empty && to_is_empty) { /* both are empty arrays: do not convert */ PUSH_ADDR(bse,off); return; } if (from_is_empty || to_is_empty) { /* one is empty, the other is not */ raise(CONSTRAINT_ERROR, "Array conversion"); return; } /* both have components: do the conversion */ if (S_ARRAY(ptr_from)->sahigh - S_ARRAY(ptr_from)->salow != S_ARRAY(ptr_to)->sahigh - S_ARRAY(ptr_to)->salow) { raise(CONSTRAINT_ERROR, "Array conversion"); return; } } PUSH_ADDR(bse,off); } } /* TYPE_ELABORATE */ void type_elaborate(int flag, int bse, int off) /*;type_elaborate*/ { /* * flag = 0 == type template is to remain global and the original * can be updated on the spot * flag = 1 == a new local type template has to be created * * In the local case, the size of the object to allocate is computed, the * new type is created and initialized with the old one. From then on, * both cases, local and global, can proceed with the same code, given a * ptr in memory to the beginning of the type template. */ int template_size, nb_field, variant_size, component_size, nb_fixed, templ_bse, templ_off, temporary, last_offset, first_case, *case_table_ptr, *field_table_ptr, offset, lbd, ubd, lng; float fval_high,fval_low; long fix_val_high,fix_val_low; /*GET_GAD(bse,off); bse,off retrieved by main_loop */ ptr = ADDR(bse,off); value = TYPE(ptr); /* type of type */ if (flag == 1) { switch (value) { case TT_I_RANGE: template_size = WORDS_I_RANGE; break; case TT_FL_RANGE: template_size = WORDS_FL_RANGE; break; case TT_E_RANGE: template_size = WORDS_E_RANGE; break; case TT_FX_RANGE: template_size = WORDS_FX_RANGE; break; case TT_ACCESS: template_size = WORDS_ACCESS; break; case TT_RECORD: nb_field = RECORD(ptr)->nb_field; template_size = 3 * nb_field + WORDS_RECORD; break; case TT_U_RECORD: case TT_V_RECORD: nb_field = U_RECORD(ptr)->nb_field_u; variant_size = U_RECORD(ptr)->variant; template_size = 3 * nb_field + WORDS_U_RECORD + variant_size; break; case TT_C_RECORD: nb_discr = C_RECORD(ptr)->nb_discr_c; template_size = WORDS_C_RECORD + nb_discr; break; case TT_U_ARRAY: case TT_C_ARRAY: nb_dim = ARRAY(ptr)->dim; template_size = 2 * (nb_dim - 1) + WORDS_ARRAY; break; case TT_D_RECORD: nb_discr = D_TYPE(ptr)->nb_discr_d; template_size = WORDS_D_TYPE + 2 * nb_discr; break; case TT_D_ARRAY: nb_discr = D_TYPE(ptr)->nb_discr_d; template_size = WORDS_D_TYPE + 4 * nb_discr; break; case TT_S_ARRAY: template_size = WORDS_S_ARRAY; break; case TT_TASK: template_size = WORDS_TASK + (TASK(ptr)->nb_families * 2); break; default: ; } ptr1 = ptr; create (template_size, &templ_bse, &templ_off, &ptr); for (i = 0; i < template_size; i++) *ptr++ = *ptr1++; ptr -= template_size; /* restore ptr */ } /* Now ptr designates the template to modify */ switch (value) { case TT_E_RANGE: POP(val_high); E_RANGE(ptr)->ehigh = val_high; POP(val_low); E_RANGE(ptr)->elow = val_low; break; case TT_FL_RANGE: POPF(fval_high); FL_RANGE(ptr)->flhigh = fval_high; POPF(fval_low); FL_RANGE(ptr)->fllow = fval_low; break; case TT_I_RANGE: POP(val_high); I_RANGE(ptr)->ihigh = val_high; POP(val_low); I_RANGE(ptr)->ilow = val_low; break; case TT_FX_RANGE: POPL(fix_val_high); POPL(fix_val_low); FX_RANGE(ptr)->fxlow = fix_val_low; FX_RANGE(ptr)->fxhigh = fix_val_high; break; case TT_ACCESS: ACCESS(ptr)->master_task = tp; ACCESS(ptr)->master_bfp = bfp; break; case TT_S_ARRAY: break; case TT_U_ARRAY: nb_dim = ARRAY(ptr)->dim; update_address(ptr1 = &(ARRAY(ptr)->component_base)); for (i = 0; i < nb_dim; i++) { ptr1 += 2; update_address(ptr1); } break; case TT_C_ARRAY: nb_dim = ARRAY(ptr)->dim; update_address(ptr1 = &(ARRAY(ptr)->component_base)); component_size = SIZE(ADDR(*ptr1, *(ptr1 + 1))); for (i = 0; i < nb_dim; i++) { ptr1 += 2; update_address(ptr1); val_high = I_RANGE(ADDR(*ptr1, *(ptr1 + 1)))->ihigh; val_low = I_RANGE(ADDR(*ptr1, *(ptr1 + 1)))->ilow; if(val_low > val_high) component_size = 0; if (component_size) { temporary = word_sub(val_high,val_low,&overflow); if (overflow) break; temporary = word_add(temporary,1,&overflow); if (overflow) break; temporary = MAX(0,temporary); component_size = word_mul(component_size,temporary,&overflow); if (overflow) break; } } if (overflow) raise(NUMERIC_ERROR,"Type size overflow"); I_RANGE(ptr)->object_size = component_size; break; case TT_D_ARRAY: update_address(&(D_TYPE(ptr)->dbase)); nb_discr = D_TYPE(ptr)->nb_discr_d; ptr2 = ptr + WORDS_D_TYPE + 4 * nb_discr - 1; for (i = 0; i < 2 * nb_discr; i++) { POP(value); *ptr2 = value; ptr2 -= 2; } break; case TT_RECORD: nb_field = RECORD(ptr)->nb_field; last_offset = compute_offset(0,nb_field-1,0,-1, ptr + WORDS_RECORD, 0); SIZE(ptr) = last_offset; break; case TT_U_RECORD: nb_field = U_RECORD(ptr)->nb_field_u; nb_fixed = U_RECORD(ptr)->nb_fixed_u; first_case = U_RECORD(ptr)->first_case; field_table_ptr = ptr + WORDS_U_RECORD; case_table_ptr = field_table_ptr + 3 * nb_field; last_offset = compute_offset( 0, /* first field of fixed part */ nb_fixed-1, /* last field of fixed part */ 0, /* offset of first field */ first_case, field_table_ptr, case_table_ptr); SIZE(ptr) = last_offset; break; case TT_V_RECORD: nb_field = U_RECORD(ptr)->nb_field_u; nb_fixed = U_RECORD(ptr)->nb_fixed_u; first_case = U_RECORD(ptr)->first_case; field_table_ptr = ptr + WORDS_U_RECORD + 1; for (i = 1; i <= nb_field; i++) { update_address(field_table_ptr); field_table_ptr += 3; } break; case TT_C_RECORD: update_address (&(C_RECORD(ptr)->cbase)); ptr2 = ADDR (C_RECORD(ptr)->cbase, C_RECORD(ptr)->coff); /* base type */ nb_discr = C_RECORD(ptr)->nb_discr_c; ptr1 = ptr + WORDS_C_RECORD; for (i = 0; i < nb_discr; i++) { POP(value); *ptr1++ = value; discr_list[i] = value; } if (TYPE(ptr2) == TT_U_RECORD) SIZE(ptr) = SIZE(ptr2); else if (TYPE(ptr2) == TT_V_RECORD) { /* Here compute size of the subtype */ SIZE(ptr) = actual_size (ptr2,discr_list); } break; case TT_D_RECORD: update_address (&(D_TYPE(ptr)->dbase)); nb_discr = D_TYPE(ptr)->nb_discr_d; ptr2 = ptr + WORDS_D_TYPE + 2 * nb_discr - 1; for (i = 1; i <= nb_discr; i++) { POP(value); *ptr2 = value; ptr2 -= 2; } break; case TT_TASK: update_address (&(TASK(ptr)->body_base)); ptr1 = ptr + WORDS_TASK; offset = 0; for (i = 1; i <= TASK(ptr)->nb_families; i++) { bse = *ptr1; off = *(ptr1 + 1); if (bse == 0 && off == 0) { /* Simple entry */ *ptr1++ = offset; *ptr1++ = 1; offset += 1; } else { if (bse == 0) { /* Index subtype is local */ bse = STACK_FRAME(off); off = STACK_FRAME(off+1); } lbd = I_RANGE(ADDR(bse, off))->ilow; ubd = I_RANGE(ADDR(bse, off))->ihigh; lng = ubd - lbd +1; *ptr1++ = offset - lbd; *ptr1++ = lng; offset += lng; } } TASK(ptr)->nb_entries = offset; break; default: raise (SYSTEM_ERROR, "Elaborate unknown type"); } if (flag == 1) PUSH_ADDR(templ_bse,templ_off); } void subprogram(int bse, int off) /*;subprogram*/ { ptr = ADDR(bse, off); if (*ptr < 0) *ptr = -*ptr; /* mark the procedure as elab. */ /* copy relay table */ POP_ADDR(bas1, off1); /* subprogram template */ ptr1 = ADDR(bas1, off1); if ((slot = SUBPROG(ptr1)->relay_slot) != 0) { ptr1 = ADDR(1, *ADDR(1,0)); while (*ptr1 != slot) ptr1 += *(ptr1 + 1) + 2; ptr1 += 2; } else ptr1 += WORDS_SUBPROG; value = SIZE(ptr); /* # of relayed objects */ ptr += 2; for (i = 1; i <= value; i++) { sp = sfp + *ptr1++; *ptr++ = cur_stack[sp]; *ptr++ = cur_stack[sp + 1]; } } int compute_offset(int from_field, int to_field, int field_offset, int next_case, int *field_table_ptr, int * case_table_ptr) /*;compute_offset*/ { int i, *field_ptr, type_base, type_off, *type_ptr, *case_ptr, max_field_offset, nb_choices,last_offset; field_ptr = field_table_ptr + 3 * from_field; for (i = from_field; i <= to_field; i++) { *field_ptr = field_offset; update_address(field_ptr += 1); type_base = *field_ptr; type_off = *++field_ptr; type_ptr = ADDR(type_base, type_off); field_offset += SIZE(type_ptr); field_ptr++; } max_field_offset = field_offset; if (next_case != -1) { case_ptr = case_table_ptr + next_case + 1; nb_choices = *case_ptr; for (i = 1; i <= nb_choices; i++) { from_field = *++case_ptr; to_field = *++case_ptr; next_case = *++case_ptr; last_offset = compute_offset( from_field, to_field, field_offset, next_case, field_table_ptr, case_table_ptr); if (last_offset > max_field_offset) max_field_offset = last_offset; case_ptr++; } } return max_field_offset; } static void update_address(int *addr_ptr) /*;update_address*/ { int type_base, type_off; type_base = *addr_ptr; if (type_base == 0) { /* local address */ type_off = *(addr_ptr + 1); type_base = STACK_FRAME(type_off); type_off = STACK_FRAME(type_off + 1); *addr_ptr = type_base; *(addr_ptr + 1) = type_off; } } void raise(int exception_value, char *reason) /*;raise*/ { if (exception_trace && cs > 2) { printf("raising exception %s in %s", exception_slots[exception_value],code_slots[cs]); if(lin>0) printf(" at line %d",lin); if(*reason != '\0') printf(" (%s)\n",reason); else printf("\n"); } if(*reason != '\0') { raise_cs = cs; raise_lin = lin; raise_reason = reason; } exr = exception_value; terminate_unactivated(); ip = BLOCK_FRAME->bf_handler; BLOCK_FRAME->bf_handler = 0; } static void image_attribute() /*;image_attribute*/ { char s[MAX_IDLEN]; /* chars and length of string */ int slen; /* length of string */ long lv; POP_ADDR(bse, off); /* type */ ptr = ADDR(bse, off); val1 = TYPE(ptr); if (val1 == TT_E_RANGE) { /* take base type */ bse = E_RANGE(ptr)->ebase; off = E_RANGE(ptr)->eoff; ptr = ADDR(bse, off); val1 = TYPE(ptr); } if (val1 == TT_ENUM) { POP(value); ptr += WORDS_E_RANGE; if(*ptr == -1) { /* special case for CHARACTER */ slen = 3; s[0] = s[2] = 39; /* prime character */ s[1] = value; } else { for (i = 1; i <= value; i++) ptr = ptr + *ptr + 1; slen = *ptr++; for (i = 0; i < slen; i++) s[i] = *ptr++; } } else { if (val1 == TT_I_RANGE) { POP(value); lvalue = value; } #ifdef LONG_INT else /* val1 = TT_L_RANGE */ POPL(lvalue); #endif lv = ABS(value); i = MAX_IDLEN-1; if (lv == 0) s[i--] = '0'; while (lv != 0) { s[i--] = (lv % 10) + '0'; lv = lv / 10; } if (lvalue < 0) s[i] = '-'; else s[i] = ' '; slen = 0; while (i < MAX_IDLEN) s[slen++] = s[i++]; } create(slen, &bas1, &off1, &ptr1); for (i = 0; i < slen; i++) *ptr1++ = s[i]; PUSH_ADDR(bas1, off1); create(WORDS_S_ARRAY, &bas2, &off2, &ptr2); S_ARRAY(ptr2)->ttype = TT_S_ARRAY; S_ARRAY(ptr2)->object_size = slen; S_ARRAY(ptr2)->index_size = 1; S_ARRAY(ptr2)->component_size = 1; S_ARRAY(ptr2)->salow = 1; S_ARRAY(ptr2)->sahigh = slen; PUSH_ADDR(bas2, off2); } static void value_attribute() /*;value_attribute*/ { int *s; /* pointer to string chars */ int slen; /* length of string */ int i; /* string index */ POP_ADDR(bse, off); /* type */ ptr = ADDR(bse, off); POP_ADDR(bas1, off1); /* string template */ ptr1 = ADDR(bas1, off1); POP_ADDR(bas2, off2); /* string value */ s = ADDR(bas2, off2); slen = SIZE(ptr1); if (slen) { /* point to end */ s += slen; s--; } while (slen > 0 && *s == ' ') { s--; slen--; /* get rid of the trailing blanks */ } s = ADDR(bas2, off2); while (slen > 0 && *s == ' ') { s++; slen--; /* get rid of the leading blanks */ } i = 0; while (i < slen) /* convert to C string */ work_string[i++] = (char)*s++; work_string[i] = '\0'; if (setjmp(raise_env)) { data_exception = DATA_ERROR; return; } data_exception = CONSTRAINT_ERROR; val1 = TYPE(ptr); if (val1 == TT_ENUM || val1 == TT_E_RANGE) value = enum_ord(ptr, slen, CONSTRAINT_ERROR); else if (val1 == TT_I_RANGE #ifdef LONG_INT || val1==TT_L_RANGE #endif ) { /* second argument is dummy */ lvalue = scan_integer_string(ptr,&i); if ((i+1) != slen) /* If not all scanned */ raise(CONSTRAINT_ERROR, "Number not integer literal for VALUE"); } if (val1 == TT_I_RANGE) { value = (int) lvalue; if (value == lvalue) PUSH(value); else raise(CONSTRAINT_ERROR, "Number out of range for VALUE"); } else PUSH(value); } void create_structure() /*;create_structure*/ { POP_ADDR(bse, off); ptr = ADDR(bse, off); val1 = TYPE(ptr); val2 = SIZE(ptr); switch(val1) { case TT_U_ARRAY: case TT_C_ARRAY: case TT_S_ARRAY: case TT_D_ARRAY: create(val2, &bas1, &off1, &ptr1); PUSH_ADDR(bas1, off1); PUSH_ADDR(bse, off); /* push type template */ break; case TT_RECORD: create(val2, &bas1, &off1, &ptr1); PUSH_ADDR(bas1, off1); break; case TT_U_RECORD: case TT_V_RECORD: create(val2, &bas1, &off1, &ptr1); PUSH_ADDR(bas1, off1); *ptr1 = 0; /* unconstrained */ /* initialize the full record for the shake of comparisons. * note that the value used does not matter but has to be * the same in the code generator. If zero is used, * the constraint bit might be included in that loop. */ for (i = 1; i < val2; i++) *(ptr1 + i) = 0; break; case TT_C_RECORD: create(val2, &bas1, &off1, &ptr1); PUSH_ADDR(bas1, off1); *ptr1 = 1; /* constrained */ nb_discr = C_RECORD(ptr)->nb_discr_c; for (i = 1; i <= nb_discr; i++) *(ptr1 + i) = *(ptr + WORDS_C_RECORD + i); break; case TT_D_RECORD: /* to be checked */ create(val2, &bas1, &off1, &ptr1); PUSH_ADDR(bas1, off1); *ptr1++ = 1; /* constrained */ nb_discr = C_RECORD(ptr)->nb_discr_c; for (i = 1; i <= nb_discr; i++) *ptr1++ = *(ptr++ + WORDS_C_RECORD + i); break; case TT_SUBPROG: if ((slot = SUBPROG(ptr)->relay_slot) != 0) { ptr2 = ADDR(1, *ADDR(1,0)); while (*ptr2 != slot) ptr2 += *(ptr2 + 1) + 2; val2 = *(ptr2 + 1);/* # of relayed objects */ } create(2 * val2 + 2, &bas1, &off1, &ptr1); *ptr1 = -SUBPROG(ptr)->cs;/* Not yet elab. */ *(ptr1 + 1) = val2; PUSH_ADDR(bas1, off1); break; default: raise(SYSTEM_ERROR, "Creating object of unknown type"); } } void create_copy_struc() /*;create_copy_struc*/ { POP_ADDR(bse, off); /* type */ ptr = ADDR(bse, off); POP_ADDR(bas2, off2); /* value */ ptr2 = ADDR(bas2, off2); val1 = TYPE(ptr); val2 = SIZE(ptr); create(val2, &bas1, &off1, &ptr1); PUSH_ADDR(bas1, off1); switch(val1) { case TT_U_ARRAY: case TT_C_ARRAY: case TT_S_ARRAY: case TT_D_ARRAY: if (val2 > 0) { /* copy the object */ for (i = 1; i <= val2; i++) *ptr1++ = *ptr2++; } if (bse >= heap_base) { /* create new type template */ val2 = *(ptr - WORDS_HDR) - WORDS_HDR; /* size of template */ create(val2, &bas3, &off3, &ptr3); for (i = 1; i <= val2; i++) *ptr3++ = *ptr++; } else { bas3 = bse; /* static template, use same */ off3 = off; } PUSH_ADDR(bas3, off3); break; case TT_RECORD: case TT_C_RECORD: case TT_U_RECORD: case TT_D_RECORD: case TT_V_RECORD: for (i = 1; i <= val2; i++) *ptr1++ = *ptr2++; break; } } void compare_struc() /*;compare_struc*/ { POP_ADDR(bse, off); /* type */ ptr3 = ADDR(bse, off); length1 = SIZE(ptr3); POP_ADDR(bse, off); /* first value */ ptr1 = ADDR(bse, off); switch TYPE(ptr3) { /* type of type */ case TT_U_ARRAY: case TT_C_ARRAY: case TT_S_ARRAY: case TT_D_ARRAY: POP_ADDR(bse, off); /* type of the other one */ ptr4 = ADDR(bse, off); length2 = SIZE(ptr4); POP_ADDR(bse, off); /* second value */ if (length1 != length2) { PUSH(FALSE); return; } if (length1 == 0) { PUSH(TRUE); return; } if ((TYPE(ptr3) == TT_U_ARRAY || TYPE(ptr3) == TT_C_ARRAY) && !same_dimensions(ptr3, ptr4)) { PUSH(FALSE); return ; } ptr2 = ADDR(bse, off); break; case TT_RECORD: case TT_U_RECORD: case TT_C_RECORD: case TT_D_RECORD: POP_ADDR(bse, off); /* second value */ ptr2 = ADDR(bse, off); if (TYPE(ptr3) != TT_RECORD) { ptr1 += 1; /* skip constraint bit */ ptr2 += 1; length1 -= 1; } /* else { PUSH (compare_fields_record (ptr1, ptr2, ptr3)); return; } */ break; } while (length1-- > 0) { val1 = *ptr1++; val2 = *ptr2++; if (val1 != val2) { PUSH(FALSE); return; } } PUSH(TRUE); } void compare_arrays() /* compare_arrays */ { int eq_val; int inf_val; POP_ADDR(bse, off); /* type */ ptr3 = ADDR(bse, off); length1 = SIZE(ptr3); POP_ADDR(bse, off); /* first value */ ptr1 = ADDR(bse, off); POP_ADDR(bse, off); /* type of the other one */ ptr4 = ADDR(bse, off); length2 = SIZE(ptr4); POP_ADDR(bse, off); /* second value */ ptr2 = ADDR(bse, off); eq_val = (length1 == length2); inf_val = (length1 < length2); if (length1 <= length2) { if (length2 == 0) { eq_val = 1; inf_val = 0; } else if (length1 == 0) { eq_val = 0; inf_val = 1; } else { while (length1-- > 0) { if ((val1 = *ptr1++) < (val2 = *ptr2++)) { eq_val = 0; inf_val = 1; break; } else if (val1 > val2) { eq_val = 0; inf_val = 0; break; } } } } else { while (length2-- > 0) { if ((val2 = *ptr2++) > (val1 = *ptr1++)) { eq_val = 0; inf_val = 1; break; } else if (val2 < val1) { eq_val = 0; inf_val = 0; break; } else if (length2 == 0) { eq_val = 0; inf_val = 0; } } } PUSH(eq_val+2*inf_val); } void array_slice() /*;array_slice*/ { int low_bound, high_bound, length; POP_ADDR(bse, off); /* type */ ptr = ADDR(bse, off); POP_ADDR(bas1, off1); /* value */ /* extract bounds and size of component */ if (TYPE(ptr) == TT_S_ARRAY) { component_size = S_ARRAY(ptr)->component_size; high_bound = S_ARRAY(ptr)->sahigh; low_bound = S_ARRAY(ptr)->salow; } else if (TYPE(ptr) == TT_C_ARRAY) { bse = ARRAY(ptr)->component_base; off = ARRAY(ptr)->component_offset; component_size = SIZE(ADDR(bse, off)); bse = ARRAY(ptr)->index1_base; off = ARRAY(ptr)->index1_offset; high_bound = I_RANGE(ADDR(bse, off))->ihigh; low_bound = I_RANGE(ADDR(bse, off))->ilow; } POP(val_high); POP(val_low); if (val_high < val_low) /* make null slice if null */ length = 0; else if (val_high > high_bound || val_low < low_bound) { raise(CONSTRAINT_ERROR, "Slice index out of bounds"); return; } else length = val_high - val_low + 1; size = length * component_size; off1 = off1 + (val_low - low_bound) * component_size; PUSH_ADDR(bas1, off1); create(WORDS_S_ARRAY, &bse, &off, &ptr); S_ARRAY(ptr)->ttype = TT_S_ARRAY; S_ARRAY(ptr)->object_size = size; S_ARRAY(ptr)->component_size = component_size; S_ARRAY(ptr)->index_size = 1; S_ARRAY(ptr)->salow = val_low; S_ARRAY(ptr)->sahigh = val_high; PUSH_ADDR(bse, off); } /* ARRAY_CATENATE */ void array_catenate() /*;array_catenate*/ { int catsize, val_low, val_high, rlow, rhigh, index_kind; POP_ADDR(bse, off); /* type of result for qual */ ptr = ADDR(bse, off); /* right argument */ POP_ADDR(bas1, off1); /* type of right arg */ ptr1 = ADDR(bas1, off1); POP_ADDR(bas2, off2); /* right arg */ ptr2 = ADDR(bas2, off2); /* left operand */ POP_ADDR(bas3, off3); /* type */ ptr3 = ADDR(bas3, off3); POP_ADDR(bas4, off4); ptr4 = ADDR(bas4, off4); /* empty arrays */ if ((length2 = SIZE(ptr3)) == 0) { PUSH_ADDR(bas2, off2); PUSH_ADDR(bas1, off1); return; /* result is right operand */ } if ((length1 = SIZE(ptr1)) == 0) { PUSH_ADDR(bas4, off4); PUSH_ADDR(bas3, off3); return; /* result is left operand */ } /* get lower bound of left */ if (*ptr3 == TT_S_ARRAY) { val_low = S_ARRAY(ptr3)->salow; index_kind = S_ARRAY(ptr3)->index_size; component_size = S_ARRAY(ptr3)->component_size; } else if (*ptr3 == TT_C_ARRAY || *ptr3 == TT_U_ARRAY) { component_size = SIZE(ADDR(ARRAY(ptr3)->component_base, ARRAY(ptr3)->component_offset)); val_low = I_RANGE(ADDR(ARRAY(ptr3)->index1_base, ARRAY(ptr3)->index1_offset))->ilow; index_kind = SIZE(ADDR(ARRAY(ptr3)->index1_base, ARRAY(ptr3)->index1_offset)); } catsize = length2 + length1; val_high = val_low +(catsize / component_size) - 1; /* get bounds of result */ if (*ptr == TT_S_ARRAY) { rlow = S_ARRAY(ptr)->salow; rhigh = S_ARRAY(ptr)->sahigh; } else if (*ptr == TT_C_ARRAY || *ptr == TT_U_ARRAY) { rlow = I_RANGE(ADDR(ARRAY(ptr)->index1_base, ARRAY(ptr)->index1_offset))->ilow; rhigh = I_RANGE(ADDR(ARRAY(ptr)->index1_base, ARRAY(ptr)->index1_offset))->ihigh; } /* check bounds */ if (val_low < rlow || val_high > rhigh) { raise(CONSTRAINT_ERROR, "Array catenate"); return; } /* everything ok: do the job */ create(catsize, &bse, &off, &ptr); for (i = 0; i < length2; i++) *ptr++ = *ptr4++; for (i = 0; i < length1; i++) *ptr++ = *ptr2++; PUSH_ADDR(bse, off); create(WORDS_S_ARRAY, &bse, &off, &ptr); S_ARRAY(ptr)->ttype = TT_S_ARRAY; S_ARRAY(ptr)->object_size = catsize; S_ARRAY(ptr)->component_size = component_size; S_ARRAY(ptr)->index_size = index_kind; S_ARRAY(ptr)->salow = val_low; S_ARRAY(ptr)->sahigh = val_high; PUSH_ADDR(bse, off); } void subscript() /*;subscript*/ { POP_ADDR(bas1, off1); /* type */ POP_ADDR(bse, off); /* array */ ptr1 = ADDR(bas1, off1); val1 = TYPE(ptr1); /* type of type */ if (val1 == TT_S_ARRAY) { POP(value); val2 = S_ARRAY(ptr1)->component_size; val_low = S_ARRAY(ptr1)->salow; val_high = S_ARRAY(ptr1)->sahigh; if (value < val_low || value > val_high) raise(CONSTRAINT_ERROR, "Index out of bounds"); result = (value - val_low) * val2; } else if ((val1 == TT_C_ARRAY) ||(val1 == TT_U_ARRAY)) { bas1 = ARRAY(ptr1)->component_base; off1 = ARRAY(ptr1)->component_offset; val1 = SIZE(ADDR(bas1, off1));/* size of component */ val2 = ARRAY(ptr1)->dim; result = 0; delta = 1; ptr1 = &(ARRAY(ptr1)->index1_base); for (i = 1; i <= val2; i++) { POP(value); bas2 = *ptr1++; off2 = *ptr1++; ptr2 = ADDR(bas2, off2); val_low = I_RANGE(ptr2)->ilow; val_high = I_RANGE(ptr2)->ihigh; if (value < val_low || value > val_high) { raise(CONSTRAINT_ERROR, "Index out of bounds"); } value = value - val_low; result = (value * delta) + result; delta = delta *(val_high - val_low + 1); } result = result * val1; } else raise(SYSTEM_ERROR, "Illegal array type"); off += result; PUSH_ADDR(bse, off); } void array_move() /*;array_move*/ { POP_ADDR(bse, off); /* type of the value */ ptr1 = ADDR(bse, off); POP_ADDR(bse, off); /* value */ ptr2 = ADDR(bse, off); POP_ADDR(bse, off); /* type of the object */ ptr3 = ADDR(bse, off); POP_ADDR(bse, off); /* object */ ptr4 = ADDR(bse, off); length1 = SIZE(ptr1); length2 = SIZE(ptr3); /* : The test of the length equalities has to be done at first otherwise * "a := b" will be valid if a is a null array and b a non null one */ if (length1 != length2) raise(CONSTRAINT_ERROR, "Arrays not same length"); else if (length1 == 0) return; /* null array */ else { if (ptr4 < ptr2) { for (i = 0; i <= length2 - 1; i++) /* copy in ascending order */ *(ptr4 + i) = *(ptr2 + i); } else { ptr4 += length2; /* copy in descending order */ ptr2 += length2; for (i = 1; i <= length2; i++) *(ptr4 - i) = *(ptr2 - i); } } } static int same_dimensions(int *temp1, int *temp2) /*;same_dimensions */ { int *p1, *p2, *p3 ; int low1, low2, high1, high2; int d ; /* When comparing multidimensional arrays, must check that they have * the same dimensions (otherwise a 2 by 3 array might check equal to a * 3 by 2 array. See c34005m). */ d = ARRAY(temp1)->dim; if (d == 1) return (TRUE) ; p1 = &(ARRAY(temp1)->index1_base); p2 = &(ARRAY(temp2)->index1_base); for (i = 1; i <= d; i++) { bas1 = *p1++; off1 = *p1++; p3 = ADDR(bas1, off1); /* template of 1st index type */ low1 = I_RANGE(p3)->ilow; high1 = I_RANGE(p3)->ihigh; bas2 = *p2++; off2 = *p2++; p3 = ADDR(bas2, off2); /* template of 2nd index type */ low2 = I_RANGE(p3)->ilow; high2 = I_RANGE(p3)->ihigh; if (high1 - low1 != high2 - low2) return (FALSE) ; } return TRUE ; } static int compare_fields_record (int *v_ptr1, int *v_ptr2, int *itemplate) /*;compare_fields_record*/ { /* this procedure allows the comparison of record. * The comparison is not straightfoward if one in unconstrained * and the other is constrained or if there are variant parts. * This procedure was not intended to be completed. It was just a * test to solve one acv test of c3. * This procedure is not called from the Ada machine because it * slows down the comparison. * Nevertheless, this case has to be taken into account for future * work */ int length1, *ptr1, *ptr2 ; int i, nb_field, type_base, type_off, *type_ptr, *field_ptr; int field_offset; ptr1 = v_ptr1; ptr2 = v_ptr2; switch TYPE (itemplate) { case TT_RECORD: nb_field = RECORD(itemplate)->nb_field; field_ptr = itemplate + WORDS_RECORD; for (i = 1; i <= nb_field; i++) { field_offset = *field_ptr; field_ptr = field_ptr + 1; type_base = *field_ptr; type_off = *++field_ptr; type_ptr = ADDR(type_base, type_off); if (!compare_fields_record (v_ptr1 + field_offset, v_ptr2 + field_offset, type_ptr)) { return FALSE; } field_ptr++; } return TRUE; case TT_U_RECORD: case TT_C_RECORD: case TT_D_RECORD: length1 = SIZE (itemplate); ptr1 += 1; /* skip constraint bit */ ptr2 += 1; length1 -= 1; break; default: length1 = SIZE (itemplate); break; } while (length1-- > 0) { val1 = *ptr1++; val2 = *ptr2++; if (val1 != val2) return FALSE; } return TRUE; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.