]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - scripts/dtc/util.c
dtc: import latest upstream dtc
[karo-tx-linux.git] / scripts / dtc / util.c
index d7ac27d2ae15469d09e476d4193d120e6ac97f6b..2422c34e11dfd381b26d11c1fec39d9369b17d62 100644 (file)
@@ -1,6 +1,10 @@
 /*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
  *
+ * util_is_printable_string contributed by
+ *     Pantelis Antoniou <pantelis.antoniou AT gmail.com>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  *                                                                   USA
  */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
+#include <assert.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
 
+#include "libfdt.h"
 #include "util.h"
 
 char *xstrdup(const char *s)
@@ -57,3 +68,264 @@ char *join_path(const char *path, const char *name)
        memcpy(str+lenp, name, lenn+1);
        return str;
 }
+
+int util_is_printable_string(const void *data, int len)
+{
+       const char *s = data;
+       const char *ss;
+
+       /* zero length is not */
+       if (len == 0)
+               return 0;
+
+       /* must terminate with zero */
+       if (s[len - 1] != '\0')
+               return 0;
+
+       ss = s;
+       while (*s && isprint(*s))
+               s++;
+
+       /* not zero, or not done yet */
+       if (*s != '\0' || (s + 1 - ss) < len)
+               return 0;
+
+       return 1;
+}
+
+/*
+ * Parse a octal encoded character starting at index i in string s.  The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_oct_char(const char *s, int *i)
+{
+       char x[4];
+       char *endx;
+       long val;
+
+       x[3] = '\0';
+       strncpy(x, s + *i, 3);
+
+       val = strtol(x, &endx, 8);
+
+       assert(endx > x);
+
+       (*i) += endx - x;
+       return val;
+}
+
+/*
+ * Parse a hexadecimal encoded character starting at index i in string s.  The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_hex_char(const char *s, int *i)
+{
+       char x[3];
+       char *endx;
+       long val;
+
+       x[2] = '\0';
+       strncpy(x, s + *i, 2);
+
+       val = strtol(x, &endx, 16);
+       if (!(endx  > x))
+               die("\\x used with no following hex digits\n");
+
+       (*i) += endx - x;
+       return val;
+}
+
+char get_escape_char(const char *s, int *i)
+{
+       char    c = s[*i];
+       int     j = *i + 1;
+       char    val;
+
+       assert(c);
+       switch (c) {
+       case 'a':
+               val = '\a';
+               break;
+       case 'b':
+               val = '\b';
+               break;
+       case 't':
+               val = '\t';
+               break;
+       case 'n':
+               val = '\n';
+               break;
+       case 'v':
+               val = '\v';
+               break;
+       case 'f':
+               val = '\f';
+               break;
+       case 'r':
+               val = '\r';
+               break;
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+               j--; /* need to re-read the first digit as
+                     * part of the octal value */
+               val = get_oct_char(s, &j);
+               break;
+       case 'x':
+               val = get_hex_char(s, &j);
+               break;
+       default:
+               val = c;
+       }
+
+       (*i) = j;
+       return val;
+}
+
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+       int fd = 0;     /* assume stdin */
+       char *buf = NULL;
+       off_t bufsize = 1024, offset = 0;
+       int ret = 0;
+
+       *buffp = NULL;
+       if (strcmp(filename, "-") != 0) {
+               fd = open(filename, O_RDONLY);
+               if (fd < 0)
+                       return errno;
+       }
+
+       /* Loop until we have read everything */
+       buf = malloc(bufsize);
+       do {
+               /* Expand the buffer to hold the next chunk */
+               if (offset == bufsize) {
+                       bufsize *= 2;
+                       buf = realloc(buf, bufsize);
+                       if (!buf) {
+                               ret = ENOMEM;
+                               break;
+                       }
+               }
+
+               ret = read(fd, &buf[offset], bufsize - offset);
+               if (ret < 0) {
+                       ret = errno;
+                       break;
+               }
+               offset += ret;
+       } while (ret != 0);
+
+       /* Clean up, including closing stdin; return errno on error */
+       close(fd);
+       if (ret)
+               free(buf);
+       else
+               *buffp = buf;
+       return ret;
+}
+
+char *utilfdt_read(const char *filename)
+{
+       char *buff;
+       int ret = utilfdt_read_err(filename, &buff);
+
+       if (ret) {
+               fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
+                       strerror(ret));
+               return NULL;
+       }
+       /* Successful read */
+       return buff;
+}
+
+int utilfdt_write_err(const char *filename, const void *blob)
+{
+       int fd = 1;     /* assume stdout */
+       int totalsize;
+       int offset;
+       int ret = 0;
+       const char *ptr = blob;
+
+       if (strcmp(filename, "-") != 0) {
+               fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+               if (fd < 0)
+                       return errno;
+       }
+
+       totalsize = fdt_totalsize(blob);
+       offset = 0;
+
+       while (offset < totalsize) {
+               ret = write(fd, ptr + offset, totalsize - offset);
+               if (ret < 0) {
+                       ret = -errno;
+                       break;
+               }
+               offset += ret;
+       }
+       /* Close the file/stdin; return errno on error */
+       if (fd != 1)
+               close(fd);
+       return ret < 0 ? -ret : 0;
+}
+
+
+int utilfdt_write(const char *filename, const void *blob)
+{
+       int ret = utilfdt_write_err(filename, blob);
+
+       if (ret) {
+               fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
+                       strerror(ret));
+       }
+       return ret ? -1 : 0;
+}
+
+int utilfdt_decode_type(const char *fmt, int *type, int *size)
+{
+       int qualifier = 0;
+
+       if (!*fmt)
+               return -1;
+
+       /* get the conversion qualifier */
+       *size = -1;
+       if (strchr("hlLb", *fmt)) {
+               qualifier = *fmt++;
+               if (qualifier == *fmt) {
+                       switch (*fmt++) {
+/* TODO:               case 'l': qualifier = 'L'; break;*/
+                       case 'h':
+                               qualifier = 'b';
+                               break;
+                       }
+               }
+       }
+
+       /* we should now have a type */
+       if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+               return -1;
+
+       /* convert qualifier (bhL) to byte size */
+       if (*fmt != 's')
+               *size = qualifier == 'b' ? 1 :
+                               qualifier == 'h' ? 2 :
+                               qualifier == 'l' ? 4 : -1;
+       *type = *fmt++;
+
+       /* that should be it! */
+       if (*fmt)
+               return -1;
+       return 0;
+}