settings.cc Source File

Back to the index.

settings.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * A generic settings object. (This module should be 100% indepedent of GXemul
29  * and hence easily reusable.) It is basically a tree structure of nodes,
30  * where each node has a name and a few properties. The main property is
31  * a pointer, which can either point to other settings ("sub-settings"),
32  * or to a variable in memory.
33  *
34  * Appart from the pointer, the other properties are a definition of the
35  * type being pointed to (int, int32_t, int64_t, char*, etc), how it should be
36  * presented (e.g. it may be an int value in memory, but it should be
37  * presented as a boolean "true/false" value), and a flag which tells us
38  * whether the setting is directly writable or not.
39  *
40  * If UNSTABLE_DEVEL is defined, then warnings are printed when
41  * settings_destroy() is called if individual settings have not yet been
42  * deleted. (This is to help making sure that code which uses the settings
43  * subsystem correctly un-initializes stuff.)
44  */
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 
50 /* Including misc.h should ONLY be necessary to work around the fact that
51  many systems don't have PRIx64 etc defined. */
52 #include "misc.h"
53 
54 #include "settings.h"
55 
56 
57 struct settings {
58  struct settings *parent;
60 
62 
63  /*
64  * Each setting has a name, a writable flag, a storage type, a
65  * presentation format, and a pointer.
66  *
67  * For subsettings, the pointer points to the subsettings object;
68  * for other settings, the pointer points to a variable.
69  *
70  * These pointers point to simple linear arrays, containing n_settings
71  * entries each.
72  */
73 
74  char **name;
75  int *writable;
78  void **ptr;
79 };
80 
81 
82 /*
83  * settings_new():
84  *
85  * Create a new settings object. Return value is a pointer to the newly
86  * created object. The function does not return on failure.
87  */
88 struct settings *settings_new(void)
89 {
90  struct settings *settings;
91 
92  CHECK_ALLOCATION(settings = (struct settings *) malloc(sizeof(struct settings)));
93  memset(settings, 0, sizeof(struct settings));
94 
95  return settings;
96 }
97 
98 
99 /*
100  * settings_destroy():
101  *
102  * Frees all resources occupied by a settings object. Also, if this settings
103  * object has a parent, then remove it from the parent.
104  */
106 {
107  int i;
108 
109  if (settings == NULL) {
110  fprintf(stderr, "settings_destroy(): internal error, "
111  "settings = NULL!\n");
112  exit(1);
113  }
114 
115 #ifdef UNSTABLE_DEVEL
116  if (settings->n_settings > 0)
117  printf("settings_destroy(): there are remaining settings!\n");
118 #endif
119 
120  if (settings->name != NULL) {
121  for (i=0; i<settings->n_settings; i++) {
122  if (settings->name[i] != NULL) {
123 #ifdef UNSTABLE_DEVEL
124  printf("settings_destroy(): setting '%s'"
125  " was not properly deleted before "
126  "exiting!\n", settings->name[i]);
127 #endif
128  free(settings->name[i]);
129  }
130  }
131 
132  free(settings->name);
133  } else if (settings->n_settings != 0) {
134  fprintf(stderr, "settings_destroy(): internal error, "
135  "settings->name = NULL, but there were settings?"
136  " (n_settings = %i)\n", settings->n_settings);
137  exit(1);
138  }
139 
140  if (settings->writable != NULL)
141  free(settings->writable);
142 
143  if (settings->storage_type != NULL)
144  free(settings->storage_type);
145 
146  if (settings->presentation_format != NULL)
148 
149  if (settings->ptr != NULL)
150  free(settings->ptr);
151 
152  if (settings->parent != NULL) {
154  free(settings->name_in_parent);
155  }
156 
157  free(settings);
158 }
159 
160 
161 /*
162  * settings_read():
163  *
164  * Used internally by settings_access() and settings_debugdump().
165  */
166 static int settings_read(struct settings *settings, int i, uint64_t *valuep)
167 {
168  *valuep = 0;
169 
170  switch (settings->storage_type[i]) {
171  case SETTINGS_TYPE_INT:
172  *valuep = *((int *) settings->ptr[i]);
173  break;
174  case SETTINGS_TYPE_INT8:
175  *valuep = *((int8_t *) settings->ptr[i]);
176  break;
177  case SETTINGS_TYPE_INT16:
178  *valuep = *((int16_t *) settings->ptr[i]);
179  break;
180  case SETTINGS_TYPE_INT32:
181  *valuep = *((int32_t *) settings->ptr[i]);
182  break;
183  case SETTINGS_TYPE_INT64:
184  *valuep = *((int64_t *) settings->ptr[i]);
185  break;
186  case SETTINGS_TYPE_UINT:
187  *valuep = *((uint *) settings->ptr[i]);
188  break;
189  case SETTINGS_TYPE_UINT8:
190  *valuep = *((uint8_t *) settings->ptr[i]);
191  break;
193  *valuep = *((uint16_t *) settings->ptr[i]);
194  break;
196  *valuep = *((uint32_t *) settings->ptr[i]);
197  break;
199  *valuep = *((uint64_t *) settings->ptr[i]);
200  break;
202  /* Note: Strings cannot be read like this. */
203  break;
204  default:printf("settings_read(): FATAL ERROR! Unknown storage type"
205  ": %i\n", settings->storage_type[i]);
206  exit(1);
207  }
208 
209  return SETTINGS_OK;
210 }
211 
212 
213 /*
214  * settings_write():
215  *
216  * Used internally by settings_access().
217  */
218 static int settings_write(struct settings *settings, int i, uint64_t *valuep)
219 {
220  if (!settings->writable[i])
221  return SETTINGS_READONLY;
222 
223  switch (settings->storage_type[i]) {
224  case SETTINGS_TYPE_INT:
225  case SETTINGS_TYPE_UINT:
226  *((int *) settings->ptr[i]) = *valuep;
227  break;
228  case SETTINGS_TYPE_INT8:
229  case SETTINGS_TYPE_UINT8:
230  *((int8_t *) settings->ptr[i]) = *valuep;
231  break;
232  case SETTINGS_TYPE_INT16:
234  *((int16_t *) settings->ptr[i]) = *valuep;
235  break;
236  case SETTINGS_TYPE_INT32:
238  *((int32_t *) settings->ptr[i]) = *valuep;
239  break;
240  case SETTINGS_TYPE_INT64:
242  *((int64_t *) settings->ptr[i]) = *valuep;
243  break;
245  /* Note: Strings cannot be read like this. */
246  printf("settings_write(): ERROR! Strings cannot be "
247  "written like this.\n");
248  break;
249  default:printf("settings_read(): FATAL ERROR! Unknown storage type"
250  ": %i\n", settings->storage_type[i]);
251  exit(1);
252  }
253 
254  return SETTINGS_OK;
255 }
256 
257 
258 /*
259  * settings_debugdump():
260  *
261  * Dump settings in a settings object to stdout.
262  * If recurse is non-zero, all subsetting objects are also dumped.
263  */
264 void settings_debugdump(struct settings *settings, const char *prefix,
265  int recurse)
266 {
267  size_t name_buflen = strlen(prefix) + 100;
268  char *name;
269  int i;
270  uint64_t value = 0;
271 
272  CHECK_ALLOCATION(name = (char *) malloc(name_buflen));
273 
274  for (i=0; i<settings->n_settings; i++) {
275  snprintf(name, name_buflen, "%s.%s", prefix, settings->name[i]);
276 
278  /* Subsettings: */
279  if (recurse)
280  settings_debugdump((struct settings *)settings->ptr[i], name, 1);
281  } else {
282  /* Normal value: */
283  printf("%s = ", name);
284 
285  settings_read(settings, i, &value);
286 
287  switch (settings->presentation_format[i]) {
289  printf("%" PRIi64, value);
290  break;
292  printf("0x%02" PRIx8, (int8_t) value);
293  break;
295  printf("0x%04" PRIx16, (int16_t) value);
296  break;
298  printf("0x%08" PRIx32, (int32_t) value);
299  break;
301  printf("0x%016" PRIx64, (int64_t) value);
302  break;
304  printf(value? "true" : "false");
305  break;
307  printf(value? "yes" : "no");
308  break;
310  printf("\"%s\"", *((char **)settings->ptr[i]));
311  break;
312  default:printf("FATAL ERROR! Unknown presentation "
313  "format: %i\n",
315  exit(1);
316  }
317 
318  if (!settings->writable[i])
319  printf(" (R/O)");
320 
321  printf("\n");
322  }
323  }
324 
325  free(name);
326 }
327 
328 
329 /*
330  * settings_add():
331  *
332  * Add a setting to a settings object.
333  */
334 void settings_add(struct settings *settings, const char *name, int writable,
335  int type, int format, void *ptr)
336 {
337  int i;
338 
339  for (i=0; i<settings->n_settings; i++) {
340  if (strcmp(settings->name[i], name) == 0)
341  break;
342  }
343 
344  if (i < settings->n_settings) {
345  fprintf(stderr, "settings_add(): name '%s' is already"
346  " in use\n", name);
347  exit(1);
348  }
349 
350  settings->n_settings ++;
351 
352  CHECK_ALLOCATION(settings->name = (char **) realloc(settings->name,
353  settings->n_settings * sizeof(char *)));
354  CHECK_ALLOCATION(settings->writable = (int *) realloc(settings->writable,
355  settings->n_settings * sizeof(int)));
356  CHECK_ALLOCATION(settings->storage_type = (int *) realloc(
357  settings->storage_type, settings->n_settings * sizeof(int)));
359  presentation_format, settings->n_settings * sizeof(int)));
360  CHECK_ALLOCATION(settings->ptr = (void **) realloc(settings->ptr,
361  settings->n_settings * sizeof(void *)));
362 
364  strdup(name));
369 
370  if (type == SETTINGS_TYPE_SUBSETTINGS) {
371  ((struct settings *)ptr)->parent = settings;
373  strdup(name) );
374  }
375 }
376 
377 
378 /*
379  * settings_remove():
380  *
381  * Remove a setting from a settings object.
382  */
383 void settings_remove(struct settings *settings, const char *name)
384 {
385  int i, m;
386 
387  for (i=0; i<settings->n_settings; i++) {
388  if (strcmp(settings->name[i], name) == 0)
389  break;
390  }
391 
392  if (i >= settings->n_settings) {
393 #ifdef UNSTABLE_DEVEL
394  fprintf(stderr, "settings_remove(): attempting to remove"
395  " non-existant setting '%s'\n", name);
396 #endif
397  return;
398  }
399 
400  /* Check subsettings specifically: */
402  settings->ptr[i] != NULL) {
403  struct settings *subsettings = (struct settings *) settings->ptr[i];
404  if (subsettings->n_settings != 0) {
405  fprintf(stderr, "settings_remove(): attempting to "
406  "remove non-emtpy setting '%s'\n", name);
407  fprintf(stderr, "Remaining settings are:\n");
408  for (i=0; i<subsettings->n_settings; i++)
409  fprintf(stderr, "\t%s\n", subsettings->name[i]);
410  exit(1);
411  }
412  }
413 
414  settings->n_settings --;
415  free(settings->name[i]);
416 
417  m = settings->n_settings - i;
418  if (m == 0)
419  return;
420 
421  memmove(&settings->name[i], &settings->name[i+1],
422  m * sizeof(settings->name[0]));
423  memmove(&settings->writable[i], &settings->writable[i+1],
424  m * sizeof(settings->writable[0]));
425  memmove(&settings->storage_type[i], &settings->storage_type[i+1],
426  m * sizeof(settings->storage_type[0]));
427  memmove(&settings->presentation_format[i],
429  m * sizeof(settings->presentation_format[0]));
430  memmove(&settings->ptr[i], &settings->ptr[i+1],
431  m * sizeof(settings->ptr[0]));
432 }
433 
434 
435 /*
436  * settings_remove_all():
437  *
438  * Remove all (level-1) settings from a settings object. By level-1, I mean
439  * all settings that do not contain subsettings.
440  */
442 {
443  while (settings->n_settings > 0)
445 }
446 
447 
448 /*
449  * settings_access():
450  *
451  * Read or write a setting. fullname may be something like "settings.x.y".
452  * When writing a value, valuebuf should point to a uint64_t containing the
453  * new value (note: always a uint64_t). When reading a value, valuebuf should
454  * point to a uint64_t where the value will be stored.
455  *
456  * The return value is one of the following:
457  *
458  * SETTINGS_OK
459  * The value was read or written.
460  *
461  * SETTINGS_NAME_NOT_FOUND
462  * The name was not found in the settings object.
463  *
464  * SETTINGS_READONLY
465  * The name was found, but it was marked as read-only, and
466  * an attempt was made to write to it.
467  */
468 int settings_access(struct settings *settings, const char *fullname,
469  int writeflag, uint64_t *valuep)
470 {
471  int i;
472 
473  /* printf("settings_access(fullname='%s')\n", fullname); */
474 
475  if (strncmp(fullname, GLOBAL_SETTINGS_NAME".",
476  strlen(GLOBAL_SETTINGS_NAME) + 1) == 0)
477  fullname += strlen(GLOBAL_SETTINGS_NAME) + 1;
478 
479  for (i=0; i<settings->n_settings; i++) {
480  size_t settings_name_len = strlen(settings->name[i]);
481 
482  if (strncmp(fullname, settings->name[i],
483  settings_name_len) != 0)
484  continue;
485 
486  /* Found the correct setting? */
487  if (fullname[settings_name_len] == '\0') {
488  if (writeflag)
489  return settings_write(settings, i, valuep);
490  else
491  return settings_read(settings, i, valuep);
492  }
493 
494  /* Found a setting which has sub-settings? */
495  if (fullname[settings_name_len] == '.') {
496  /* Recursive search: */
497  return settings_access(
498  (struct settings *)settings->ptr[i],
499  fullname + settings_name_len + 1,
500  writeflag, valuep);
501  }
502  }
503 
505 }
506 
settings::presentation_format
int * presentation_format
Definition: settings.cc:77
settings::n_settings
int n_settings
Definition: settings.cc:61
settings::ptr
void ** ptr
Definition: settings.cc:78
SETTINGS_TYPE_INT32
#define SETTINGS_TYPE_INT32
Definition: settings.h:43
settings::parent
struct settings * parent
Definition: settings.cc:58
SETTINGS_FORMAT_HEX32
#define SETTINGS_FORMAT_HEX32
Definition: settings.h:55
settings.h
SETTINGS_FORMAT_STRING
#define SETTINGS_FORMAT_STRING
Definition: settings.h:59
SETTINGS_FORMAT_HEX64
#define SETTINGS_FORMAT_HEX64
Definition: settings.h:56
SETTINGS_TYPE_UINT
#define SETTINGS_TYPE_UINT
Definition: settings.h:45
SETTINGS_FORMAT_DECIMAL
#define SETTINGS_FORMAT_DECIMAL
Definition: settings.h:52
settings::writable
int * writable
Definition: settings.cc:75
SETTINGS_TYPE_STRING
#define SETTINGS_TYPE_STRING
Definition: settings.h:39
if
addr & if(addr >=0x24 &&page !=NULL)
Definition: tmp_arm_multi.cc:56
SETTINGS_NAME_NOT_FOUND
#define SETTINGS_NAME_NOT_FOUND
Definition: settings.h:82
SETTINGS_TYPE_INT64
#define SETTINGS_TYPE_INT64
Definition: settings.h:44
settings_remove_all
void settings_remove_all(struct settings *settings)
Definition: settings.cc:441
settings_new
struct settings * settings_new(void)
Definition: settings.cc:88
strlen
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
Definition: cpu_arm_instr.cc:2333
SETTINGS_FORMAT_HEX8
#define SETTINGS_FORMAT_HEX8
Definition: settings.h:53
misc.h
settings::storage_type
int * storage_type
Definition: settings.cc:76
SETTINGS_TYPE_INT16
#define SETTINGS_TYPE_INT16
Definition: settings.h:42
settings_access
int settings_access(struct settings *settings, const char *fullname, int writeflag, uint64_t *valuep)
Definition: settings.cc:468
SETTINGS_OK
#define SETTINGS_OK
Definition: settings.h:81
SETTINGS_TYPE_SUBSETTINGS
#define SETTINGS_TYPE_SUBSETTINGS
Definition: settings.h:38
settings
Definition: settings.cc:57
SETTINGS_FORMAT_HEX16
#define SETTINGS_FORMAT_HEX16
Definition: settings.h:54
SETTINGS_TYPE_UINT16
#define SETTINGS_TYPE_UINT16
Definition: settings.h:47
settings::name
char ** name
Definition: settings.cc:74
settings_destroy
void settings_destroy(struct settings *settings)
Definition: settings.cc:105
settings_debugdump
void settings_debugdump(struct settings *settings, const char *prefix, int recurse)
Definition: settings.cc:264
SETTINGS_TYPE_UINT8
#define SETTINGS_TYPE_UINT8
Definition: settings.h:46
SETTINGS_FORMAT_BOOL
#define SETTINGS_FORMAT_BOOL
Definition: settings.h:57
settings::name_in_parent
char * name_in_parent
Definition: settings.cc:59
SETTINGS_TYPE_UINT64
#define SETTINGS_TYPE_UINT64
Definition: settings.h:49
SETTINGS_TYPE_INT8
#define SETTINGS_TYPE_INT8
Definition: settings.h:41
GLOBAL_SETTINGS_NAME
#define GLOBAL_SETTINGS_NAME
Definition: settings.h:33
settings_add
void settings_add(struct settings *settings, const char *name, int writable, int type, int format, void *ptr)
Definition: settings.cc:334
SETTINGS_READONLY
#define SETTINGS_READONLY
Definition: settings.h:83
SETTINGS_FORMAT_YESNO
#define SETTINGS_FORMAT_YESNO
Definition: settings.h:58
settings_remove
void settings_remove(struct settings *settings, const char *name)
Definition: settings.cc:383
SETTINGS_TYPE_INT
#define SETTINGS_TYPE_INT
Definition: settings.h:40
SETTINGS_TYPE_UINT32
#define SETTINGS_TYPE_UINT32
Definition: settings.h:48
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17