Пример #1
0
inline string xml_attribute::parse() const {
  string data;
  unsigned offset = 0;

  const char *source = content;
  while(*source) {
    if(*source == '&') {
      if(strbegin(source, "&lt;"))   { data[offset++] = '<';  source += 4; continue; }
      if(strbegin(source, "&gt;"))   { data[offset++] = '>';  source += 4; continue; }
      if(strbegin(source, "&amp;"))  { data[offset++] = '&';  source += 5; continue; }
      if(strbegin(source, "&apos;")) { data[offset++] = '\''; source += 6; continue; }
      if(strbegin(source, "&quot;")) { data[offset++] = '"';  source += 6; continue; }
    }

    //reject illegal characters
    if(*source == '&') return "";
    if(*source == '<') return "";
    if(*source == '>') return "";

    data[offset++] = *source++;
  }

  data[offset] = 0;
  return data;
}
Пример #2
0
inline bool xml_element::parse_head(string data) {
  data.qreplace("\t", " ");
  data.qreplace("\r", " ");
  data.qreplace("\n", " ");
  while(qstrpos(data, "  ")) data.qreplace("  ", " ");
  data.qreplace(" =", "=");
  data.qreplace("= ", "=");
  data.rtrim();

  lstring part;
  part.qsplit(" ", data);

  name = part[0];
  if(name == "") throw "...";

  for(unsigned i = 1; i < part.size(); i++) {
    lstring side;
    side.qsplit("=", part[i]);
    if(side.size() != 2) throw "...";

    xml_attribute attr;
    attr.name = side[0];
    attr.content = side[1];
    if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) attr.content.trim_once("\"");
    else if(strbegin(attr.content, "'") && strend(attr.content, "'")) attr.content.trim_once("'");
    else throw "...";
    attribute.append(attr);
  }

  return true;
}
Пример #3
0
// insert a new line just after the current one and switch to it.
//
// keep it on the same tab level by having it start off with as many
// tabs as the current line has.
//
// if cursor is before the leading tabs when we push ENTER, then the cursor
// goes to X position 0 instead of following the end of the copied tabs.
//
// if we push ENTER in the middle of a line, we split the line and add
// the rest of the line at the old cursor position to the new one.
void DoEnter(EditView *ev)
{
int ntabs;
int y = ev->cursor.y;
bool extra_indent = false;

	// record current indentation level.
	// if cursor is at or after this level, we will auto-indent the resultant line.
	ntabs = ev->curline->GetIndentationLevel();
	if (ev->cursor.x < ntabs) ntabs = 0;
	
	if (editor.settings.smart_indent_on_open)
	{
		// test if current line ends in a "{"
		if (ev->curline->GetCharAtIndex(ev->curline->GetLength() - 1) == '{')
		{
			if (ntabs > 0 || !editor.settings.no_smart_open_at_baselevel)
			{
				ntabs++;
				extra_indent = true;
			}
		}
	}
	
	// language-aware auto-indenting
	if (editor.settings.language_aware_indent && !extra_indent)
	{
		BString *bstr = ev->curline->GetLineAsString();
		const char *str = bstr->String();
		
		if (*str==TAB || *str==' ')
		{
			do { str++; } while(*str == TAB || *str == ' ');
			
			if (strbegin(str, "case ") || strbegin(str, "default:"))
			{
				ntabs++;
				extra_indent = true;
			}
		}
		
		delete bstr;
	}
	
	ev->action_insert_cr(ev->cursor.x, y);
	
	if (ntabs)
	{
		char *tabs = (char *)smal(ntabs + 1);
		memset(tabs, TAB, ntabs);
		tabs[ntabs] = 0;
		
		ev->action_insert_string(0, y + 1, tabs, NULL, NULL);
		frees(tabs);
	}
	
	ev->cursor.move(ntabs, y + 1);
}
Пример #4
0
//ensure there is only one root element
inline bool xml_validate(xml_element &document) {
  unsigned root_counter = 0;

  for(unsigned i = 0; i < document.element.size(); i++) {
    string &name = document.element[i].name;
    if(strbegin(name, "?")) continue;
    if(strbegin(name, "!")) continue;
    if(++root_counter > 1) return false;
  }

  return true;
}
Пример #5
0
char* ltrim(char *str, const char *key) {
  if(!key || !*key) return str;
  while(strbegin(str, key)) {
    char *dest = str, *src = str + strlen(key);
    while(true) {
      *dest = *src++;
      if(!*dest) break;
      dest++;
    }
  }
  return str;
}
Пример #6
0
void FileBrowser::onAcceptCartridge(const string &path) {
  string filename;
  if(QDir(path).exists()) {
    filename = resolveFilename(path);
  } else {
    filename = path;
  }

  if(file::exists(filename)) {
    close();
    config().path.current.cartridge = fileSystemModel->rootPath().toUtf8().constData();

    if(cartridgeMode == LoadDirect) {
      config().path.current.filter = filterBox->currentIndex();
      string filter = filterBox->currentText().toUtf8().constData();

      if(0);
      //file extension detection
      else if(striend(filename, ".sfc")) acceptNormal(filename);
      else if(striend(filename, ".bs"))  acceptBsx(filename);
      else if(striend(filename, ".st"))  acceptSufamiTurbo(filename);
      else if(striend(filename, ".gb"))  acceptSuperGameBoy(filename);
      else if(striend(filename, ".sgb")) acceptSuperGameBoy(filename);
      else if(striend(filename, ".gbc")) acceptSuperGameBoy(filename);
      //filter detection
      else if(strbegin(filter, "SNES cartridges")) acceptNormal(filename);
      else if(strbegin(filter, "BS-X cartridges")) acceptBsx(filename);
      else if(strbegin(filter, "Sufami Turbo cartridges")) acceptSufamiTurbo(filename);
      else if(strbegin(filter, "Game Boy cartridges")) acceptSuperGameBoy(filename);
      //fallback behavior
      else acceptNormal(filename);
    } else if(cartridgeMode == LoadBase) {
      loaderWindow->selectBaseCartridge(filename);
    } else if(cartridgeMode == LoadSlot1) {
      loaderWindow->selectSlot1Cartridge(filename);
    } else if(cartridgeMode == LoadSlot2) {
      loaderWindow->selectSlot2Cartridge(filename);
    }
  }
}
Пример #7
0
 static uint16_t decode(const char *name) {
   string s(name);
   if(!strbegin(name, "KB")) return 0;
   ltrim(s, "KB");
   unsigned id = strunsigned(s);
   auto pos = strpos(s, "::");
   if(!pos) return 0;
   s = substr(s, pos() + 2);
   for(unsigned i = 0; i < Limit; i++) {
     if(s == KeyboardScancodeName[i]) return Base + Size * id + i;
   }
   return 0;
 }
