This is resources.c in view mode; [Download] [Up]
/* * resources.c - Resource (setting) handling for VICE. * * Written by * Ettore Perazzoli (ettore@comm2000.it) * * This file is part of VICE, the Versatile Commodore Emulator. * See README for copyright notice. * * 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 License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. * */ /* This implements simple facilities to handle the resources and command-line options. All the resources for the emulators can be stored in a single file, and they are separated by an `emulator identifier', i.e. the machine name between brackets (e.g. ``[C64]''). All the resources are stored in the form ``ResourceName=ResourceValue'', and separated by newline characters. Leading and trailing spaces are removed from the ResourceValue unless it is put between quotes ("). */ #include "vice.h" #include <stdio.h> #include <stdarg.h> #include <string.h> #ifdef __MSDOS__ #include <dir.h> #endif #include "resources.h" #include "utils.h" #include "ui.h" static int num_resources, num_allocated_resources; static resource_t *resources; static const char *machine_id; /* FIXME: I don't like this to be here. */ #ifdef __MSDOS__ #define RESOURCE_FILE_NAME "VICERC" #else #define RESOURCE_FILE_NAME ".vicerc" #endif #if 0 #define RWARNING(s) printf s #else #define RWARNING(s) #endif /* ------------------------------------------------------------------------- */ /* FIXME: We might want to use a hash table instead of a linear search some day. */ int resources_register(const resource_t *r) { const resource_t *sp; resource_t *dp; sp = r; dp = resources + num_resources; while (sp->name != NULL) { if (num_allocated_resources <= num_resources) { num_allocated_resources *= 2; resources = xrealloc(resources, num_allocated_resources * sizeof(resource_t)); dp = resources + num_resources; } dp->name = sp->name; dp->type = sp->type; dp->factory_value = sp->factory_value; dp->value_ptr = sp->value_ptr; dp->set_func = sp->set_func; num_resources++, sp++, dp++; } return 0; } static resource_t *lookup(const char *name) { int i; for (i = 0; i < num_resources; i++) if (strcasecmp(resources[i].name, name) == 0) return resources + i; return NULL; } /* ------------------------------------------------------------------------- */ int resources_init(const char *machine) { machine_id = stralloc(machine); num_allocated_resources = 100; num_resources = 0; resources = (resource_t *) xmalloc(num_allocated_resources * sizeof(resource_t)); return 0; } int resources_set_value(const char *name, resource_value_t value) { resource_t *r = lookup(name); if (r == NULL) { RWARNING(("Warning: Trying to assign value to unknown resource `%s'\n", name)); return -1; } return r->set_func(value); } int resources_set_value_string(const char *name, const char *value) { resource_t *r = lookup(name); if (r == NULL) { RWARNING(("Warning: Trying to assign value to unknown resource `%s'\n", name)); return -1; } switch (r->type) { case RES_INTEGER: return r->set_func((resource_value_t) atoi(value)); case RES_STRING: return r->set_func((resource_value_t) value); default: fprintf(stderr, "Warning: unknown resource type for `%s'\n", name); return -1; } return -1; } int resources_get_value(const char *name, resource_value_t *value_return) { resource_t *r = lookup(name); if (r == NULL) { RWARNING(("Warning: Trying to read value from unknown resource `%s'\n", name)); return -1; } switch (r->type) { case RES_INTEGER: *(int *)value_return = *(int *)r->value_ptr; break; case RES_STRING: *(char **)value_return = *(char **)r->value_ptr; break; default: fprintf(stderr, "Warning: unknown resource type for `%s'\n", name); return -1; } return 0; } void resources_set_defaults(void) { int i; for (i = 0; i < num_resources; i++) resources[i].set_func(resources[i].factory_value); ui_update_menus(); } int resources_toggle(const char *name, resource_value_t *new_value_return) { resource_t *r = lookup(name); int value; if (r == NULL) { RWARNING((stderr, "Warning: Trying to toggle boolean value of unknown resource `%s'\n", name)); return -1; } value = !(*(int *)r->value_ptr); if (new_value_return != NULL) *(int *)new_value_return = value; return r->set_func((resource_value_t) value); } /* ------------------------------------------------------------------------- */ #ifndef __MSDOS__ /* Return a malloced string with the name of the backup file corresponding to `fname'. */ static char *make_backup_file_name(const char *fname) { return concat(fname, "~", NULL); } #else /* __MSDOS__ */ /* Return a malloced string with the name of the backup file corresponding to `fname'. FIXME: Only works with 8+3 names. */ static char *make_backup_file_name(const char *fname) { static char backup_name[MAXPATH]; char drive[MAXDRIVE]; char dir[MAXDIR]; char name[MAXFILE]; char ext[MAXEXT]; fnsplit(fname, drive, dir, name, ext); fnmerge(backup_name, drive, dir, name, "BAK"); return stralloc(backup_name); } #endif /* __MSDOS__ */ /* Check whether `buf' is the emulator ID for the machine we are emulating. */ static int check_emu_id(const char *buf) { int machine_id_len, buf_len; buf_len = strlen(buf); if (*buf != '[' || *(buf + buf_len - 1) != ']') return 0; if (machine_id == NULL) return 1; machine_id_len = strlen(machine_id); if (machine_id_len != buf_len - 2) return 0; if (strncmp(buf + 1, machine_id, machine_id_len) == 0) return 1; else return 0; } /* Return a malloced string containing the name of the default user-specific resource file. Warning: assumes `boot_path' does not change (it should be always so). */ static const char *default_resource_file(void) { static char *fname = NULL; if (fname == NULL) { #if defined __MSDOS__ || defined WIN32 /* On MS-DOS, always boot from the directory in which the binary is stored. */ fname = concat(boot_path, "\\", RESOURCE_FILE_NAME, NULL); #else fname = concat(getenv("HOME"), "/", RESOURCE_FILE_NAME, NULL); #endif } return (const char *)fname; } /* ------------------------------------------------------------------------- */ /* Read one resource line from the file descriptor `f'. Return 1 on success, -1 on failure, 0 on EOF or end of emulator section. */ static int read_resource_item(FILE *f) { char buf[1024]; char *arg_ptr; int line_len, resname_len, arg_len; resource_t *r; line_len = get_line(buf, 1024, f); if (line_len < 0) return 0; /* Ignore empty lines. */ if (*buf == '\0') return 1; if (*buf == '[') { /* End of emulator-specific section. */ return 0; } arg_ptr = strchr(buf, '='); if (!arg_ptr) return -1; resname_len = arg_ptr - buf; arg_ptr++; arg_len = strlen(arg_ptr); /* If the value is between quotes, remove them. */ if (*arg_ptr == '"' && *(arg_ptr + arg_len - 1) == '"') { *(arg_ptr + arg_len - 1) = '\0'; arg_ptr++; } *(buf + resname_len) = '\0'; { int result; r = lookup(buf); if (r == NULL) { fprintf(stderr, "Unknown resource `%s'.\n", buf); return -1; } switch (r->type) { case RES_INTEGER: result = r->set_func((resource_value_t) atoi(arg_ptr)); break; case RES_STRING: result = r->set_func((resource_value_t) arg_ptr); break; default: fprintf(stderr, "Warning: Unknown resource type for `%s'.\n", r->name); result = -1; } if (result < 0) { RWARNING((stderr, "Warning: Cannot assign value to resource `%s'.\n", r->name)); return -1; } return 1; } } /* Load the resources from file `fname'. If `fname' is NULL, load them from the default resource file. */ int resources_load(const char *fname) { FILE *f; int retval; int line_num; int err = 0; if (fname == NULL) fname = default_resource_file(); #ifdef __MSDOS__ f = fopen(fname, "rt"); #else f = fopen(fname, "r"); #endif if (f == NULL) { /*perror(fname);*/ return RESERR_FILE_NOT_FOUND; } printf("Reading configuration file `%s'.\n", fname); /* Find the start of the configuration section for this emulator. */ for (line_num = 1; ; line_num++) { char buf[1024]; if (get_line(buf, 1024, f) < 0) { fclose(f); return RESERR_READ_ERROR; } if (check_emu_id(buf)) { line_num++; break; } } do { retval = read_resource_item(f); if (retval == -1) { fprintf(stderr, "%s: Invalid resource specification at line %d.\n", fname, line_num); err = 1; } line_num++; } while (retval != 0); fclose(f); /* Update the values in the UI menus. */ ui_update_menus(); return err ? RESERR_FILE_INVALID : 0; } /* Write the resource specification for resource number `num' to file descriptor `f'. */ static void write_resource_item(FILE *f, int num) { resource_value_t v; fprintf(f, "%s=", resources[num].name); switch (resources[num].type) { case RES_INTEGER: v = (resource_value_t)*(int *)resources[num].value_ptr; fprintf(f, "%d", (int)v); break; case RES_STRING: v = *resources[num].value_ptr; if ((char *)v != NULL) fprintf(f, "\"%s\"", (char *)v); break; default: fprintf(stderr, "Warning: Unknown value type for resource `%s'.\n", resources[num].name); } fputc('\n', f); } /* Save all the resources into file `fname'. If `fname' is NULL, save them in the default resource file. Writing the resources does not destroy the resources for the other emulators. */ int resources_save(const char *fname) { char *backup_name; FILE *in_file, *out_file; int have_old; int i; if (fname == NULL) fname = default_resource_file(); /* Make a backup copy of the existing configuration file. */ backup_name = make_backup_file_name(fname); if (rename(fname, backup_name) == 0) have_old = 1; else have_old = 0; printf("Writing configuration file `%s'.\n", fname); #ifdef __MSDOS__ out_file = fopen(fname, "wt"); #else out_file = fopen(fname, "w"); #endif if (!out_file) { perror(fname); free (backup_name); return RESERR_CANNOT_CREATE_FILE; } if (have_old) { #ifdef __MSDOS__ in_file = fopen(backup_name, "rt"); #else in_file = fopen(backup_name, "r"); #endif if (!in_file) { fclose(out_file); perror(backup_name); free(backup_name); return RESERR_READ_ERROR; } /* Copy the configuration for the other emulators. */ while (1) { char buf[1024]; if (get_line(buf, 1024, in_file) < 0) break; if (check_emu_id(buf)) break; fprintf(out_file, "%s\n", buf); } } else in_file = NULL; /* Write our current configuration. */ fprintf(out_file,"[%s]\n", machine_id); for (i = 0; i < num_resources; i++) write_resource_item(out_file, i); if (have_old) { char buf[1024]; /* Skip the old configuration for this emulator. */ while (1) { if (get_line(buf, 1024, in_file) < 0) break; /* Check if another emulation section starts. */ if (*buf == '[') { fprintf(out_file, "%s\n", buf); break; } } if (!feof(in_file)) { /* Copy the configuration for the other emulators. */ while (get_line(buf, 1024, in_file) >= 0) fprintf(out_file, "%s\n", buf); } } if (in_file) fclose(in_file); fclose(out_file); free(backup_name); return 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.