示例#1
0
UCS2 *Parser::String_To_UCS2(const char *str)
{
    UCS2 *char_string = nullptr;
    UCS2 *char_array = nullptr;
    int char_array_size = 0;
    int utf8arraysize = 0;
    unsigned char *utf8array = nullptr;
    int index_in = 0;
    int index_out = 0;
    char *dummy_ptr = nullptr;
    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;
    }

    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("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++)
        char_string[index_out] = char_array[index_in];

    char_string[index_out] = 0;
    index_out++;

    if (char_array != nullptr)
        POV_FREE(char_array);

    return char_string;
}
示例#2
0
bool Parser::expr_err(ExprNode *&, int stage, int)
{
    int i;

    if(stage == 35)
        PossibleError("Suspicious identifier found in function!\n"
                      "If you want to call a function make sure the function you call has been declared.\n"
                      "If you call an internal function, make sure you have included 'functions.inc'.");

    for(i = 0; (expr_parser_error_table[i].stage >= 0) && (expr_parser_error_table[i].expected != NULL); i++)
    {
        if(expr_parser_error_table[i].stage == stage)
            Expectation_Error(expr_parser_error_table[i].expected);
    }

    Expectation_Error("valid function expression");

    // unreachable, Expectation_Error stops parsing
    return false;
}
示例#3
0
char *Locate_Filename(char *filename, unsigned int stype, bool err_flag)
{
  int i,ii,l[4];
  char pathname[FILE_NAME_LENGTH];
  char file[FILE_NAME_LENGTH];
  char file_x[4][FILE_NAME_LENGTH];
  char *result = NULL;

  if (Has_Extension(filename))
  {
    for(i = 0; i < 4; i++)
      l[i]=0;
  }
  else
  {
    for(i = 0; i < 4; i++)
    {
      if ((l[i] = strlen(gPOV_File_Extensions[stype].ext[i])) > 0)
      {
        strcpy(file_x[i], filename);
        strcat(file_x[i], gPOV_File_Extensions[stype].ext[i]);
      }
    }
  }

  /* Check the current directory first. */
  for(i = 0; i < 4; i++)
  {
    /* Try appending the variations of the file extension */
    if(l[i])
    {
      if (EXIST_FILE(file_x[i]) == true)
      {
        result = new char[strlen(file_x[i]) + 1];
        POV_GET_FULL_PATH(file_x[i], result);
        return result;
      }
    }
  }
  /* Try the filename without any modifications */
  if (EXIST_FILE(filename) == true)
  {
    result = new char[strlen(filename) + 1];
    POV_GET_FULL_PATH(filename, result);
    return result;
  }
  
  /* Walk through the library paths, trying with and without file extensions */
  for (i = 0; i < opts.Library_Path_Index; i++)
  {
    strcpy(file, opts.Library_Paths[i]);
    file[strlen(file)+1] = '\0';
    if (file[strlen(file) - 1] != DRIVE_SEPARATOR)
      file[strlen(file)] = FILENAME_SEPARATOR;
    
    for(ii = 0; ii < 4; ii++)
    {
      if(l[ii])
      {
        strcpy(pathname, file);
        strcat(pathname, file_x[ii]);
        if (EXIST_FILE(pathname) == true)
        {
          result = new char[strlen(pathname) + 1];
          POV_GET_FULL_PATH(pathname, result);
          return result;
        }
      }
    }
    
    strcpy(pathname, file);
    strcat(pathname, filename);
    if (EXIST_FILE(pathname) == true)
    {
      result = new char[strlen(pathname) + 1];
      POV_GET_FULL_PATH(pathname, result);
      return result;
    }
  }

  // Allow system specific access of font files:
  // Obviously this requires POV_NEW_ISTREAM
  // to be platform specific as well! [trf]
  if(stype == POV_File_Font_TTF)
  {
    if(EXIST_FONT_FILE(filename))
    {
       result = new char[strlen(filename) + 1];
       strcpy(filename, result);
       return result;
    }
  }

  if (err_flag)
  {
    if (l[0])
      PossibleError("Could not find file '%s%s'",filename,gPOV_File_Extensions[stype].ext[0]);
    else
      PossibleError("Could not find file '%s'",filename);
  }
  
  return NULL;
}
示例#4
0
文件: parsestr.cpp 项目: Nyoho/povray
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;
}
示例#5
0
void FrameRender()
{
   // Store start time for parse.
   START_TIME

   Current_Token_Count = 0;
   tparse_frame = tphoton_frame = trender_frame = 0.0;

   // Parse the scene file.
   Send_Progress("Parsing", PROGRESS_PARSING);

   opts.Do_Stats = false;

   // Set up noise-tables
   Initialize_Noise();

   // Set up function VM
   POVFPU_Init();

   // Init module specific stuff.
   Initialize_Mesh_Code();

   Parse();

   opts.Do_Stats = true;

   if (opts.Radiosity_Enabled)
      Experimental_Flag |= EF_RADIOS;

   if (Experimental_Flag)
   {
      char str[512] = "" ;

      if (Experimental_Flag & EF_SPLINE)
        strcat (str, str [0] ? ", spline" : "spline") ;
      if (Experimental_Flag & EF_RADIOS)
        strcat (str, str [0] ? ", radiosity" : "radiosity") ;
      if (Experimental_Flag & EF_SLOPEM)
        strcat (str, str [0] ? ", slope pattern" : "slope pattern") ;
      if (Experimental_Flag & EF_ISOFN) 
        strcat (str, str [0] ? ", function '.hf'" : "function '.hf'") ;
      if (Experimental_Flag & EF_TIFF) 
        strcat (str, str [0] ? ", TIFF image support" : "TIFF image support") ;

      Warning(0, "This rendering uses the following experimental feature(s): %s.\n"
                 "The design and implementation of these features is likely to change in future versions\n"
                 "of POV-Ray. Full backward compatibility with the current implementation is NOT guaranteed.",
                 str);
   }

   Experimental_Flag = 0;

   // Switch off standard anti-aliasing.

   if((Frame.Camera->Aperture != 0.0) && (Frame.Camera->Blur_Samples > 0))
   {
      opts.Options &= ~ANTIALIAS;

      Warning(0, "Focal blur is used. Standard antialiasing is switched off.");
   }

   // Create the bounding box hierarchy.

   Stage = STAGE_SLAB_BUILDING;

   if(opts.Use_Slabs)
      Send_Progress("Creating bounding slabs", PROGRESS_CREATING_BOUNDING_SLABS);

   // Init module specific stuff.
   Initialize_Atmosphere_Code();
   Initialize_BBox_Code();
   Initialize_Lighting_Code();
   Initialize_VLBuffer_Code();
   Initialize_Radiosity_Code();

   // Always call this to print number of objects.
   Build_Bounding_Slabs(&Root_Object);

   // Create the vista buffer.
   Build_Vista_Buffer();

   // Create the light buffers.
   Build_Light_Buffers();

   // Save variable values.
   variable_store(STORE);

   // Get the parsing time.
   STOP_TIME
   tparse = TIME_ELAPSED
   Send_ProgressUpdate(PROGRESS_PARSING, 0);

   // Output parsing statistics.
   Send_ParseStatistics();

   if (photonOptions.photonsEnabled)
   {
     /* Store start time for photons. */
     START_TIME

     /* now backwards-trace the scene and build the photon maps */
     InitBacktraceEverything();
     BuildPhotonMaps();

     /* Get the photon-shooting time. */
     STOP_TIME
     tphoton = TIME_ELAPSED

     /* Get total parsing time. */
     tphoton_total += tphoton;
     tphoton_frame = tphoton;
     tphoton = 0;
   }

   /* Store start time for the rest of parsing. */
   START_TIME
   Stage = STAGE_INIT;

   // Open output file and if we are continuing an interrupted trace,
   // read in the previous file settings and any data there.  This has to
   // be done before any image-size related allocations, since the settings
   // in a resumed file take precedence over that specified by the user. [AED]
   open_output_file();

   // Start the display.
   if(opts.Options & DISPLAY)
   {
      Send_Progress("Displaying", PROGRESS_DISPLAYING);

      Display_Started = POV_DISPLAY_INIT(opts.Preview_RefCon, Frame.Screen_Width, Frame.Screen_Height);

      // Display vista tree.
      Draw_Vista_Buffer();
   }
   else
   {
      Display_Started = false;
   }

   // Get things ready for ray tracing (misc init, mem alloc)
   Initialize_Renderer();

   // This had to be taken out of open_output_file() because we don't have
   // the final image size until the output file has been opened, so we can't
   // initialize the display until we know this, which in turn means we can't
   // read the rendered part before the display is initialized. [AED]
   if((opts.Options & DISKWRITE) && (opts.Options & CONTINUE_TRACE))
   {
      Read_Rendered_Part(Actual_Output_Name);

      if (opts.Last_Line > Frame.Screen_Height)
         opts.Last_Line = Frame.Screen_Height;

      if (opts.Last_Column > Frame.Screen_Width)
         opts.Last_Column = Frame.Screen_Width;
   }

   // Get the rest of the parsing time.
   STOP_TIME
   tparse += TIME_ELAPSED

   // Store start time for trace.
   START_TIME

   // Get total parsing time.
   tparse_total += tparse;
   tparse_frame = tparse;
   tparse = 0;

   // Start tracing.
   Stage = STAGE_RENDERING;

   POV_PRE_RENDER

   Send_Progress("Rendering", PROGRESS_RENDERING);

   // Macro for setting up any special FP options
   CONFIG_MATH

   // Ok, go for it - trace the picture.

   // If radiosity preview has been done, we are continuing a trace, so it
   // is important NOT to do the preview, even if the user requests it, as it
   // will cause discontinuities in radiosity shading by (probably) calculating
   // a few more radiosity values.

   // Note that radiosity REQUIRES a mosaic preview prior to main scan
   if ( opts.Radiosity_Enabled && !opts.Radiosity_Preview_Done)
      Start_Tracing_Radiosity_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);

   else if((opts.Options & PREVIEW) && (opts.Options & DISPLAY))
      Start_Tracing_Mosaic_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);

   switch(opts.Tracing_Method)
   {
      case 2:
         Start_Adaptive_Tracing();
         break;
      case 1:
      default:
         Start_Non_Adaptive_Tracing();
   }

   // Record time so well spent before file close so it can be in comments
   STOP_TIME
   trender = TIME_ELAPSED

   // shutdown (freeing memory) does not get included in the time!

   // Get total render time.
   trender_total += trender;
   trender_frame = trender;
   trender = 0;

   // Close out our file
   if(Output_File != NULL)
   {
      delete Output_File;
      Output_File = NULL;
   }

   // For all those who never rtfm [trf]
   if((Highest_Trace_Level >= Max_Trace_Level) && (Had_Max_Trace_Level == false))
      PossibleError("Maximum trace level reached! If your scene contains black spots\nread more about the max_trace_level setting in the documentation!");

   Stage = STAGE_SHUTDOWN;

   POV_PRE_SHUTDOWN

   // DESTROY lots of stuff
   /* NK phmap */
   FreeBacktraceEverything();
   Deinitialize_Atmosphere_Code();
   Deinitialize_BBox_Code();
   Deinitialize_Lighting_Code();
   Deinitialize_Mesh_Code();
   Deinitialize_VLBuffer_Code();
   Deinitialize_Radiosity_Code();
   Destroy_Light_Buffers();
   Destroy_Vista_Buffer();
   Destroy_Bounding_Slabs();
   Destroy_Frame();
   Terminate_Renderer();
   FreeFontInfo();
   Free_Iteration_Stack();
   Free_Noise_Tables();

   POVFPU_Terminate();

   POV_POST_SHUTDOWN

   if((opts.Options & DISPLAY) && Display_Started)
   {
      POV_DISPLAY_FINISHED(opts.Preview_RefCon);

      POV_DISPLAY_CLOSE(opts.Preview_RefCon);

      Display_Started = false;
   }

   if(opts.histogram_on)
      write_histogram(opts.Histogram_File_Name);

   Send_Progress("Done Tracing", PROGRESS_DONE_TRACING);

   // Print stats ...
   Send_RenderStatistics();

   if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME)
   {
      // Add them up
      sum_statistics(totalstats, stats);

      // ... and then clear them for the next frame
      init_statistics(stats);
   }

   // Restore variable values.
   variable_store(RESTORE);
}
示例#6
0
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;
}
示例#7
0
UCS2 *Parser::String_To_UCS2(const char *str)
{
    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 *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++)
        char_string[index_out] = char_array[index_in];

    char_string[index_out] = 0;
    index_out++;

    if(char_array != NULL)
        POV_FREE(char_array);

    return char_string;
}
示例#8
0
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;
}