Пример #8
0
 static uint16_t decode(const char *name) {
   string s(name);
   if(!strbegin(name, "JP")) return 0;
   ltrim(s, "JP");
   unsigned id = strunsigned(s);
   int pos = strpos(s, "::");
   if(pos < 0) return 0;
   s = substr(s, pos + 2);
   for(unsigned i = 0; i < Limit; i++) {
     if(s == JoypadScancodeName[i]) return Base + Size * id + i;
   }
   return 0;
 }
Пример #9
0
//limit defaults to zero, which will underflow on first compare; equivalent to no limit
template<unsigned Limit> char* ltrim(char *str, const char *key) {
  unsigned limit = Limit;
  if(!key || !*key) return str;
  while(strbegin(str, key)) {
    char *dest = str, *src = str + strlen(key);
    while(true) {
      *dest = *src++;
      if(!*dest) break;
      dest++;
    }
    if(--limit == 0) break;
  }
  return str;
}
Пример #10
0
    string operator[](const char *input) {
      for(unsigned i = 0; i < index_input.size(); i++) {
        if(index_input[i] == input) return index_output[i];
      }

      //no match, use input; remove input identifier, if one exists
      if(strbegin(input, "{{")) {
        if(optional<unsigned> pos = strpos(input, "}}")) {
          string temp = substr(input, pos() + 2);
          return temp;
        }
      }

      return input;
    }
