symbian-qemu-0.9.1-12/dtc-trunk/data.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
       
     3  *
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU General Public License as
       
     7  * published by the Free Software Foundation; either version 2 of the
       
     8  * License, or (at your option) any later version.
       
     9  *
       
    10  *  This program is distributed in the hope that it will be useful,
       
    11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  *  General Public License for more details.
       
    14  *
       
    15  *  You should have received a copy of the GNU General Public License
       
    16  *  along with this program; if not, write to the Free Software
       
    17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
       
    18  *                                                                   USA
       
    19  */
       
    20 
       
    21 #include "dtc.h"
       
    22 
       
    23 void data_free(struct data d)
       
    24 {
       
    25 	struct marker *m, *nm;
       
    26 
       
    27 	m = d.markers;
       
    28 	while (m) {
       
    29 		nm = m->next;
       
    30 		free(m->ref);
       
    31 		free(m);
       
    32 		m = nm;
       
    33 	}
       
    34 
       
    35 	if (d.val)
       
    36 		free(d.val);
       
    37 }
       
    38 
       
    39 struct data data_grow_for(struct data d, int xlen)
       
    40 {
       
    41 	struct data nd;
       
    42 	int newsize;
       
    43 
       
    44 	if (xlen == 0)
       
    45 		return d;
       
    46 
       
    47 	nd = d;
       
    48 
       
    49 	newsize = xlen;
       
    50 
       
    51 	while ((d.len + xlen) > newsize)
       
    52 		newsize *= 2;
       
    53 
       
    54 	nd.val = xrealloc(d.val, newsize);
       
    55 
       
    56 	return nd;
       
    57 }
       
    58 
       
    59 struct data data_copy_mem(const char *mem, int len)
       
    60 {
       
    61 	struct data d;
       
    62 
       
    63 	d = data_grow_for(empty_data, len);
       
    64 
       
    65 	d.len = len;
       
    66 	memcpy(d.val, mem, len);
       
    67 
       
    68 	return d;
       
    69 }
       
    70 
       
    71 static char get_oct_char(const char *s, int *i)
       
    72 {
       
    73 	char x[4];
       
    74 	char *endx;
       
    75 	long val;
       
    76 
       
    77 	x[3] = '\0';
       
    78 	strncpy(x, s + *i, 3);
       
    79 
       
    80 	val = strtol(x, &endx, 8);
       
    81 
       
    82 	assert(endx > x);
       
    83 
       
    84 	(*i) += endx - x;
       
    85 	return val;
       
    86 }
       
    87 
       
    88 static char get_hex_char(const char *s, int *i)
       
    89 {
       
    90 	char x[3];
       
    91 	char *endx;
       
    92 	long val;
       
    93 
       
    94 	x[2] = '\0';
       
    95 	strncpy(x, s + *i, 2);
       
    96 
       
    97 	val = strtol(x, &endx, 16);
       
    98 	if (!(endx  > x))
       
    99 		die("\\x used with no following hex digits\n");
       
   100 
       
   101 	(*i) += endx - x;
       
   102 	return val;
       
   103 }
       
   104 
       
   105 struct data data_copy_escape_string(const char *s, int len)
       
   106 {
       
   107 	int i = 0;
       
   108 	struct data d;
       
   109 	char *q;
       
   110 
       
   111 	d = data_grow_for(empty_data, strlen(s)+1);
       
   112 
       
   113 	q = d.val;
       
   114 	while (i < len) {
       
   115 		char c = s[i++];
       
   116 
       
   117 		if (c != '\\') {
       
   118 			q[d.len++] = c;
       
   119 			continue;
       
   120 		}
       
   121 
       
   122 		c = s[i++];
       
   123 		assert(c);
       
   124 		switch (c) {
       
   125 		case 'a':
       
   126 			q[d.len++] = '\a';
       
   127 			break;
       
   128 		case 'b':
       
   129 			q[d.len++] = '\b';
       
   130 			break;
       
   131 		case 't':
       
   132 			q[d.len++] = '\t';
       
   133 			break;
       
   134 		case 'n':
       
   135 			q[d.len++] = '\n';
       
   136 			break;
       
   137 		case 'v':
       
   138 			q[d.len++] = '\v';
       
   139 			break;
       
   140 		case 'f':
       
   141 			q[d.len++] = '\f';
       
   142 			break;
       
   143 		case 'r':
       
   144 			q[d.len++] = '\r';
       
   145 			break;
       
   146 		case '0':
       
   147 		case '1':
       
   148 		case '2':
       
   149 		case '3':
       
   150 		case '4':
       
   151 		case '5':
       
   152 		case '6':
       
   153 		case '7':
       
   154 			i--; /* need to re-read the first digit as
       
   155 			      * part of the octal value */
       
   156 			q[d.len++] = get_oct_char(s, &i);
       
   157 			break;
       
   158 		case 'x':
       
   159 			q[d.len++] = get_hex_char(s, &i);
       
   160 			break;
       
   161 		default:
       
   162 			q[d.len++] = c;
       
   163 		}
       
   164 	}
       
   165 
       
   166 	q[d.len++] = '\0';
       
   167 	return d;
       
   168 }
       
   169 
       
   170 struct data data_copy_file(FILE *f, size_t maxlen)
       
   171 {
       
   172 	struct data d = empty_data;
       
   173 
       
   174 	while (!feof(f) && (d.len < maxlen)) {
       
   175 		size_t chunksize, ret;
       
   176 
       
   177 		if (maxlen == -1)
       
   178 			chunksize = 4096;
       
   179 		else
       
   180 			chunksize = maxlen - d.len;
       
   181 
       
   182 		d = data_grow_for(d, chunksize);
       
   183 		ret = fread(d.val + d.len, 1, chunksize, f);
       
   184 
       
   185 		if (ferror(f))
       
   186 			die("Error reading file into data: %s", strerror(errno));
       
   187 
       
   188 		if (d.len + ret < d.len)
       
   189 			die("Overflow reading file into data\n");
       
   190 
       
   191 		d.len += ret;
       
   192 	}
       
   193 
       
   194 	return d;
       
   195 }
       
   196 
       
   197 struct data data_append_data(struct data d, const void *p, int len)
       
   198 {
       
   199 	d = data_grow_for(d, len);
       
   200 	memcpy(d.val + d.len, p, len);
       
   201 	d.len += len;
       
   202 	return d;
       
   203 }
       
   204 
       
   205 struct data data_insert_at_marker(struct data d, struct marker *m,
       
   206 				  const void *p, int len)
       
   207 {
       
   208 	d = data_grow_for(d, len);
       
   209 	memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
       
   210 	memcpy(d.val + m->offset, p, len);
       
   211 	d.len += len;
       
   212 
       
   213 	/* Adjust all markers after the one we're inserting at */
       
   214 	m = m->next;
       
   215 	for_each_marker(m)
       
   216 		m->offset += len;
       
   217 	return d;
       
   218 }
       
   219 
       
   220 struct data data_append_markers(struct data d, struct marker *m)
       
   221 {
       
   222 	struct marker **mp = &d.markers;
       
   223 
       
   224 	/* Find the end of the markerlist */
       
   225 	while (*mp)
       
   226 		mp = &((*mp)->next);
       
   227 	*mp = m;
       
   228 	return d;
       
   229 }
       
   230 
       
   231 struct data data_merge(struct data d1, struct data d2)
       
   232 {
       
   233 	struct data d;
       
   234 	struct marker *m2 = d2.markers;
       
   235 
       
   236 	d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
       
   237 
       
   238 	/* Adjust for the length of d1 */
       
   239 	for_each_marker(m2)
       
   240 		m2->offset += d1.len;
       
   241 
       
   242 	d2.markers = NULL; /* So data_free() doesn't clobber them */
       
   243 	data_free(d2);
       
   244 
       
   245 	return d;
       
   246 }
       
   247 
       
   248 struct data data_append_cell(struct data d, cell_t word)
       
   249 {
       
   250 	cell_t beword = cpu_to_fdt32(word);
       
   251 
       
   252 	return data_append_data(d, &beword, sizeof(beword));
       
   253 }
       
   254 
       
   255 struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
       
   256 {
       
   257 	struct fdt_reserve_entry bere;
       
   258 
       
   259 	bere.address = cpu_to_fdt64(re->address);
       
   260 	bere.size = cpu_to_fdt64(re->size);
       
   261 
       
   262 	return data_append_data(d, &bere, sizeof(bere));
       
   263 }
       
   264 
       
   265 struct data data_append_addr(struct data d, uint64_t addr)
       
   266 {
       
   267 	uint64_t beaddr = cpu_to_fdt64(addr);
       
   268 
       
   269 	return data_append_data(d, &beaddr, sizeof(beaddr));
       
   270 }
       
   271 
       
   272 struct data data_append_byte(struct data d, uint8_t byte)
       
   273 {
       
   274 	return data_append_data(d, &byte, 1);
       
   275 }
       
   276 
       
   277 struct data data_append_zeroes(struct data d, int len)
       
   278 {
       
   279 	d = data_grow_for(d, len);
       
   280 
       
   281 	memset(d.val + d.len, 0, len);
       
   282 	d.len += len;
       
   283 	return d;
       
   284 }
       
   285 
       
   286 struct data data_append_align(struct data d, int align)
       
   287 {
       
   288 	int newlen = ALIGN(d.len, align);
       
   289 	return data_append_zeroes(d, newlen - d.len);
       
   290 }
       
   291 
       
   292 struct data data_add_marker(struct data d, enum markertype type, char *ref)
       
   293 {
       
   294 	struct marker *m;
       
   295 
       
   296 	m = xmalloc(sizeof(*m));
       
   297 	m->offset = d.len;
       
   298 	m->type = type;
       
   299 	m->ref = ref;
       
   300 	m->next = NULL;
       
   301 
       
   302 	return data_append_markers(d, m);
       
   303 }
       
   304 
       
   305 int data_is_one_string(struct data d)
       
   306 {
       
   307 	int i;
       
   308 	int len = d.len;
       
   309 
       
   310 	if (len == 0)
       
   311 		return 0;
       
   312 
       
   313 	for (i = 0; i < len-1; i++)
       
   314 		if (d.val[i] == '\0')
       
   315 			return 0;
       
   316 
       
   317 	if (d.val[len-1] != '\0')
       
   318 		return 0;
       
   319 
       
   320 	return 1;
       
   321 }