/* Primitives Package */ #include "copyright.h" #include <sys/types.h> #include <stdio.h> #include <time.h> #include <ctype.h> #include <stdlib.h> #include "config.h" #include "db.h" #include "tune.h" #include "inst.h" #include "externs.h" #include "match.h" #include "interface.h" #include "params.h" #include "fbstrings.h" #include "interp.h" static struct inst *oper1, *oper2, *oper3, *oper4; static int result; static char buf[BUFFER_LEN]; union error_mask { struct { unsigned int div_zero:1; /* Divide by zero */ unsigned int nan:1; /* Result would not be a number */ unsigned int imaginary:1; /* Result would be imaginary */ unsigned int f_bounds:1; /* Float boundary error */ unsigned int i_bounds:1; /* Integer boundary error */ } error_flags; int is_flags; }; #define ERROR_NAME_MAX_LEN 15 #define ERROR_STRING_MAX_LEN 80 #define ERROR_NUM 5 union error_mask err_bits[ERROR_NUM]; struct err_type { int error_bit; char error_name[ERROR_NAME_MAX_LEN]; char error_string[ERROR_STRING_MAX_LEN]; }; static struct err_type err_defs[] = { {0, "DIV_ZERO", "Division by zero attempted."}, {1, "NAN", "Result was not a number."}, {2, "IMAGINARY", "Result was imaginary."}, {3, "FBOUNDS", "Floating-point inputs were infinite or out of range."}, {4, "IBOUNDS", "Calculation resulted in an integer overflow."}, {5, "", ""} }; static int err_init = 0; void init_err_val(void) { int i; for (i = 0; i < ERROR_NUM; i++) err_bits[i].is_flags = 0; err_bits[0].error_flags.div_zero = 1; err_bits[1].error_flags.nan = 1; err_bits[2].error_flags.imaginary = 1; err_bits[3].error_flags.f_bounds = 1; err_bits[4].error_flags.i_bounds = 1; err_init = 1; } void prim_clear(PRIM_PROTOTYPE) { CHECKOP(0); fr->error.is_flags = 0; } void prim_error_num(PRIM_PROTOTYPE) { CHECKOP(0); CHECKOFLOW(1); result = ERROR_NUM; PushInt(result); } void prim_clear_error(PRIM_PROTOTYPE) { int loop; CHECKOP(1); oper1 = POP(); if (oper1->type != PROG_STRING && oper1->type != PROG_INTEGER) abort_interp("Invalid argument type. (1)"); if (!err_init) init_err_val(); if (oper1->type == PROG_INTEGER) { if ((oper1->data.number < 0) || (oper1->data.number >= ERROR_NUM)) { result = 0; } else { fr->error.is_flags = fr->error.is_flags & (~err_bits[oper1->data.number].is_flags); result = 1; } } else { if (!oper1->data.string) { result = 0; } else { loop = 0; result = strlen(oper1->data.string->data); for (loop = 0; loop < result; loop++) buf[loop] = toupper(oper1->data.string->data[loop]); result = 0; loop = 0; while (loop < ERROR_NUM) { if (!strcmp(buf, err_defs[loop].error_name)) { result = 1; loop = ERROR_NUM; fr->error.is_flags = fr->error.is_flags & (~err_bits[loop].is_flags); } else { loop++; } } } } CLEAR(oper1); PushInt(result); } void prim_set_error(PRIM_PROTOTYPE) { int loop; CHECKOP(1); oper1 = POP(); if (oper1->type != PROG_STRING && oper1->type != PROG_INTEGER) abort_interp("Invalid argument type. (1)"); if (!err_init) init_err_val(); if (oper1->type == PROG_INTEGER) { if ((oper1->data.number < 0) || (oper1->data.number >= ERROR_NUM)) { result = 0; } else { fr->error.is_flags = fr->error.is_flags | err_bits[oper1->data.number].is_flags; result = 1; } } else { if (!oper1->data.string) { result = 0; } else { loop = 0; result = strlen(oper1->data.string->data); for (loop = 0; loop < result; loop++) buf[loop] = toupper(oper1->data.string->data[loop]); result = 0; loop = 0; while (loop < ERROR_NUM) { if (!strcmp(buf, err_defs[loop].error_name)) { result = 1; loop = ERROR_NUM; fr->error.is_flags = fr->error.is_flags | err_bits[loop].is_flags; } else { loop++; } } } } CLEAR(oper1); PushInt(result); } void prim_is_set(PRIM_PROTOTYPE) { int loop; CHECKOP(1); oper1 = POP(); if (oper1->type != PROG_STRING && oper1->type != PROG_INTEGER) abort_interp("Invalid argument type. (1)"); if (!err_init) init_err_val(); if (oper1->type == PROG_INTEGER) { if ((oper1->data.number < 0) || (oper1->data.number >= ERROR_NUM)) { result = 0; } else { result = ((fr->error.is_flags & err_bits[oper1->data.number].is_flags) != 0); } } else { if (!oper1->data.string) { result = 0; } else { loop = 0; result = strlen(oper1->data.string->data); for (loop = 0; loop < result; loop++) buf[loop] = toupper(oper1->data.string->data[loop]); result = 0; loop = 0; while (loop < ERROR_NUM) { if (!strcmp(buf, err_defs[loop].error_name)) { loop = ERROR_NUM; result = ((fr->error.is_flags & err_bits[loop].is_flags) != 0); } else { loop++; } } } } CLEAR(oper1); PushInt(result); } void prim_error_str(PRIM_PROTOTYPE) { int loop; CHECKOP(1); oper1 = POP(); if (oper1->type != PROG_STRING && oper1->type != PROG_INTEGER) abort_interp("Invalid argument type. (1)"); if (!err_init) init_err_val(); if (oper1->type == PROG_INTEGER) { if ((oper1->data.number < 0) || (oper1->data.number >= ERROR_NUM)) { result = -1; } else { result = oper1->data.number; } } else { if (!oper1->data.string) { result = -1; } else { loop = 0; result = strlen(oper1->data.string->data); for (loop = 0; loop < result; loop++) buf[loop] = toupper(oper1->data.string->data[loop]); result = -1; loop = 0; while (loop < ERROR_NUM) { if (!strcmp(buf, err_defs[loop].error_name)) { result = loop; loop = ERROR_NUM; } else { loop++; } } } } CLEAR(oper1); if (result == -1) { PushNullStr; } else { PushString(err_defs[result].error_string); } } void prim_error_name(PRIM_PROTOTYPE) { CHECKOP(1); oper1 = POP(); if (oper1->type != PROG_INTEGER) abort_interp("Invalid argument type. (1)"); if (!err_init) init_err_val(); if ((oper1->data.number < 0) || (oper1->data.number >= ERROR_NUM)) { result = -1; } else { result = oper1->data.number; } CLEAR(oper1); if (result == -1) { PushNullStr; } else { PushString(err_defs[result].error_name); } } void prim_error_bit(PRIM_PROTOTYPE) { int loop; CHECKOP(1); oper1 = POP(); if (oper1->type != PROG_STRING) abort_interp("Invalid argument type. (1)"); if (!err_init) init_err_val(); if (!oper1->data.string) { result = -1; } else { loop = 0; result = strlen(oper1->data.string->data); for (loop = 0; loop < result; loop++) buf[loop] = toupper(oper1->data.string->data[loop]); result = -1; loop = 0; while (loop < ERROR_NUM) { if (!strcmp(buf, err_defs[loop].error_name)) { result = loop; loop = ERROR_NUM; } else { loop++; } } } CLEAR(oper1); PushInt(result); } void prim_is_error(PRIM_PROTOTYPE) { CHECKOP(0); CHECKOFLOW(1); result = ((fr->error.is_flags) != 0); PushInt(result); }