Пример #11
0
int main(int argc, char **argv) {
	xkas::Format format = xkas::format_bin;
	string outputFilename, exportFilename;
	lstring inputFilename;

	for(unsigned i = 1; i < argc; i++) {
		if(!strcmp(argv[i], "-o") && argc >= i + 1) {
			outputFilename = argv[++i];
		
		} else if(!strcmp(argv[i], "-e") && argc >= i + 1) {
			exportFilename = argv[++i];
		
		} else if (!strcmp(argv[i], "-ips")) {
			format = xkas::format_IPS;
		
		} else if(!strbegin(argv[i], "-")) {
			inputFilename.append(argv[i]);
		
		} else {
			print("unrecognized option: ", argv[i], "\n");
			return 1;
		}
	}

	if(outputFilename == "" || inputFilename.size() == 0) {
		print("xkas-plus v14+1\n");
		print("usage: xkas -o output.bin input.asm\n");
		return 0;
	}

	xkas as;
	unsigned err = 0;
	as.open(outputFilename, format);
	foreach(filename, inputFilename) {
		if(as.assemble(filename) == false) {
		  err = 1;
		  break;
		}
	}
	if (!err && exportFilename != "") {
		as.exportFile(exportFilename);
	}
	as.close();
	return err;
}
Пример #12
0
inline string xml_element::parse() const {
  string data;
  unsigned offset = 0;

  const char *source = content;
  while(*source) {
    if(*source == '&') {
      if(strbegin(source, "&lt;"))   { data[offset++] = '<';  source += 4; continue; }
      if(strbegin(source, "&gt;"))   { data[offset++] = '>';  source += 4; continue; }
      if(strbegin(source, "&amp;"))  { data[offset++] = '&';  source += 5; continue; }
      if(strbegin(source, "&apos;")) { data[offset++] = '\''; source += 6; continue; }
      if(strbegin(source, "&quot;")) { data[offset++] = '"';  source += 6; continue; }
    }

    if(strbegin(source, "<!--")) {
      if(optional<unsigned> pos = strpos(source, "-->")) {
        source += pos() + 3;
        continue;
      } else {
        return "";
      }
    }

    if(strbegin(source, "<![CDATA[")) {
      if(optional<unsigned> pos = strpos(source, "]]>")) {
        string cdata = substr(source, 9, pos() - 9);
        data << cdata;
        offset += strlen(cdata);

        source += offset + 3;
        continue;
      } else {
        return "";
      }
    }

    //reject illegal characters
    if(*source == '&') return "";
    if(*source == '<') return "";
    if(*source == '>') return "";

    data[offset++] = *source++;
  }

  data[offset] = 0;
  return data;
}
Пример #13
0
/**  
 *  setstr:
 *  @buf:		The non tabbed prefixed, null terminated string
 *  @str:		The strings to compare with e.g. "Vendor:"
 *  @prop:		The HAL property to set
 *
 *  Return		TRUE is found, FALSE otherwise.
 *
 *  Finds the start of a null terminated string and sets HAL property if valid.
 */
static int
setstr (char *buf, char *str, char *prop)
{
	DBusError error;
	char *value;

	if (strbegin (buf, str)) {
		dbus_error_init (&error);
		value = buf + strlen (str) + 1;
		if (strcmp (value, "Not Specified") == 0)
			goto out;

		libhal_device_set_property_string (hfp_ctx, hfp_udi, prop, value, &hfp_error);
		LIBHAL_FREE_DBUS_ERROR (&hfp_error);
		hfp_info ("Setting %s='%s'", prop, value);
		return TRUE;
	}
out:
	return FALSE;
}
Пример #14
0
//ensure file path is absolute (eg resolve relative paths)
string Cartridge::filepath(const char *filename, const char *pathname) {
  //if no pathname, return filename as-is
  string file(filename);
  file.replace("\\", "/");

  string path = (!pathname || !*pathname) ? (const char*)snes.config.path.current : pathname;
  //ensure path ends with trailing '/'
  path.replace("\\", "/");
  if(!strend(path, "/")) path.append("/");

  //replace relative path with absolute path
  if(strbegin(path, "./")) {
    ltrim(path, "./");
    path = string() << snes.config.path.base << path;
  }

  //remove folder part of filename
  lstring part;
  part.split("/", file);
  return path << part[part.size() - 1];
}
Пример #15
0
FILE* sec_fopen(char *path, char *mode)
{
	char *rpath=realpath(path,NULL);
	char *spath=sec_path(NULL);
	FILE *ret=NULL;

	log_write(LOG_DBG, "Trying to access %s -> %s", path, rpath);


	if(rpath!=NULL && spath!=NULL && strbegin(rpath, spath)==0)
	{
		ret=fopen(rpath, mode);
		nfree(rpath);
	}
	else
	{
		log_write(LOG_INFO, "Prevented access to %s", path);
		nfree(rpath);
	}

	return ret;
}
Пример #16
0
/** 
 *  setstr:
 *  @buf:		The non tabbed prefixed, null terminated string
 *  @str:		The strings to compare with e.g. "Vendor:"
 *  @prop:		The HAL property to set
 *
 *  Returns:		TRUE is found, FALSE otherwise.
 *
 *  Finds the start of a null terminated string and sets HAL
 *  property if valid.
 */
