Пример #1
0
IFileStream::IFileStream(const UCS2String& name) : IStream(name), f(NULL)
{
    if(pov_stricmp(UCS2toASCIIString(name).c_str(), "stdin") == 0)
    {
        f = stdin;
    }
    else if((pov_stricmp(UCS2toASCIIString(name).c_str(), "stdout") == 0) ||
            (pov_stricmp(UCS2toASCIIString(name).c_str(), "stderr") == 0))
    {
        f = NULL;
    }
    else
    {
        f = POV_UCS2_FOPEN(name, "rb");
    }
    fail = (f == NULL);
}
Пример #2
0
int InferFileTypeFromExt(const UCS2String& ext) // TODO FIXME - belongs in backend
{
    // TODO FIXME - better compare in the string domain

    string str = UCS2toASCIIString(ext);

    for (int i = 0; i < POV_File_Count; i++)
    {
        // TODO - checking whether extension matches is required at other places, too
        for (int j = 0; j < POV_FILE_EXTENSIONS_PER_TYPE; j ++)
        {
            if ( (strlen(gPOV_File_Extensions[i].ext[j]) > 0) &&
                 (pov_stricmp (gPOV_File_Extensions[i].ext[j], str.c_str()) == 0) )
            {
                return (i);
            }
        }
    }
    return NO_FILE;
}
bool ProcessOptions::Parse_INI_String_Smartmode(ITextStream *file)
{
	ITextStream::FilePos backtrackpos = file->tellg();
	bool result = false; // false - end string here, true - continue parsing string
	struct INI_Parser_Table *table = parse_ini_table;
	char *key = NULL;

	(void)Parse_INI_Skip_Space(file, false);

	switch(file->getchar())
	{
		// end of file
		case EOF:
			break; // return false, parsing more of the string simply is not possible
		// INI file comment
		case ';':
		case '#':
			break; // return false, this is a comment which terminates the string
		// INI value list separator 
		case ',':
			break; // return false, this is a value list of unquoted strings
		// POV-Ray-style INI file with command-line switch
		case '+':
		case '-':
		// POV-Ray-style INI file with system specific command-line switch on some systems (i.e. Windos)
		#if(FILENAME_SEPARATOR != '/')
		case '/':
		#endif
			if(isalpha(file->getchar()))
				break; // return false, this is most likely a command-line
			else
				file->seekg(backtrackpos); // most likely an unquoted string, so allow parsing it as a whole
		// INI file option
		default:
			// read the key string
			key = Parse_INI_String(file);
			if(key != NULL)
			{
				// find the keyword
				while(table->keyword != NULL)
				{
					if(pov_stricmp(table->keyword, key) == 0)
						break;
					table++;
				}

				// if no valid keyword has been found
				if(table->keyword == NULL)
				{
					result = true; // return true, this is most likely an unquoted path
					ParseErrorAt(file,
					             "Most likely detected an unquoted string with spaces in INI file. Assuming string ends at the of the line.\n"
					             "Make sure all strings with spaces are properly quoted in the INI file.\n"
					             "Use either \" or \' to quote strings. For details, please check the user manual!");
				}

				delete[] key;
				key = NULL;
			}
			break; // return false, unless the code above did not find a valid keyword
	}

	file->seekg(backtrackpos);

	return result;
}
int ProcessOptions::Parse_INI_Option(ITextStream *file, POVMSObjectPtr obj)
{
	struct INI_Parser_Table *table = parse_ini_table;
	char *value = NULL;
	char *key = NULL;
	char chr = 0;
	int err = kNoErr;

	// read the key string
	key = Parse_INI_String(file);
	if(key == NULL)
	{
		ParseErrorAt(file, "Expected key in INI file, no key was found.");
		return kParseErr;
	}

	// find the keyword
	while(table->keyword != NULL)
	{
		if(pov_stricmp(table->keyword, key) == 0)
			break;
		table++;
	}

	// return if no valid keyword has been found
	if(table->keyword == NULL)
	{
		ParseErrorAt(file, "Unknown key '%s' in INI file.", key);
		delete[] key;
		return kParseErr;
	}
	else
	{
		delete[] key;
		key = NULL;
	}

	// skip any spaces
	(void)Parse_INI_Skip_Space(file, false);

	// expect the equal sign
	if(file->getchar() != '=')
		return kParseErr;

	// skip any spaces
	(void)Parse_INI_Skip_Space(file, false);

	// if the string is quoted, parse it matching quotes
	chr = file->getchar();
	if((chr == '\"') || (chr == '\''))
		value = Parse_INI_String(file, chr);
	// if there were no quotes, just read up to the next space or newline
	else
	{
		file->ungetchar(chr);
		value = Parse_INI_String(file, -2, true);
	}

	if(value == NULL)
	{
		ParseErrorAt(file, "Expected value in INI file, no value was found.");
		return kParseErr;
	}

	err = Process_INI_Option(table, value, obj);
	delete[] value;
	value = NULL;

	// skip any spaces
	(void)Parse_INI_Skip_Space(file, false);

	// if there is a comma, parse more values and append them
	chr = file->getchar();
	if(chr == ',')
	{
		// read more value strings
		while((file->eof() == false) && (err == kNoErr))
		{
			// skip any spaces
			(void)Parse_INI_Skip_Space(file, false);

			// if the string is quoted, parse it matching quotes
			chr = file->getchar();
			if((chr == '\"') || (chr == '\''))
				value = Parse_INI_String(file, chr);
			// if there were no quotes, just read up to the next space or newline
			else
			{
				file->ungetchar(chr);
				value = Parse_INI_String(file, -2);
			}

			if(value == NULL)
			{
				ParseErrorAt(file, "Expected value in INI file, no value was found.");
				return kParseErr;
			}

			err = Process_INI_Option(table, value, obj);
			delete[] value;
			value = NULL;

			// skip any spaces
			(void)Parse_INI_Skip_Space(file, false);

			// if there is no other comma, stop parsing values
			chr = file->getchar();
			if(chr != ',')
			{
				file->ungetchar(chr);
				break;
			}
		}
	}
	else
		file->ungetchar(chr);

	return err;
}
int ProcessOptions::ParseFile(const char *filespec, POVMSObjectPtr obj)
{
	ITextStream *file = NULL;
	const char *currentsection = NULL;
	char *sectionname = NULL;
	char *filename = NULL;
	int err = kNoErr;
	POVMSObjectPtr section = NULL;
	int currentline = 1;

	// split the INI files specification into filename and optional section name
	err = Parse_INI_Specification(filespec, filename, sectionname);
	if(err == kNoErr)
	{
		file = OpenFileForRead(filename, obj);
		if(file == NULL)
		{
			// all errors here are non-fatal, the calling code has to decide if an error is fatal
			ParseError("Cannot open INI file '%s'.", filename);
			err= kCannotOpenFileErr;
		}
	}

	if(err == kNoErr)
	{
		int token = 0;

		// apply options prior to any named section
		section = obj;

		// read the whole file to the end
		while((file->eof() == false) && (err == kNoErr))
		{
			currentline += Parse_INI_Skip_Space(file, true);

			token = file->getchar();

			// INI file section name
			if(token == '[')
			{
				// free old section name, if any
				if(currentsection != NULL)
					delete[] currentsection;

				// read until the section name end marker
				currentsection = Parse_INI_String(file, ']');

				// if the user specified a section name, compare the two and enable reading
				if((sectionname != NULL) && (currentsection != NULL))
				{
					if(pov_stricmp(currentsection, sectionname) == 0)
						section = obj; // named section matches specified section name, apply options
					else
						section = NULL; // named section does not match specified section name, ignore options
				}
				// if there was no user specified section name, ignore all named sections
				else
					section = NULL; // no section name was specified, ignore options in named section
			}
			// skip lines that do not belong to the desired sections
			else if(section == NULL)
			{
				currentline += Parse_INI_Skip_Line(file);
			}
			// fully process lines in desired sections
			else
			{
				switch(token)
				{
					// end of file
					case EOF:
						break;
					// quoted string
					case '\"':
					case '\'':
						err = kFalseErr;
						break;
					// POV-Ray-style INI file with command-line switch
					case '+':
					case '-':
					// POV-Ray-style INI file with system specific command-line switch on some systems (i.e. Windos)
					#if(FILENAME_SEPARATOR != '/')
					case '/':
					#endif
						err = Parse_INI_Switch(file, token, section);
						break;
					// INI file comment
					case ';':
					case '#':
						currentline += Parse_INI_Skip_Line(file);
						break;
					// INI file option
					default:
						if(isalnum(token) || (token == '_'))
						{
							file->ungetchar(token);
							ITextStream::FilePos backtrackpos = file->tellg();
							err = Parse_INI_Option(file, section);
							// only one option is allowed per line
							if(err == kNoErr)
								currentline += Parse_INI_Skip_Line(file);
							else if(err == kParseErr)
							{
								file->seekg(backtrackpos);
								err = kFalseErr;
							}
						}
						else
							err = kFalseErr;
						break;
				}

				// if nothing else was appropriate, assume it is some other kind of string requiring special attention
				if(err == kFalseErr)
				{
					char *plainstring = NULL;

					if((token == '\"') || (token == '\''))
						plainstring = Parse_INI_String(file, token, true);
					// if there were no quotes, just read up to the next space or newline
					else
						plainstring = Parse_INI_String(file, -1, true);

					err = ProcessUnknownString(plainstring, obj);

					if(plainstring != NULL)
						delete[] plainstring;
				}
			}
		}

		// all errors here are non-fatal, the calling code has to decide if an error is fatal
		if(err != kNoErr)
		{
			if(currentsection != NULL)
			{
				ParseErrorAt(file,
				             "Cannot continue to process INI file '%s' due to a parse error in line %d section '%s'.\n"
				             "This is not a valid INI file. Check the file for syntax errors, correct them, and try again!\n"
				             "Valid options in INI files are explained in detail in the reference part of the documentation.",
				             filename, currentline, currentsection);
			}
			else
			{
				ParseErrorAt(file,
				             "Cannot continue to process INI file '%s' due to a parse error in line %d.\n"
				             "This is not a valid INI file. Check the file for syntax errors, correct them, and try again!\n"
				             "Valid options in INI files are explained in detail in the reference part of the documentation.",
				             filename, currentline);
			}
		}

		if(currentsection != NULL)
			delete[] currentsection;
	}

	if(filename != NULL)
		delete[] filename;

	if(sectionname != NULL)
		delete[] sectionname;

	if(file != NULL)
		delete file;

	return err;
}
int ProcessOptions::Parse_CL_Option(const char *&commandline, POVMSObjectPtr obj, bool singleswitch)
{
	struct INI_Parser_Table *table = parse_ini_table;
	char *value = NULL;
	char *key = NULL;
	char chr = 0;
	int err = kNoErr;

	// read the key string
	key = Parse_CL_String(commandline);
	if(key == NULL)
	{
		ParseError("Expected INI file key on command-line, no key was found.");
		return kParseErr;
	}

	// find the keyword
	while(table->keyword != NULL)
	{
		if(pov_stricmp(table->keyword, key) == 0)
			break;
		table++;
	}

	// return false if no valid keyword has been found
	if(table->keyword == NULL)
	{
		delete[] key;
		return kParseErr;
	}
	else
	{
		delete[] key;
		key = NULL;
	}

	// expect the equal sign
	if(*commandline != '=')
		return kParseErr;
	commandline++;

	// if the string is quoted, parse it matching quotes
	chr = *commandline;
	if((chr == '\"') || (chr == '\''))
	{
		commandline++;

		value = Parse_CL_String(commandline, chr);
	}
	// if there were no quotes, just read up to the next space or newline
	else if(singleswitch == false) // see if quotes had been stripped outside POV-Ray
		value = Parse_CL_String(commandline, -2);
	else
		value = Parse_CL_String(commandline, 0);

	if(value == NULL)
	{
		ParseError("Expected value on command-line, no value was found.");
		return kParseErr;
	}

	err = Process_INI_Option(table, value, obj);
	delete[] value;
	value = NULL;

	return err;
}
bool IOBase::open(const char *Name, unsigned int Flags /* = 0 */)
{
  char mode[8];

  close();

  if((Flags & append) == 0)
  {
    switch(direction)
    {
      case input:
           strcpy(mode, "r");
           break;
      case output:
           strcpy(mode, "w");
           break;
      case io:
           strcpy(mode, "w+");
           break;
      default:
        return false;
    }
  }
  else
  {
    // we cannot use append mode here, since "a" mode is totally incompatible with any
    // output file format that requires in-place updates(i.e. writing to any location
    // other than the end of the file). BMP files are in this category. In theory, "r+"
    // can do anything "a" can do(with appropriate use of seek()) so append mode should
    // not be needed.
    strcpy(mode, "r+");
  }

  strcat(mode, "b");

  f = NULL;
  if(pov_stricmp(Name, "stdin") == 0)
  {
    if(direction != input ||(Flags & append) != 0)
      return false;
    f = stdin;
  }
  else if(pov_stricmp(Name, "stdout") == 0)
  {
    if(direction != output ||(Flags & append) != 0)
      return false;
    f = stdout;
  }
  else
  {
    if((f = fopen(Name, mode)) == NULL)
    {
      if((Flags & append) == 0)
        return false;

      // to maintain traditional POV +c(continue) mode compatibility, if
      // the open for append of an existing file fails, we allow a new file
      // to be created.
      mode [0] = 'w';
      if((f = fopen(Name, mode)) == NULL)
        return false;
    }
  }
  fail = false;

  if((Flags & append) != 0)
  {
    if(!seekg(0, seek_end))
    {
      close();
      return false;
    }
  }
  
  return true;
}
Пример #8
0
int ProcessRenderOptions::ProcessUnknownString(char *str, POVMSObjectPtr obj)
{
    POVMSAttributeList list;
    POVMSAttribute attr;
    int state = 0; // INI file
    int err = kNoErr;

    if(str == NULL)
    {
        ParseError("Expected filename, nothing was found.");
        return kParseErr;
    }

    // add filename or path

    // see if it is a POV file
    if(state == 0)
    {
        char *ptr = strrchr(str, '.');
        if(ptr != NULL)
        {
            if(pov_stricmp(ptr, ".pov") == 0)
                state = 1; // POV file
        }
    }

    // see if it is a path
    if(state == 0)
    {
        if(strlen(str) > 0)
        {
            if(str[strlen(str) - 1] == FILENAME_SEPARATOR)
                state = 2; // library path
        }
    }

    switch(state)
    {
    // INI file
    case 0:
        // parse INI file (recursive)
        err = ParseFile(str, obj);
        if(err == kNoErr)
        {
            // create list if it isn't there
            if(POVMSObject_Exist(obj, kPOVAttrib_IncludeIni) == kFalseErr)
                err = POVMSAttrList_New(&list);
            else if(POVMSObject_Exist(obj, kPOVAttrib_IncludeIni) != kNoErr)
                err = kObjectAccessErr;
            else
                err = POVMSObject_Get(obj, &list, kPOVAttrib_IncludeIni);
        }

        // add INI file to list
        if(err == kNoErr)
            err = POVMSAttr_New(&attr);
        if(err == kNoErr)
        {
            err = POVMSAttr_Set(&attr, kPOVMSType_CString, str, strlen(str) + 1);
            if(err == kNoErr)
                err = POVMSAttrList_Append(&list, &attr);
            else
                err = POVMSAttr_Delete(&attr);
        }
        if(err == kNoErr)
            err = POVMSObject_Set(obj, &list, kPOVAttrib_IncludeIni);
        break;
    // POV file
    case 1:
        // set POV file
        err = POVMSUtil_SetString(obj, kPOVAttrib_InputFile, str);
        break;
    // library path
    case 2:
        // create list if it isn't there
        if(POVMSObject_Exist(obj, kPOVAttrib_LibraryPath) == kFalseErr)
            err = POVMSAttrList_New(&list);
        else if(POVMSObject_Exist(obj, kPOVAttrib_LibraryPath) != kNoErr)
            err = kObjectAccessErr;
        else
            err = POVMSObject_Get(obj, &list, kPOVAttrib_LibraryPath);

        // add librarypath to list
        if(err == kNoErr)
            err = POVMSAttr_New(&attr);
        if(err == kNoErr)
        {
            err = POVMSAttr_Set(&attr, kPOVMSType_CString, str, strlen(str) + 1);
            if(err == kNoErr)
                err = POVMSAttrList_Append(&list, &attr);
            else
                err = POVMSAttr_Delete(&attr);
        }
        if(err == kNoErr)
            err = POVMSObject_Set(obj, &list, kPOVAttrib_LibraryPath);
        break;
    }

    return err;
}
Пример #9
0
OStream::OStream(const UCS2String& name, unsigned int Flags) : IOBase(name), f(NULL)
{
    const char* mode;

    if((Flags & append) == 0)
    {
        mode = "wb";
    }
    else
    {
        // we cannot use append mode here, since "a" mode is totally incompatible with any
        // output file format that requires in-place updates(i.e. writing to any location
        // other than the end of the file). BMP files are in this category. In theory, "r+"
        // can do anything "a" can do(with appropriate use of seek()) so append mode should
        // not be needed.
        mode = "r+b";
    }

    if(pov_stricmp(UCS2toASCIIString(name).c_str(), "stdin") == 0)
    {
        f = NULL;
    }
    else if(pov_stricmp(UCS2toASCIIString(name).c_str(), "stdout") == 0)
    {
        if((Flags & append) != 0)
            f = NULL;
        else
            f = stdout;
    }
    else if(pov_stricmp(UCS2toASCIIString(name).c_str(), "stderr") == 0)
    {
        if((Flags & append) != 0)
            f = NULL;
        else
            f = stdout;
    }
    else
    {
        f = POV_UCS2_FOPEN(name, mode);
        if (f == NULL)
        {
            if((Flags & append) == 0)
                f = NULL;
            else
            {
                // to maintain traditional POV +c(continue) mode compatibility, if
                // the open for append of an existing file fails, we allow a new file
                // to be created.
                mode = "wb";
                f = POV_UCS2_FOPEN(name, mode);
            }
        }

        if (f != NULL)
        {
            if((Flags & append) != 0)
            {
                if(!seekg(0, seek_end))
                {
                    fclose(f);
                    f = NULL;
                }
            }
        }
    }

    fail = (f == NULL);
}