UCS4 *Parser::Convert_UTF8_To_UCS4(const unsigned char *text_array, int text_array_size, int *char_array_size) { UCS4 *char_array = NULL; UCS4 chr; int i, j, k, seqlen; if((text_array == NULL) || (text_array_size == 0) || (char_array_size == NULL)) return NULL; char_array = reinterpret_cast<UCS4 *>(POV_MALLOC(text_array_size * sizeof(UCS4), "Character Array")); if(char_array == NULL) throw POV_EXCEPTION_CODE(kOutOfMemoryErr); for(i = 0, k = 0; i < text_array_size; k++, i++) { seqlen = gUTF8SequenceArray[text_array[i]]; chr = 0; for(j = seqlen; j > 0; j--) { chr += text_array[i]; chr <<= 6; i++; } chr += text_array[i]; char_array[k] = chr - gUTF8Offsets[seqlen]; } char_array = reinterpret_cast<UCS4 *>(POV_REALLOC(char_array, k * sizeof(UCS4), "Character Array")); *char_array_size = k; return char_array; }
FUNCTION POVFPU_AddConstant(DBL v) { unsigned int i; if(POVFPU_Consts == NULL) { POVFPU_Consts = (DBL *)POV_MALLOC(sizeof(DBL), "fn: constant floats"); POVFPU_Consts[0] = v; POVFPU_ConstCnt = 1; return 0; } for(i = 0; i < POVFPU_ConstCnt; i++) { if(POVFPU_Consts[i] == v) return (unsigned int)i; } if(POVFPU_ConstCnt == MAX_K) Error("More than %d constants in all functions are not supported.", (int)MAX_K); POVFPU_ConstCnt++; POVFPU_Consts = (DBL *)POV_REALLOC(POVFPU_Consts, sizeof(DBL) * POVFPU_ConstCnt, "fn: constant floats"); POVFPU_Consts[POVFPU_ConstCnt - 1] = v; return POVFPU_ConstCnt - 1; }
// Create a bounding box hierarchy from a given list of finite and // infinite elements. Each element consists of // // - an infinite flag // - a bounding box enclosing the element // - a pointer to the structure representing the element (e.g an object) void Build_BBox_Tree(BBOX_TREE **Root, size_t numOfFiniteObjects, BBOX_TREE **&Finite, size_t numOfInfiniteObjects, BBOX_TREE **Infinite, size_t& maxfinitecount) { ptrdiff_t low, high; BBOX_TREE *cd, *root; // This is a resonable guess at the number of finites needed. // This array will be reallocated as needed if it isn't. maxfinitecount = 2 * numOfFiniteObjects; // Now do a sort on the objects, with the end result being // a tree of objects sorted along the x, y, and z axes. if(numOfFiniteObjects > 0) { low = 0; high = numOfFiniteObjects; while(sort_and_split(Root, Finite, &numOfFiniteObjects, low, high, maxfinitecount) == 0) { low = high; high = numOfFiniteObjects; } // Move infinite objects in the first leaf of Root. if(numOfInfiniteObjects > 0) { root = *Root; root->Node = reinterpret_cast<BBOX_TREE **>(POV_REALLOC(root->Node, (root->Entries + 1) * sizeof(BBOX_TREE *), "composite")); POV_MEMMOVE(&(root->Node[1]), &(root->Node[0]), root->Entries * sizeof(BBOX_TREE *)); root->Entries++; cd = create_bbox_node(numOfInfiniteObjects); for(size_t i = 0; i < numOfInfiniteObjects; i++) cd->Node[i] = Infinite[i]; calc_bbox(&(cd->BBox), Infinite, 0, numOfInfiniteObjects); root->Node[0] = cd; calc_bbox(&(root->BBox), root->Node, 0, root->Entries); // Root and first node are infinite. root->Infinite = true; root->Node[0]->Infinite = true; } } else { // There are no finite objects and no Root was created. // Create it now and put all infinite objects into it. if(numOfInfiniteObjects > 0) { cd = create_bbox_node(numOfInfiniteObjects); for(size_t i = 0; i < numOfInfiniteObjects; i++) cd->Node[i] = Infinite[i]; calc_bbox(&(cd->BBox), Infinite, 0, numOfInfiniteObjects); *Root = cd; (*Root)->Infinite = true; } } }
UCS2 *Parser::UCS2_strcat(UCS2 *s1, const UCS2 *s2) { int l1, l2; l1 = UCS2_strlen(s1); l2 = UCS2_strlen(s2); s1 = reinterpret_cast<UCS2 *>(POV_REALLOC(s1, sizeof(UCS2) * (l1 + l2 + 1), "UCS2 String")); UCS2_strcpy(&s1[l1], s2); return s1; }
static void priority_queue_insert(PRIORITY_QUEUE *Queue, DBL Depth, BBOX_TREE *Node) { unsigned size; int i; QELEM tmp; QELEM *List; #ifdef BBOX_EXTRA_STATS Increase_Counter(stats[totalQueues]); #endif Queue->QSize++; size = Queue->QSize; /* Reallocate priority queue if it's too small. */ if (size >= Queue->Max_QSize) { if (size >= INT_MAX/2) { Error("Priority queue overflow."); } #ifdef BBOX_EXTRA_STATS Increase_Counter(stats[totalQueueResizes]); #endif Queue->Max_QSize *= 2; Queue->Queue = (QELEM *)POV_REALLOC(Queue->Queue, Queue->Max_QSize*sizeof(QELEM), "priority queue"); } List = Queue->Queue; List[size].Depth = Depth; List[size].Node = Node; i = size; while (i > 1 && List[i].Depth < List[i / 2].Depth) { tmp = List[i]; List[i] = List[i / 2]; List[i / 2] = tmp; i = i / 2; } }
void POVFPU_SetGlobal(unsigned int k, DBL v) { if(POVFPU_Globals == NULL) { POVFPU_GlobalCnt = k + 1; POVFPU_Globals = (DBL *)POV_MALLOC(sizeof(DBL) * POVFPU_GlobalCnt, "fn: globals"); } else if(POVFPU_GlobalCnt < k + 1) { POVFPU_GlobalCnt = k + 1; POVFPU_Globals = (DBL *)POV_REALLOC(POVFPU_Globals, sizeof(DBL) * POVFPU_GlobalCnt, "fn: globals"); } POVFPU_Globals[k] = v; }
void Reinitialize_VLBuffer_Code() { if (Node_Queue->QSize >= Node_Queue->Max_QSize) { if (Node_Queue->QSize >= INT_MAX/2) { Error("Node queue overflow."); } Node_Queue->Max_QSize *= 2; Node_Queue->Queue = (PROJECT_TREE_NODE **)POV_REALLOC(Node_Queue->Queue, Node_Queue->Max_QSize*sizeof(PROJECT_TREE_NODE *), "vista/light buffer node queue"); } }
void POVFPU_SetLocal(unsigned int k, DBL v) { if(k >= POVFPU_Current_Context->maxdblstacksize) { #if (SYS_FUNCTIONS == 1) unsigned long diff = ((unsigned long)(POVFPU_Current_Context->dblstack)) - ((unsigned long)(POVFPU_Current_Context->dblstackbase)); #endif POVFPU_Current_Context->maxdblstacksize = max(k + 1, (unsigned int)256); POVFPU_Current_Context->dblstackbase = (DBL *)POV_REALLOC(POVFPU_Current_Context->dblstackbase, sizeof(DBL) * POVFPU_Current_Context->maxdblstacksize, "fn: stack"); #if (SYS_FUNCTIONS == 1) POVFPU_Current_Context->dblstack = (DBL *)(((unsigned long)(POVFPU_Current_Context->dblstackbase)) + diff); #endif } POVFPU_Current_Context->dblstackbase[k] = v; }
void POVFPU_RemoveFunction(FUNCTION fn) { if((POVFPU_Functions == NULL) || (fn >= POVFPU_FunctionCnt)) return; if(POVFPU_Functions[fn].reference_count > 0) // necessary to prevent any recursion { POVFPU_Functions[fn].reference_count--; if(POVFPU_Functions[fn].reference_count == 0) { // The copying is necessary because recursive POVFPU_RemoveFunction // calls may shrink the POVFPU_Functions array and remove the data // before we are done with it here! [trf] FunctionEntry f = POVFPU_Functions[fn]; unsigned int i = 0; SYS_DELETE_FUNCTION(&f); for(i = 0; i < f.fn.program_size; i++) { if(GET_OP(f.fn.program[i]) == OPCODE_CALL) POVFPU_RemoveFunction(GET_K(f.fn.program[i])); } FNCode_Delete(&(f.fn)); for(i = POVFPU_FunctionCnt - 1; i > 0; i--) { if(POVFPU_Functions[i].reference_count == 0) POVFPU_FunctionCnt--; else break; } if(POVFPU_FunctionCnt == 0) { POV_FREE(POVFPU_Functions); POVFPU_Functions = NULL; } else POVFPU_Functions = (FunctionEntry *)POV_REALLOC(POVFPU_Functions, sizeof(FunctionEntry) * POVFPU_FunctionCnt, "fn: FunctionEntry"); } } }
FUNCTION POVFPU_AddFunction(FunctionCode *f) { FUNCTION fn = 0; if(POVFPU_Functions == NULL) { POVFPU_Functions = (FunctionEntry *)POV_MALLOC(sizeof(FunctionEntry), "fn: FunctionEntry"); POVFPU_Functions[0].fn = *f; POVFPU_Functions[0].reference_count = 1; SYS_ADD_FUNCTION(fn); POVFPU_FunctionCnt = 1; return 0; } if(POVFPU_FunctionCnt == MAX_FN) { for(fn = 0; fn < MAX_FN; fn++) { if(POVFPU_Functions[fn].reference_count == 0) break; } if(fn == MAX_K) Error("Maximum number (%d) of functions per scene reached.", MAX_FN); } else { fn = POVFPU_FunctionCnt; POVFPU_FunctionCnt++; } POVFPU_Functions = (FunctionEntry *)POV_REALLOC(POVFPU_Functions, sizeof(FunctionEntry) * POVFPU_FunctionCnt, "fn: FunctionEntry"); POVFPU_Functions[fn].fn = *f; POVFPU_Functions[fn].reference_count = 1; SYS_ADD_FUNCTION(fn); return fn; }
void Insert_Spline_Entry(SPLINE * sp, DBL p, EXPRESS v) { int i, k; /* Reset the Coeffs_Computed flag. Inserting a new point invalidates * pre-computed coefficients */ sp->Coeffs_Computed = false; sp->Cache_Valid = false; /* If all space is used, reallocate */ if(sp->Number_Of_Entries >= sp->Max_Entries) { sp->Max_Entries += INIT_SPLINE_SIZE; sp->SplineEntries = (SPLINE_ENTRY *)POV_REALLOC(sp->SplineEntries, sp->Max_Entries * sizeof(SPLINE_ENTRY), "Temporary Spline Entries"); for (i = sp->Number_Of_Entries; i < sp->Max_Entries; i++) { sp->SplineEntries[i].par=-1e6; } } i = findt(sp, p); /* If p is already in spline, replace */ /* The clause after the || is needed because findt returns sp->Number_Of_Entries * if p is greater than OR EQUAL TO the highest par in the spline */ if(sp->Number_Of_Entries != 0 && ((sp->SplineEntries[i].par == p) || (i == sp->Number_Of_Entries && sp->SplineEntries[i-1].par == p))) { for(k=0; k<5; k++) sp->SplineEntries[i].vec[k] = v[k]; } else { mkfree(sp, i); sp->SplineEntries[i].par = p; for(k=0; k<5; k++) sp->SplineEntries[i].vec[k] = v[k]; sp->Number_Of_Entries += 1; } }
static int sort_and_split(BSPHERE_TREE **Root, BSPHERE_TREE ***Elements, int *nElem, int first, int last, int& maxelements) { int size, i, best_loc; DBL *area_left, *area_right; DBL best_index, new_index; BSPHERE_TREE *cd; int Axis = find_axis(*Elements, first, last); size = last - first; if (size <= 0) { return (1); } /* * Actually, we could do this faster in several ways. We could use a * logn algorithm to find the median along the given axis, and then a * linear algorithm to partition along the axis. Oh well. */ switch(Axis) { case X: QSORT((void *)(*Elements + first), size, sizeof(BSPHERE_TREE *), comp_elements<X>); break; case Y: QSORT((void *)(*Elements + first), size, sizeof(BSPHERE_TREE *), comp_elements<Y>); break; case Z: QSORT((void *)(*Elements + first), size, sizeof(BSPHERE_TREE *), comp_elements<Z>); break; } /* * area_left[] and area_right[] hold the surface areas of the bounding * boxes to the left and right of any given point. E.g. area_left[i] holds * the surface area of the bounding box containing Elements 0 through i and * area_right[i] holds the surface area of the box containing Elements * i through size-1. */ area_left = (DBL *)POV_MALLOC(size * sizeof(DBL), "blob bounding hierarchy"); area_right = (DBL *)POV_MALLOC(size * sizeof(DBL), "blob bounding hierarchy"); /* Precalculate the areas for speed. */ build_area_table(*Elements, first, last - 1, area_left); build_area_table(*Elements, last - 1, first, area_right); best_index = area_right[0] * (size - 3.0); best_loc = - 1; /* * Find the most effective point to split. The best location will be * the one that minimizes the function N1*A1 + N2*A2 where N1 and N2 * are the number of objects in the two groups and A1 and A2 are the * surface areas of the bounding boxes of the two groups. */ for (i = 0; i < size - 1; i++) { new_index = (i + 1) * area_left[i] + (size - 1 - i) * area_right[i + 1]; if (new_index < best_index) { best_index = new_index; best_loc = i + first; } } POV_FREE(area_left); POV_FREE(area_right); /* * Stop splitting if the BRANCHING_FACTOR is reached or * if splitting stops being effective. */ if ((size <= BRANCHING_FACTOR) || (best_loc < 0)) { cd = (BSPHERE_TREE *)POV_MALLOC(sizeof(BSPHERE_TREE), "blob bounding hierarchy"); cd->Entries = (short)size; cd->Node = (BSPHERE_TREE **)POV_MALLOC(size*sizeof(BSPHERE_TREE *), "blob bounding hierarchy"); for (i = 0; i < size; i++) { cd->Node[i] = (*Elements)[first+i]; } recompute_bound(cd); *Root = cd; if (*nElem >= maxelements) { /* Prim array overrun, increase array by 50%. */ maxelements = 1.5 * maxelements; /* For debugging only. */ // TODO FIXME Debug_Info("Reallocing elements to %d\n", maxelements); *Elements = (BSPHERE_TREE **)POV_REALLOC(*Elements, maxelements * sizeof(BSPHERE_TREE *), "bounding slabs"); } (*Elements)[*nElem] = cd; (*nElem)++; return (1); } else { sort_and_split(Root, Elements, nElem, first, best_loc + 1, maxelements); sort_and_split(Root, Elements, nElem, best_loc + 1, last, maxelements); return (0); } }
UCS2 *Parser::String_To_UCS2(const char *str, bool pathname) { UCS2 *char_string = NULL; UCS2 *char_array = NULL; int char_array_size = 0; int utf8arraysize = 0; unsigned char *utf8array = NULL; int index_in = 0; int index_out = 0; char buffer[8]; char *dummy_ptr = NULL; int i = 0; if(strlen(str) == 0) { char_string = reinterpret_cast<UCS2 *>(POV_MALLOC(sizeof(UCS2), "UCS2 String")); char_string[0] = 0; return char_string; } switch(sceneData->stringEncoding) { case 0: // ASCII char_array_size = (int)strlen(str); char_array = reinterpret_cast<UCS2 *>(POV_MALLOC(char_array_size * sizeof(UCS2), "Character Array")); for(i = 0; i < char_array_size; i++) { if(sceneData->languageVersion < 350) char_array[i] = (unsigned char)(str[i]); else { char_array[i] = str[i] & 0x007F; if(char_array[i] != str[i]) { char_array[i] = ' '; PossibleError("Non-ASCII character has been replaced by space character."); } } } break; case 1: // UTF8 char_array = Convert_UTF8_To_UCS2(reinterpret_cast<const unsigned char *>(str), (int)strlen(str), &char_array_size); break; case 2: // System Specific char_array = POV_CONVERT_TEXT_TO_UCS2(reinterpret_cast<const unsigned char *>(str), strlen(str), &char_array_size); if(char_array == NULL) Error("Cannot convert system specific text format to Unicode."); break; default: Error("Unsupported text encoding format."); break; } if(char_array == NULL) Error("Cannot convert text to UCS2 format."); char_string = reinterpret_cast<UCS2 *>(POV_MALLOC((char_array_size + 1) * sizeof(UCS2), "UCS2 String")); for(index_in = 0, index_out = 0; index_in < char_array_size; index_in++, index_out++) { if((char_array[index_in] == '\\') && (pathname == false)) { index_in++; switch(char_array[index_in]) { case 'a': char_string[index_out] = 0x07; break; case 'b': char_string[index_out] = 0x08; break; case 'f': char_string[index_out] = 0x0c; break; case 'n': char_string[index_out] = 0x0a; break; case 'r': char_string[index_out] = 0x0d; break; case 't': char_string[index_out] = 0x09; break; case 'v': char_string[index_out] = 0x0b; break; case '\0': char_string[index_out] = 0x5c; break; case '\'': char_string[index_out] = 0x27; break; case '\\': char_string[index_out] = '\\'; break; case 'u': if(index_in + 4 >= char_array_size) Error("Unexpected end of escape sequence in text string."); buffer[0] = char_array[++index_in]; buffer[1] = char_array[++index_in]; buffer[2] = char_array[++index_in]; buffer[3] = char_array[++index_in]; buffer[4] = 0; char_string[index_out] = (UCS2)strtoul(buffer, &dummy_ptr, 16); break; default: char_string[index_out] = char_array[index_in]; if ( char_array ) POV_FREE(char_array); char_array = NULL; Error( "Illegal escape sequence in string." ); break; } } else char_string[index_out] = char_array[index_in]; } char_string[index_out] = 0; index_out++; char_string = reinterpret_cast<UCS2 *>(POV_REALLOC(char_string, index_out * sizeof(UCS2), "UCS2 String")); if(char_array != NULL) POV_FREE(char_array); return char_string; }
static int sort_and_split(BBOX_TREE **Root, BBOX_TREE **&Finite, long *numOfFiniteObjects, long first, long last) { BBOX_TREE *cd; long size, i, best_loc; DBL *area_left, *area_right; DBL best_index, new_index; Axis = find_axis(Finite, first, last); size = last - first; if (size <= 0) { return (1); } Do_Cooperate(1); /* * Actually, we could do this faster in several ways. We could use a * logn algorithm to find the median along the given axis, and then a * linear algorithm to partition along the axis. Oh well. */ QSORT((void *)(&Finite[first]), (unsigned long)size, sizeof(BBOX_TREE *), compboxes); /* * area_left[] and area_right[] hold the surface areas of the bounding * boxes to the left and right of any given point. E.g. area_left[i] holds * the surface area of the bounding box containing Finite 0 through i and * area_right[i] holds the surface area of the box containing Finite * i through size-1. */ area_left = (DBL *)POV_MALLOC(size * sizeof(DBL), "bounding boxes"); area_right = (DBL *)POV_MALLOC(size * sizeof(DBL), "bounding boxes"); /* Precalculate the areas for speed. */ build_area_table(Finite, first, last - 1, area_left); build_area_table(Finite, last - 1, first, area_right); best_index = area_right[0] * (size - 3.0); best_loc = -1; /* * Find the most effective point to split. The best location will be * the one that minimizes the function N1*A1 + N2*A2 where N1 and N2 * are the number of objects in the two groups and A1 and A2 are the * surface areas of the bounding boxes of the two groups. */ for (i = 0; i < size - 1; i++) { new_index = (i + 1) * area_left[i] + (size - 1 - i) * area_right[i + 1]; if (new_index < best_index) { best_index = new_index; best_loc = i + first; } } POV_FREE(area_left); POV_FREE(area_right); /* * Stop splitting if the BUNCHING_FACTOR is reached or * if splitting stops being effective. */ if ((size <= BUNCHING_FACTOR) || (best_loc < 0)) { cd = create_bbox_node(size); for (i = 0; i < size; i++) { cd->Node[i] = Finite[first+i]; } calc_bbox(&(cd->BBox), Finite, first, last); *Root = (BBOX_TREE *)cd; if (*numOfFiniteObjects > maxfinitecount) { /* Prim array overrun, increase array by 50%. */ maxfinitecount = 1.5 * maxfinitecount; /* For debugging only. */ Debug_Info("Reallocing Finite to %d\n", maxfinitecount); Finite = (BBOX_TREE **)POV_REALLOC(Finite, maxfinitecount * sizeof(BBOX_TREE *), "bounding boxes"); } Finite[*numOfFiniteObjects] = cd; (*numOfFiniteObjects)++; return (1); } else { sort_and_split(Root, Finite, numOfFiniteObjects, first, best_loc + 1); sort_and_split(Root, Finite, numOfFiniteObjects, best_loc + 1, last); return (0); } }
void Build_BBox_Tree(BBOX_TREE **Root, long numOfFiniteObjects, BBOX_TREE **&Finite, long numOfInfiniteObjects, BBOX_TREE **Infinite) { short i; long low, high; BBOX_TREE *cd, *root; /* * This is a resonable guess at the number of finites needed. * This array will be reallocated as needed if it isn't. */ maxfinitecount = 2 * numOfFiniteObjects; /* * Now do a sort on the objects, with the end result being * a tree of objects sorted along the x, y, and z axes. */ if (numOfFiniteObjects > 0) { low = 0; high = numOfFiniteObjects; while (sort_and_split(Root, Finite, &numOfFiniteObjects, low, high) == 0) { low = high; high = numOfFiniteObjects; Do_Cooperate(0); } /* Move infinite objects in the first leaf of Root. */ if (numOfInfiniteObjects > 0) { root = (BBOX_TREE *)(*Root); root->Node = (BBOX_TREE **)POV_REALLOC(root->Node, (root->Entries + 1) * sizeof(BBOX_TREE *), "composite"); POV_MEMMOVE(&(root->Node[1]), &(root->Node[0]), root->Entries * sizeof(BBOX_TREE *)); root->Entries++; cd = create_bbox_node(numOfInfiniteObjects); for (i = 0; i < numOfInfiniteObjects; i++) { cd->Node[i] = Infinite[i]; } calc_bbox(&(cd->BBox), Infinite, 0, numOfInfiniteObjects); root->Node[0] = (BBOX_TREE *)cd; calc_bbox(&(root->BBox), root->Node, 0, root->Entries); /* Root and first node are infinite. */ root->Infinite = true; root->Node[0]->Infinite = true; } } else { /* * There are no finite objects and no Root was created. * Create it now and put all infinite objects into it. */ if (numOfInfiniteObjects > 0) { cd = create_bbox_node(numOfInfiniteObjects); for (i = 0; i < numOfInfiniteObjects; i++) { cd->Node[i] = Infinite[i]; } calc_bbox(&(cd->BBox), Infinite, 0, numOfInfiniteObjects); *Root = (BBOX_TREE *)cd; (*Root)->Infinite = true; } } }
UCS2 *Parser::String_Literal_To_UCS2(const std::string& str) { UCS2 *char_string = nullptr; UCS2 *char_array = nullptr; std::string::size_type char_array_size = 0; int utf8arraysize = 0; unsigned char *utf8array = nullptr; int index_in = 0; int index_out = 0; char buffer[8]; char *dummy_ptr = nullptr; int i = 0; if(str.length() == 0) { char_string = reinterpret_cast<UCS2 *>(POV_MALLOC(sizeof(UCS2), "UCS2 String")); char_string[0] = 0; return char_string; } char_array_size = str.length(); char_array = reinterpret_cast<UCS2 *>(POV_MALLOC(char_array_size * sizeof(UCS2), "Character Array")); for(i = 0; i < char_array_size; i++) { if(sceneData->EffectiveLanguageVersion() < 350) char_array[i] = (unsigned char)(str[i]); else { char_array[i] = str[i] & 0x007F; if(char_array[i] != str[i]) { char_array[i] = ' '; PossibleError("Unexpected non-ASCII character has been replaced by space character."); } } } char_string = reinterpret_cast<UCS2 *>(POV_MALLOC((char_array_size + 1) * sizeof(UCS2), "UCS2 String")); for(index_in = 0, index_out = 0; index_in < char_array_size; index_in++, index_out++) { if(char_array[index_in] == '\\') { index_in++; switch(char_array[index_in]) { case 'a': char_string[index_out] = 0x07; break; case 'b': char_string[index_out] = 0x08; break; case 'f': char_string[index_out] = 0x0c; break; case 'n': char_string[index_out] = 0x0a; break; case 'r': char_string[index_out] = 0x0d; break; case 't': char_string[index_out] = 0x09; break; case 'v': char_string[index_out] = 0x0b; break; case '\0': // [CLi] shouldn't happen, as having a backslash as the last character of a string literal would invalidate the string terminator Error("Unexpected end of escape sequence in text string."); break; case '\'': case '\"': case '\\': char_string[index_out] = char_array[index_in]; break; case 'u': if(index_in + 4 >= char_array_size) Error("Unexpected end of escape sequence in text string."); buffer[0] = char_array[++index_in]; buffer[1] = char_array[++index_in]; buffer[2] = char_array[++index_in]; buffer[3] = char_array[++index_in]; buffer[4] = 0; char_string[index_out] = (UCS2)std::strtoul(buffer, &dummy_ptr, 16); break; default: char_string[index_out] = char_array[index_in]; POV_FREE(char_array); char_array = nullptr; Error( "Illegal escape sequence in string." ); break; } } else char_string[index_out] = char_array[index_in]; } char_string[index_out] = 0; index_out++; char_string = reinterpret_cast<UCS2 *>(POV_REALLOC(char_string, index_out * sizeof(UCS2), "UCS2 String")); if (char_array != nullptr) POV_FREE(char_array); return char_string; }
UCS2 *Parser::String_Literal_To_UCS2(const char *str, bool pathname) { UCS2 *char_string = NULL; UCS2 *char_array = NULL; int char_array_size = 0; int utf8arraysize = 0; unsigned char *utf8array = NULL; int index_in = 0; int index_out = 0; char buffer[8]; char *dummy_ptr = NULL; int i = 0; if(strlen(str) == 0) { char_string = reinterpret_cast<UCS2 *>(POV_MALLOC(sizeof(UCS2), "UCS2 String")); char_string[0] = 0; return char_string; } switch(sceneData->stringEncoding) { case kStringEncoding_ASCII: char_array_size = (int)strlen(str); char_array = reinterpret_cast<UCS2 *>(POV_MALLOC(char_array_size * sizeof(UCS2), "Character Array")); for(i = 0; i < char_array_size; i++) { if(sceneData->EffectiveLanguageVersion() < 350) char_array[i] = (unsigned char)(str[i]); else { char_array[i] = str[i] & 0x007F; if(char_array[i] != str[i]) { char_array[i] = ' '; PossibleError("Non-ASCII character has been replaced by space character."); } } } break; case kStringEncoding_UTF8: char_array = Convert_UTF8_To_UCS2(reinterpret_cast<const unsigned char *>(str), (int)strlen(str), &char_array_size); break; case kStringEncoding_System: char_array = POV_CONVERT_TEXT_TO_UCS2(reinterpret_cast<const unsigned char *>(str), strlen(str), &char_array_size); if(char_array == NULL) Error("Cannot convert system specific text format to Unicode."); break; default: Error("Unsupported text encoding format."); break; } if(char_array == NULL) Error("Cannot convert text to UCS2 format."); char_string = reinterpret_cast<UCS2 *>(POV_MALLOC((char_array_size + 1) * sizeof(UCS2), "UCS2 String")); for(index_in = 0, index_out = 0; index_in < char_array_size; index_in++, index_out++) { if((char_array[index_in] == '\\') && (sceneData->EffectiveLanguageVersion() >= 371 || !pathname)) { // Historically, escape sequences were ignored when parsing for a filename. // As of POV-Ray 3.71, this has been changed. #if (FILENAME_SEPARATOR == '\\') if (pathname) { Warning("Backslash encountered while parsing for a filename." " As of version 3.71, this is interpreted as an escape sequence just like in any other string literal." " If this is supposed to be a path separator, use a forward slash instead."); } #endif index_in++; switch(char_array[index_in]) { case 'a': char_string[index_out] = 0x07; break; case 'b': char_string[index_out] = 0x08; break; case 'f': char_string[index_out] = 0x0c; break; case 'n': char_string[index_out] = 0x0a; break; case 'r': char_string[index_out] = 0x0d; break; case 't': char_string[index_out] = 0x09; break; case 'v': char_string[index_out] = 0x0b; break; case '\0': // [CLi] shouldn't happen, as having a backslash as the last character of a string literal would invalidate the string terminator Error("Unexpected end of escape sequence in text string."); break; case '\'': case '\"': case '\\': char_string[index_out] = char_array[index_in]; break; case 'u': if(index_in + 4 >= char_array_size) Error("Unexpected end of escape sequence in text string."); buffer[0] = char_array[++index_in]; buffer[1] = char_array[++index_in]; buffer[2] = char_array[++index_in]; buffer[3] = char_array[++index_in]; buffer[4] = 0; char_string[index_out] = (UCS2)strtoul(buffer, &dummy_ptr, 16); break; default: char_string[index_out] = char_array[index_in]; if ( char_array ) POV_FREE(char_array); char_array = NULL; Error( "Illegal escape sequence in string." ); break; } } else { if ((char_array[index_in] == '\\') && pathname) { // Historically, escape sequences were ignored when parsing for a filename. // As of POV-Ray 3.71, this has been changed. #if (FILENAME_SEPARATOR == '\\') Warning("Backslash encountered while parsing for a filename." " In legacy (pre-3.71) scenes, this is NOT interpreted as the start of an escape sequence." " However, for future compatibility it is recommended to use a forward slash as path separator instead."); #else Warning("Backslash encountered while parsing for a filename." " In legacy (pre-3.71) scenes, this is NOT interpreted as the start of an escape sequence."); #endif } char_string[index_out] = char_array[index_in]; } } char_string[index_out] = 0; index_out++; char_string = reinterpret_cast<UCS2 *>(POV_REALLOC(char_string, index_out * sizeof(UCS2), "UCS2 String")); if(char_array != NULL) POV_FREE(char_array); return char_string; }
DBL POVFPU_RunDefault(FUNCTION fn) { StackFrame *pstack = POVFPU_Current_Context->pstackbase; DBL *dblstack = POVFPU_Current_Context->dblstackbase; unsigned int maxdblstacksize = POVFPU_Current_Context->maxdblstacksize; DBL r0, r1, r2, r3, r4, r5, r6, r7; Instruction *program = NULL; unsigned int k = 0; unsigned int pc = 0; unsigned int ccr = 0; unsigned int sp = 0; unsigned int psp = 0; #if (SUPPORT_INTEGER_INSTRUCTIONS == 1) POV_LONG iA, iB, itemp; #endif #if (DEBUG_DEFAULTCPU == 1) COUNTER instr; Long_To_Counter(POVFPU_Functions[fn].fn.program_size, instr); Add_Counter(stats[Ray_Function_VM_Instruction_Est], stats[Ray_Function_VM_Instruction_Est], instr); #endif Increase_Counter(stats[Ray_Function_VM_Calls]); program = POVFPU_Functions[fn].fn.program; while(true) { k = GET_K(program[pc]); switch(GET_OP(program[pc])) { OP_MATH_AOP(0,+); // add Rs, Rd OP_MATH_AOP(1,-); // sub Rs, Rd OP_MATH_AOP(2,*); // mul Rs, Rd OP_MATH_AOP(3,/); // div Rs, Rd OP_MOD_A(4); // mod Rs, Rd OP_ASSIGN_ABOP(5,0,r0); // move R0, Rd OP_ASSIGN_ABOP(5,1,r1); // move R1, Rd OP_ASSIGN_ABOP(5,2,r2); // move R2, Rd OP_ASSIGN_ABOP(5,3,r3); // move R3, Rd OP_ASSIGN_ABOP(5,4,r4); // move R4, Rd OP_ASSIGN_ABOP(5,5,r5); // move R5, Rd OP_ASSIGN_ABOP(5,6,r6); // move R6, Rd OP_ASSIGN_ABOP(5,7,r7); // move R7, Rd OP_CMP_ABC(6,0,r0); // cmp R0, Rd OP_CMP_ABC(6,1,r1); // cmp R1, Rd OP_CMP_ABC(6,2,r2); // cmp R2, Rd OP_CMP_ABC(6,3,r3); // cmp R3, Rd OP_CMP_ABC(6,4,r4); // cmp R4, Rd OP_CMP_ABC(6,5,r5); // cmp R5, Rd OP_CMP_ABC(6,6,r6); // cmp R6, Rd OP_CMP_ABC(6,7,r7); // cmp R7, Rd OP_ASSIGN_ABOP(7,0,-r0); // neg R0, Rd OP_ASSIGN_ABOP(7,1,-r1); // neg R1, Rd OP_ASSIGN_ABOP(7,2,-r2); // neg R2, Rd OP_ASSIGN_ABOP(7,3,-r3); // neg R3, Rd OP_ASSIGN_ABOP(7,4,-r4); // neg R4, Rd OP_ASSIGN_ABOP(7,5,-r5); // neg R5, Rd OP_ASSIGN_ABOP(7,6,-r6); // neg R6, Rd OP_ASSIGN_ABOP(7,7,-r7); // neg R7, Rd OP_ABS_A(8); // abs Rs, Rd OP_MATH_ABCOP(9,0,POVFPU_Consts[k],+); // addi k, Rd OP_MATH_ABCOP(9,1,POVFPU_Consts[k],-); // subi k, Rd OP_MATH_ABCOP(9,2,POVFPU_Consts[k],*); // muli k, Rd OP_MATH_ABCOP(9,3,POVFPU_Consts[k],/); // divi k, Rd OP_MOD_ABC(9,4,POVFPU_Consts[k]); // modi k, Rd OP_ASSIGN_ABOP(9,5,POVFPU_Consts[k]); // loadi k, Rd OP_CMP_ABC(9,6,POVFPU_Consts[k]); // cmpi k, Rs OP_ASSIGN_ABOP(10,0,ccr == 1); // seq Rd OP_ASSIGN_ABOP(10,1,ccr != 1); // sne Rd OP_ASSIGN_ABOP(10,2,ccr == 2); // slt Rd OP_ASSIGN_ABOP(10,3,ccr >= 1); // sle Rd OP_ASSIGN_ABOP(10,4,ccr == 0); // sgt Rd OP_ASSIGN_ABOP(10,5,ccr <= 1); // sge Rd OP_MATH_ABCOP(10,6,0.0,==); // teq Rd OP_MATH_ABCOP(10,7,0.0,!=); // tne Rd OP_ASSIGN_ABOP(11,0,POVFPU_Globals[k]); // load 0(k), Rd OP_ASSIGN_ABOP(11,1,dblstack[sp+k]); // load SP(k), Rd OP_REVASSIGN_ABOP(12,0,POVFPU_Globals[k]); // store Rs, 0(k) OP_REVASSIGN_ABOP(12,1,dblstack[sp+k]); // store Rs, SP(k) OP_SPECIAL(13,0,0,if(ccr == 1) pc = k - 1); // beq k OP_SPECIAL(13,1,0,if(ccr != 1) pc = k - 1); // bne k OP_SPECIAL(13,2,0,if(ccr == 2) pc = k - 1); // blt k OP_SPECIAL(13,3,0,if(ccr >= 1) pc = k - 1); // ble k OP_SPECIAL(13,4,0,if(ccr == 0) pc = k - 1); // bgt k OP_SPECIAL(13,5,0,if(ccr <= 1) pc = k - 1); // bge k OP_XCC_ABOP(14,0,==); // xeq Rd OP_XCC_ABOP(14,1,!=); // xne Rd OP_XCC_ABOP(14,2,<); // xlt Rd OP_XCC_ABOP(14,3,<=); // xle Rd OP_XCC_ABOP(14,4,>); // xgt Rd OP_XCC_ABOP(14,5,>=); // xge Rd OP_SPECIAL(14,6,0,if((r0 == 0.0) && (r0 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R0 OP_SPECIAL(14,6,1,if((r0 == 0.0) && (r1 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R1 OP_SPECIAL(14,6,2,if((r0 == 0.0) && (r2 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R2 OP_SPECIAL(14,6,3,if((r0 == 0.0) && (r3 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R3 OP_SPECIAL(14,6,4,if((r0 == 0.0) && (r4 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R4 OP_SPECIAL(14,6,5,if((r0 == 0.0) && (r5 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R5 OP_SPECIAL(14,6,6,if((r0 == 0.0) && (r6 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R6 OP_SPECIAL(14,6,7,if((r0 == 0.0) && (r7 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R7 OP_SPECIAL_CASE(15,0,0) // jsr k pstack[psp].pc = pc; pstack[psp].fn = fn; psp++; if(psp >= MAX_CALL_STACK_SIZE) POVFPU_Exception(fn, "Maximum function evaluation recursion level reached."); pc = k; continue; // prevent increment of pc OP_SPECIAL_CASE(15,0,1) // jmp k pc = k; continue; // prevent increment of pc OP_SPECIAL_CASE(15,0,2) // rts if(psp == 0) return r0; psp--; pc = pstack[psp].pc; // old position, will be incremented fn = pstack[psp].fn; program = POVFPU_Functions[fn].fn.program; break; OP_SPECIAL_CASE(15,0,3) // call k pstack[psp].pc = pc; pstack[psp].fn = fn; psp++; if(psp >= MAX_CALL_STACK_SIZE) POVFPU_Exception(fn, "Maximum function evaluation recursion level reached."); fn = k; program = POVFPU_Functions[fn].fn.program; pc = 0; continue; // prevent increment of pc OP_SPECIAL_CASE(15,0,4) // sys1 k r0 = POVFPU_Sys1Table[k](r0); break; OP_SPECIAL_CASE(15,0,5) // sys2 k r0 = POVFPU_Sys2Table[k](r0,r1); break; OP_SPECIAL_CASE(15,0,6) // trap k r0 = POVFPU_TrapTable[k].fn(&dblstack[sp], fn); maxdblstacksize = POVFPU_Current_Context->maxdblstacksize; dblstack = POVFPU_Current_Context->dblstackbase; break; OP_SPECIAL_CASE(15,0,7) // traps k POVFPU_TrapSTable[k].fn(&dblstack[sp], fn, sp); maxdblstacksize = POVFPU_Current_Context->maxdblstacksize; dblstack = POVFPU_Current_Context->dblstackbase; break; OP_SPECIAL_CASE(15,1,0) // grow k if((unsigned int)((unsigned int)sp + (unsigned int)k) >= (unsigned int)MAX_K) { POVFPU_Exception(fn, "Stack full. Possible infinite recursive function call."); } else if(sp + k >= maxdblstacksize) { maxdblstacksize = POVFPU_Current_Context->maxdblstacksize = POVFPU_Current_Context->maxdblstacksize + max(k + 1, (unsigned int)256); dblstack = POVFPU_Current_Context->dblstackbase = (DBL *)POV_REALLOC(dblstack, sizeof(DBL) * maxdblstacksize, "fn: stack"); } break; OP_SPECIAL_CASE(15,1,1) // push k if(sp + k >= maxdblstacksize) POVFPU_Exception(fn, "Function evaluation stack overflow."); sp += k; break; OP_SPECIAL_CASE(15,1,2) // pop k if(k > sp) POVFPU_Exception(fn, "Function evaluation stack underflow."); sp -= k; break; #if (SUPPORT_INTEGER_INSTRUCTIONS == 1) OP_SPECIAL_CASE(15,1,3) // iconv iA = POV_LONG(r0); break; OP_SPECIAL_CASE(15,1,4) // fconv r0 = DBL(iA); break; OP_SPECIAL_CASE(15,1,5) // reserved POVFPU_Exception(fn, "Internal error - reserved function VM opcode found!"); break; OP_INT_MATH_ABOP(15,32,+); // add s, d OP_INT_MATH_ABOP(15,33,-); // sub s, d OP_INT_MATH_ABOP(15,34,*); // mul s, d OP_INT_SPECIAL(15,35,0,iA = iA / iB); // div B, A OP_INT_SPECIAL(15,35,1,iB = iB / iA); // div A, B OP_INT_SPECIAL(15,35,2,iA = iA % iB); // mod B, A OP_INT_SPECIAL(15,35,3,iB = iB % iA); // mod A, B OP_INT_SPECIAL(15,36,0,ccr = (((iB > iA) & 1) << 1) | ((iB == iA) & 1)); // cmp B, A OP_INT_SPECIAL(15,36,1,ccr = (((iA > iB) & 1) << 1) | ((iA == iB) & 1)); // cmp A, B OP_INT_SPECIAL(15,36,2,itemp = iA; iA = iB; iB = itemp); // exg A, B OP_INT_SPECIAL(15,36,3,iA = iB = 0); // clr A, B OP_INT_SPECIAL(15,37,0,iA = 0); // clr A OP_INT_SPECIAL(15,37,1,iB = 0); // clr B OP_INT_SPECIAL(15,37,2,iA = iB); // move B, A OP_INT_SPECIAL(15,37,3,iB = iA); // move A, B OP_INT_SPECIAL(15,38,0,iA = -iA); // neg A OP_INT_SPECIAL(15,38,1,iB = -iB); // neg B OP_INT_SPECIAL(15,38,2,iA = abs(iA)); // abs A OP_INT_SPECIAL(15,38,3,iB = abs(iB)); // abs B OP_INT_SPECIAL(15,39,0,iA = iA + k); // addi k, A OP_INT_SPECIAL(15,39,1,iB = iB + k); // addi k, B OP_INT_SPECIAL(15,39,2,iA = iA - k); // subi k, A OP_INT_SPECIAL(15,39,3,iB = iB - k); // subi k, B OP_INT_MATH_SHIFT_ABOP(15,40,<<,POV_LONG); // asl s, d OP_INT_MATH_SHIFT_ABOP(15,41,>>,POV_LONG); // asr s, d OP_INT_MATH_SHIFT_ABOP(15,42,<<,POV_ULONG); // lsl s, d OP_INT_MATH_SHIFT_ABOP(15,43,>>,POV_ULONG); // lsr s, d OP_INT_MATH_ABOP(15,44,&); // and s, d OP_INT_MATH_ABOP(15,45,|); // or s, d OP_INT_MATH_ABOP(15,46,^); // xor s, d OP_INT_SPECIAL(15,47,0,iA = !iA); // not A, A OP_INT_SPECIAL(15,47,1,iA = !iB); // not B, A OP_INT_SPECIAL(15,47,2,iB = !iA); // not A, B OP_INT_SPECIAL(15,47,3,iB = !iB); // not B, B OP_INT_SPECIAL(15,48,0,iA = k); // loadi A OP_INT_SPECIAL(15,48,1,iB = k); // loadi B OP_INT_SPECIAL(15,48,2,iA = (iA << 16) | k);// ldhi A OP_INT_SPECIAL(15,48,3,iB = (iB << 16) | k);// ldhi B OP_INT_SPECIAL(15,49,0,iA = max(POV_LONG(k), iA)); // max k, A OP_INT_SPECIAL(15,49,1,iB = max(POV_LONG(k), iB)); // max k, B OP_INT_SPECIAL(15,49,2,iA = min(POV_LONG(k), iA)); // min k, A OP_INT_SPECIAL(15,49,3,iB = min(POV_LONG(k), iB)); // min k, B OP_INT_SPECIAL(15,50,0,iA = (POV_LONG(iA) << k)); // asl k, A OP_INT_SPECIAL(15,50,1,iB = (POV_LONG(iB) >> k)); // asr k, B OP_INT_SPECIAL(15,50,2,iA = (POV_ULONG(iA) << k)); // lsl k, A OP_INT_SPECIAL(15,50,3,iB = (POV_ULONG(iB) >> k)); // lsr k, B #endif default: // nop break; } pc++; } #if (DEBUG_DEFAULTCPU == 1) printf("Registers\n"); printf("=========\n"); printf("PC = %d\n", (int)pc); printf("CCR = %x\n", (int)ccr); printf("R0 = %8f R4 = %8f\n", (float)r0, (float)r4); printf("R1 = %8f R5 = %8f\n", (float)r1, (float)r5); printf("R2 = %8f R6 = %8f\n", (float)r2, (float)r6); printf("R3 = %8f R7 = %8f\n", (float)r3, (float)r7); #endif }
int sort_and_split(BBOX_TREE **Root, BBOX_TREE **&Finite, size_t *numOfFiniteObjects, ptrdiff_t first, ptrdiff_t last, size_t& maxfinitecount) { BBOX_TREE *cd; ptrdiff_t size, i, best_loc; DBL *area_left, *area_right; DBL best_index, new_index; int Axis = find_axis(Finite, first, last); size = last - first; if(size <= 0) return (1); // Actually, we could do this faster in several ways. We could use a // logn algorithm to find the median along the given axis, and then a // linear algorithm to partition along the axis. Oh well. switch(Axis) { case X: QSORT(reinterpret_cast<void *>(&Finite[first]), size, sizeof(BBOX_TREE *), compboxes<X>); break; case Y: QSORT(reinterpret_cast<void *>(&Finite[first]), size, sizeof(BBOX_TREE *), compboxes<Y>); break; case Z: QSORT(reinterpret_cast<void *>(&Finite[first]), size, sizeof(BBOX_TREE *), compboxes<Z>); break; } // area_left[] and area_right[] hold the surface areas of the bounding // boxes to the left and right of any given point. E.g. area_left[i] holds // the surface area of the bounding box containing Finite 0 through i and // area_right[i] holds the surface area of the box containing Finite // i through size-1. area_left = new DBL[size]; area_right = new DBL[size]; // Precalculate the areas for speed. build_area_table(Finite, first, last - 1, area_left); build_area_table(Finite, last - 1, first, area_right); best_index = area_right[0] * (size - 3.0); best_loc = -1; // Find the most effective point to split. The best location will be // the one that minimizes the function N1*A1 + N2*A2 where N1 and N2 // are the number of objects in the two groups and A1 and A2 are the // surface areas of the bounding boxes of the two groups. for(i = 0; i < size - 1; i++) { new_index = (i + 1) * area_left[i] + (size - 1 - i) * area_right[i + 1]; if(new_index < best_index) { best_index = new_index; best_loc = i + first; } } delete[] area_left; delete[] area_right; // Stop splitting if the BUNCHING_FACTOR is reached or // if splitting stops being effective. if((size <= BUNCHING_FACTOR) || (best_loc < 0)) { cd = create_bbox_node(size); for(i = 0; i < size; i++) cd->Node[i] = Finite[first+i]; calc_bbox(&(cd->BBox), Finite, first, last); *Root = cd; if(*numOfFiniteObjects >= maxfinitecount) { // Prim array overrun, increase array by 50%. maxfinitecount = 1.5 * maxfinitecount; // For debugging only. // TODO MESSAGE Debug_Info("Reallocing Finite to %d\n", maxfinitecount); Finite = reinterpret_cast<BBOX_TREE **>(POV_REALLOC(Finite, maxfinitecount * sizeof(BBOX_TREE *), "bounding boxes")); } Finite[*numOfFiniteObjects] = cd; (*numOfFiniteObjects)++; return (1); } sort_and_split(Root, Finite, numOfFiniteObjects, first, best_loc + 1, maxfinitecount); sort_and_split(Root, Finite, numOfFiniteObjects, best_loc + 1, last, maxfinitecount); return (0); }