static int
setstr (char *buf, char *str, char *prop)
{
	DBusError error;
	char *value;

	if (str == NULL)
		goto out;

	if (strbegin (buf, str)) {
		dbus_error_init (&error);
		value = buf + strlen (str) + 1;
		if (strcmp (value, "Not Specified") == 0)
			goto out;

		if (!libhal_device_set_property_string (ctx, udi, prop, value, &error))
			dbus_error_init (&error);

		HAL_DEBUG (("Setting %s='%s'", prop, value));
		return TRUE;
	}
out:
	return FALSE;
}
Пример #17
0
/** 
 *  main:
 *  @argc:	Number of arguments given to program
 *  @argv:	Arguments given to program
 *  Returns:	Return code
 *
 *  Main entry point
 */
int
main (int argc, char *argv[])
{
	int ret;
	char buf[512];
	char *nbuf;
	int dmipipe[2];
	int nullfd;
	int tmp_ret;
	FILE *f;
	int dmiparser_state = DMIPARSER_STATE_IGNORE;

	/* on some system chassis pops up several times,
	 * so only take the first entry for each
	 */
	int dmiparser_done_bios = FALSE;
	int dmiparser_done_system = FALSE;
	int dmiparser_done_chassis = FALSE;

	/* assume failure */
	ret = 1;

	if (! hfp_init (argc, argv))
	  goto out;

	tmp_ret = pipe (dmipipe);
	f = fdopen (dmipipe[0], "r");
	nullfd = open ("/dev/null", O_RDONLY);

	/* fork the child process */
	switch (fork ()) {
	case 0:
		/* child */

		dup2 (nullfd, STDIN_FILENO);
		dup2 (dmipipe[1], STDOUT_FILENO);
		close (dmipipe[0]);
		close (dmipipe[1]);

		/* execute the child */
		execl (DMIDECODE, DMIDECODE, NULL);

		/* throw an error if we ever reach this point */
		hfp_warning("failed to execute " DMIDECODE);
		exit (1);
		break;
	case -1:
		hfp_warning("cannot fork");
		break;
	}

	/* parent continues from here */

	/* close unused descriptor */
	close (dmipipe[1]);

	/* read the output of the child */
	while(fgets (buf, sizeof(buf), f) != NULL)
	{
		unsigned int i;
		unsigned int len;
		unsigned int tabs = 0;

		/* trim whitespace */
		len = strlen (buf);

		/* check that will fit in buffer */
		if (len >= sizeof (buf))
			continue;

		/* not big enough for data, and protects us from underflow */
		if (len < 3) {
			dmiparser_state = DMIPARSER_STATE_IGNORE;
			continue;
		}

		/* find out number of leading tabs */
		if (buf[0] == '\t' && buf[1] == '\t')
			tabs = 2; /* this is list data */
		else if (buf[0] == '\t')
			tabs = 1; /* this is data, 0 is section type */

		if (tabs == 2)
			/* we do not proccess data at depth 2 */
			continue;

		/* set the section type */
		if (tabs == 0) {
			if (!dmiparser_done_bios && strbegin (buf, "BIOS Information"))
				dmiparser_state = DMIPARSER_STATE_BIOS;
			else if (!dmiparser_done_system && strbegin (buf, "System Information"))
				dmiparser_state = DMIPARSER_STATE_SYSTEM;
			else if (!dmiparser_done_chassis && strbegin (buf, "Chassis Information"))
				dmiparser_state = DMIPARSER_STATE_CHASSIS;
			else
				/*
				 * We do not match the other sections,
				 * or sections we have processed before
				 */
				dmiparser_state = DMIPARSER_STATE_IGNORE;
			continue; /* next line */
		}

		/* we are not in a section we know, no point continueing */
		if (dmiparser_state == DMIPARSER_STATE_IGNORE)
			continue;

		/* removes the leading tab */
		nbuf = &buf[1];

		/* removes the trailing spaces */
		for (i = len - 2; isspace (nbuf[i]) && i >= 0; --i)
			nbuf[i] = '\0';

		if (dmiparser_state == DMIPARSER_STATE_BIOS) {
			setstr (nbuf, "Vendor:", "system.firmware.vendor");
			setstr (nbuf, "Version:", "system.firmware.version");
			setstr (nbuf, "Release Date:", "system.firmware.release_date");
			dmiparser_done_bios = TRUE;
		} else if (dmiparser_state == DMIPARSER_STATE_SYSTEM) {
			setstr (nbuf, "Manufacturer:", "system.hardware.vendor");
			setstr (nbuf, "Product Name:", "system.hardware.product");
			setstr (nbuf, "Version:", "system.hardware.version");
			setstr (nbuf, "Serial Number:", "system.hardware.serial");
			setstr (nbuf, "UUID:", "system.hardware.uuid");
			dmiparser_done_system = TRUE;
		} else if (dmiparser_state == DMIPARSER_STATE_CHASSIS) {
			setstr (nbuf, "Manufacturer:", "system.chassis.manufacturer");
			setstr (nbuf, "Type:", "system.chassis.type");
			dmiparser_done_chassis = TRUE;
		}
	}

	/* as read to EOF, close */
	fclose (f);

	/* return success */
	ret = 0;

out:
	return ret;
}
Пример #18
0
bool string::beginswith(const char *str) const { return strbegin(data, str); }
Пример #19
0
bool gen_table(void)
{
FILE *fp, *fpo;
char line[1024];
int nobjects = -1;
int count = 0;

	printf("regenerating object-names table...\n");
	
	fp = fopen(infile, "rb");
	if (!fp)
	{
		fprintf(stderr, "<Cannot open object.h>\n");
		return 1;
	}
	
	fpo = fopen(outfile, "wb");
	if (!fpo)
	{
		fprintf(stderr, "<Cannot open objnames.cpp>\n");
		fclose(fp);
		return 1;
	}
	
	memset(nametable, 0, sizeof(nametable));
	
	while(!feof(fp))
	{
		fgetline(fp, line, sizeof(line));
		
		if (strbegin(line, "#define OBJ_"))
		{
			char *ptr = strstr(line, "//");
			if (ptr) *ptr = 0;
			
			strtok(line, " \t");
			const char *obj_name = strtok(NULL, " \t");
			const char *obj_number_str = strtok(NULL, " \t");
			int obj_number;
			
			if (obj_name && obj_number_str && (obj_number = atoi(obj_number_str)))
			{
				if (!strcmp(obj_name, "OBJ_LAST"))
				{
					nobjects = obj_number;
				}
				else
				{
					//printf("obj_name: %s   obj_number: %d\n", obj_name, obj_number);
					nametable[obj_number] = strdup(&obj_name[4]);
					count++;
				}
			}
		}
	}
	
	if (nobjects == -1)
	{
		fprintf(stderr, "Couldn't find OBJ_LAST\n");
		fclose(fp);
		fclose(fpo);
		return 1;
	}
	
	fprintf(fpo, "\n// auto-generated by genobjnametable.cpp\n");
	fprintf(fpo, "#include <stdio.h>\n");
	fprintf(fpo, "\nconst char *object_names[] = {\n");
	
	for(int i=0;i<nobjects;i++)
	{
		if (nametable[i])
		{
			fprintf(fpo, "\t\"%s\"", nametable[i]);
			free(nametable[i]);
		}
		else
		{
			fprintf(fpo, "\tNULL");
		}
		
		if (i+1 != nobjects)
			fprintf(fpo, ",\n");
		else
			fprintf(fpo, "\n");
	}
	
	fprintf(fpo, "};\n");
	printf("wrote %d objects in a space of %d\n", count, nobjects);
	
	fclose(fp);
	fclose(fpo);
	return 0;
}
Пример #20
0
inline bool xml_element::parse_body(const char *&data) {
  while(true) {
    if(!*data) return false;
    if(*data++ != '<') continue;
    if(*data == '/') return false;

    if(strbegin(data, "!DOCTYPE") == true) {
      parse_doctype(data);
      return true;
    }

    if(strbegin(data, "!--")) {
      if(optional<unsigned> offset = strpos(data, "-->")) {
        data += offset() + 3;
        continue;
      } else {
        throw "...";
      }
    }

    if(strbegin(data, "![CDATA[")) {
      if(optional<unsigned> offset = strpos(data, "]]>")) {
        data += offset() + 3;
        continue;
      } else {
        throw "...";
      }
    }

    optional<unsigned> offset = strpos(data, ">");
    if(!offset) throw "...";

    string tag = substr(data, 0, offset());
    data += offset() + 1;
    const char *content_begin = data;

    bool self_terminating = false;

    if(strend(tag, "?") == true) {
      self_terminating = true;
      tag.rtrim_once("?");
    } else if(strend(tag, "/") == true) {
      self_terminating = true;
      tag.rtrim_once("/");
    }

    parse_head(tag);
    if(self_terminating) return true;

    while(*data) {
      unsigned index = element.size();
      xml_element node;
      if(node.parse_body(data) == false) {
        if(*data == '/') {
          signed length = data - content_begin - 1;
          if(length > 0) content = substr(content_begin, 0, length);

          data++;
          optional<unsigned> offset = strpos(data, ">");
          if(!offset) throw "...";

          tag = substr(data, 0, offset());
          data += offset() + 1;

          tag.replace("\t", " ");
          tag.replace("\r", " ");
          tag.replace("\n", " ");
          while(strpos(tag, "  ")) tag.replace("  ", " ");
          tag.rtrim();

          if(name != tag) throw "...";
          return true;
        }
      } else {
        element.append(node);
      }
    }
  }
}
Пример #21
0
char* ltrim(char *str, const char *key) {
  if(!key || !*key) return str;
  while(strbegin(str, key)) strcpy(str, str + strlen(key));
  return str;
}
Пример #22
0
/** 
 *  main:
 *  @argc:	Number of arguments given to program
 *  @argv:	Arguments given to program
 *
 *  Returns: 	Return code
 * 
 *  Main entry point
 */
int 
main (int argc, char *argv[])
{
	int ret;
	DBusError error;
	char buf[512];
	char *nbuf;
	int dmipipe[2];
	int nullfd;
	FILE *f;
	int dmiparser_state = DMIPARSER_STATE_IGNORE;

	/* on some system chassis pops up several times,
	 * so only take the first entry for each
	 */
	int dmiparser_done_bios = FALSE;
	int dmiparser_done_system = FALSE;
	int dmiparser_done_chassis = FALSE;

	uint i;
	struct stat s;
	const char *path = NULL;
	const char *possible_paths[] = {
		"/usr/sbin/dmidecode",
		"/bin/dmidecode",
		"/sbin/dmidecode",
		"/usr/local/sbin/dmidecode",
        };

	/* assume failure */
	ret = 1;

	setup_logger ();

	dbus_error_init (&error);
	
	udi = getenv ("UDI");
	if (udi == NULL) {
		HAL_ERROR (("UDI not set"));
		goto out;
	}

	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
		HAL_ERROR (("ctx init failed"));
		goto out;
	}


	/* find the path to dmidecode */
        for (i = 0; i < sizeof (possible_paths) / sizeof (char *); i++) {
                if (stat (possible_paths[i], &s) == 0 && S_ISREG (s.st_mode)) {
                        path = possible_paths[i];
                        break;
                }
        }

        if (path == NULL) {
                HAL_ERROR(("Could not find dmidecode, exit!"));
		exit(1);
	}

	if(pipe (dmipipe) == -1) {
		HAL_ERROR(("Could not create pipe (error: '%s'), exit!", strerror(errno)));
		exit(1);
	}	

	if ((f = fdopen (dmipipe[0], "r")) == NULL) {
		HAL_ERROR(("Could not open file (error: '%s'), exit!", strerror(errno)));
		exit(1);
	}

	if ((nullfd = open ("/dev/null", O_RDONLY)) == -1){
		HAL_ERROR(("Could not open /dev/null (error: '%s'), exit!", strerror(errno)));
		exit(1);
	}
	
	/* fork the child process */
	switch (fork ()) {
	case 0:
		/* child */
		
		dup2 (nullfd, STDIN_FILENO);
		dup2 (dmipipe[1], STDOUT_FILENO);
		close (dmipipe[0]);
		close (dmipipe[1]);
		
		/* execute the child */
		execl (path, path, NULL);
		
		/* throw an error if we ever reach this point */
		HAL_ERROR (("Failed to execute dmidecode!"));
		exit (1);
		break;
	case -1:
		HAL_ERROR (("Cannot fork!"));
		goto out;
	}
	
	/* parent continues from here */
	
	/* close unused descriptor */
	close (dmipipe[1]);
	
	/* read the output of the child */
	while(fgets (buf, sizeof(buf), f) != NULL)
	{
		int j;
		unsigned int len;
		unsigned int tabs = 0;

		/* trim whitespace */
		len = strlen (buf);

		/* check that will fit in buffer */
		if (len >= sizeof (buf))
			continue;

		/* not big enough for data, and protects us from underflow */
		if (len < 3) {
			dmiparser_state = DMIPARSER_STATE_IGNORE;
			continue;
		}

		/* find out number of leading tabs */
		if (buf[0] == '\t' && buf[1] == '\t')
			tabs = 2; /* this is list data */
		else if (buf[0] == '\t')
			tabs = 1; /* this is data, 0 is section type */

		if (tabs == 2)
			/* we do not proccess data at depth 2 */
			continue;
			
		/* set the section type */
		if (tabs == 0) {
			if (!dmiparser_done_bios && strbegin (buf, "BIOS Information"))
				dmiparser_state = DMIPARSER_STATE_BIOS;
			else if (!dmiparser_done_system && strbegin (buf, "System Information"))
				dmiparser_state = DMIPARSER_STATE_SYSTEM;
			else if (!dmiparser_done_chassis && strbegin (buf, "Chassis Information"))
				dmiparser_state = DMIPARSER_STATE_CHASSIS;
			else if (!dmiparser_done_chassis && strbegin (buf, "Base Board Information"))
				dmiparser_state = DMIPARSER_STATE_BOARD;
			else
				/*
				 * We do not match the other sections,
				 * or sections we have processed before
				 */
				dmiparser_state = DMIPARSER_STATE_IGNORE;
			continue; /* next line */
		}

		/* we are not in a section we know, no point continueing */
		if (dmiparser_state == DMIPARSER_STATE_IGNORE)
			continue;

		/* return success only if there was something usefull to parse */
		ret = 0;


		/* removes the leading tab */
		nbuf = &buf[1];

		/* removes the trailing spaces */
		for (j = len - 2; isspace (nbuf[j]) && j >= 0; --j)
			nbuf[j] = '\0';

		if (dmiparser_state == DMIPARSER_STATE_BIOS) {
			setstr (nbuf, "Vendor:", "system.firmware.vendor");
			setstr (nbuf, "Version:", "system.firmware.version");
			setstr (nbuf, "Release Date:", "system.firmware.release_date");
			dmiparser_done_bios = TRUE;
		} else if (dmiparser_state == DMIPARSER_STATE_SYSTEM) {
			setstr (nbuf, "Manufacturer:", "system.hardware.vendor");
			setstr (nbuf, "Product Name:", "system.hardware.product");
			setstr (nbuf, "Version:", "system.hardware.version");
			setstr (nbuf, "Serial Number:", "system.hardware.serial");
			setstr (nbuf, "UUID:", "system.hardware.uuid");
			dmiparser_done_system = TRUE;
		} else if (dmiparser_state == DMIPARSER_STATE_CHASSIS) {
			setstr (nbuf, "Manufacturer:", "system.chassis.manufacturer");
			setstr (nbuf, "Type:", "system.chassis.type");
			dmiparser_done_chassis = TRUE;
		} else if (dmiparser_state == DMIPARSER_STATE_BOARD) {
			setstr (nbuf, "Manufacturer:", "system.board.vendor");
			setstr (nbuf, "Product Name:", "system.board.product");
			setstr (nbuf, "Version:", "system.board.version");
			setstr (nbuf, "Serial Number:", "system.board.serial");
			dmiparser_done_system = TRUE;
		}
	}

	/* as read to EOF, close */
	fclose (f);

out:
	LIBHAL_FREE_DBUS_ERROR (&error);

	/* free ctx */
	if (ctx != NULL) {
		libhal_ctx_shutdown (ctx, &error);
		LIBHAL_FREE_DBUS_ERROR (&error);
		libhal_ctx_free (ctx);
	}

	return ret;
}