home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / config.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  6.4 KB  |  304 lines

  1. /*
  2.  *    Configuration stuff.
  3.  *
  4.  *    This code supports saving changes to the configuration file.
  5.  *    
  6.  */
  7.  
  8. #include <stdarg.h>
  9. #include "v9t9.h"
  10. #include "v9t9_common.h"
  11. #include "command.h"
  12. #include "config.h"
  13.  
  14. #define _L    LOG_COMMANDS | LOG_INFO
  15.  
  16. static OSHandle config;
  17.  
  18. /*
  19.  *    Escape an outgoing quoted string
  20.  */
  21. char *escape(const char *s, int quote)
  22. {
  23.     char *ret;
  24.     char *ptr;
  25.     
  26.     if (!s)
  27.         return xstrdup("");
  28.         
  29.     ret = (char *)xmalloc(strlen(s)*2+1);
  30.     ptr = ret;
  31.     while (*s) {
  32.         if (*s == '\\' || 
  33.             (quote == '\"' && *s == '\"') || 
  34.             (quote == '\'' && *s == '\''))
  35.         {
  36.             *ptr++ = '\\';
  37.         }
  38.         *ptr++ = *s++;
  39.     }
  40.     *ptr = 0;
  41.     
  42.     return ret;
  43. }
  44.  
  45. static void  cprintf(const char *format, ...)
  46. {
  47.     va_list va;
  48.     char tmp[256], *ptr;
  49.  
  50.     va_start(va, format);
  51.     ptr = mvprintf(tmp, sizeof(tmp), format, va);
  52.     if (OS_AppendHandle(&config, ptr, strlen(ptr)) != OS_NOERR)
  53.         logger(_L | LOG_FATAL, "Out of memory for config file\n");
  54.     if (ptr != tmp) xfree(ptr);
  55. }
  56.  
  57. static void dump_name(command_symbol *sym)
  58. {
  59.     char *ptr = sym->name;
  60.     int len = 0;
  61.     while (ptr[len] && ptr[len] != '|')
  62.         len++;
  63.     cprintf("%.*s ", len, ptr);
  64. }
  65.  
  66. static void dump_command(command_symbol *sym, bool session)
  67. {
  68.     command_arg *arg;
  69.     int iter = 0;
  70.     int ret;
  71.  
  72.     // don't save certain active commands
  73.     if (sym->flags & c_DONT_SAVE)
  74.         return;
  75.  
  76.     // don't save machine state unless it's a session
  77.     if ((sym->flags & c_SESSION_ONLY) && !session)
  78.         return;
  79.  
  80.     // don't save state unless it's not a session
  81.     if ((sym->flags & c_CONFIG_ONLY) && session)
  82.         return;
  83.  
  84.     do {
  85.  
  86.         if ((sym->flags & c_DYNAMIC) && sym->action) {
  87.             ret = sym->action(sym, csa_READ, iter);
  88.         } else {
  89.             ret = (iter == 0);
  90.         }
  91.         
  92.         if (!ret)
  93.             break;
  94.  
  95.         dump_name(sym);
  96.  
  97.         arg = sym->args;
  98.         while (arg) {
  99.             if (arg->type == ca_NUM) {
  100.                 int val;
  101.                 command_arg_read_num(arg, &val);
  102.                 if (strcmp(arg->name, "on|off") == 0 || strcmp(arg->name, "off|on") == 0)
  103.                     cprintf("%s ", val ? "on" : "off");
  104.                 else if (arg->u.num.sz > 2)
  105.                     cprintf("%d ", val);
  106.                 else
  107.                     cprintf("0x%x ", arg->u.num.sz == 1 ? (val & 0xff) :
  108.                             arg->u.num.sz == 2 ? (val & 0xffff) : val);
  109.             } else if (arg->type == ca_STRING) {
  110.                 char *str;
  111.                 command_arg_read_string(arg, &str);
  112.                 str = str ? escape(str, '\"') : 0L;
  113.                 cprintf("\"%s\" ", str ? str : "");
  114.                 xfree(str);
  115.             } else if (arg->type == ca_TOGGLE) {
  116.                 int val;
  117.                 command_arg_read_toggle(arg, &val);
  118.                 cprintf("%s ", val ? "on" : "off");
  119.             } else if (arg->type == ca_SPEC || arg->type == ca_PATHSPEC 
  120.                        || arg->type == ca_NAMESPEC) {
  121.                 char *str;
  122.                 command_arg_read_spec(arg, &str);
  123.                 str = str ? escape(str, '\"') : 0L;
  124.                 cprintf("\"%s\" ", str ? str : "");
  125.                 xfree(str);
  126.             } else {
  127.                 logger(_L | LOG_FATAL, "Unhandled type in dump_command (%d)\n", arg->type);
  128.             }
  129.             arg = arg->next;
  130.         }    
  131.  
  132.         cprintf("\n");
  133.         iter++;
  134.     } while (ret);
  135.  
  136. }
  137.  
  138. static void dump_symbol_table(command_symbol_table *table, bool session)
  139. {    
  140.     while (table) {
  141.         command_symbol *sym;
  142.         cprintf("\n[%s]\n", table->name);
  143.         sym = table->list;
  144.         while (sym) {
  145.             dump_command(sym, session);
  146.             sym = sym->next;
  147.         }
  148.         if (table->sub)
  149.             dump_symbol_table(table->sub, session);
  150.         table = table->next;
  151.     }
  152. }
  153.  
  154. int 
  155. config_load_spec(const OSSpec *spec, bool session)
  156. {
  157.     char path[OS_PATHSIZE];
  158.     int ret;
  159.     bool sessionflag;
  160.  
  161.     OS_SpecToString2(spec, path);
  162.     sessionflag = command_get_session_filter();
  163.     command_set_session_filter(session);
  164.     ret = command_parse_file(path);
  165.     command_set_session_filter(sessionflag);
  166.     return ret;
  167. }
  168.  
  169. int 
  170. config_save_spec(const OSSpec *spec, bool session)
  171. {
  172.     FILE *file;
  173.     char *str;
  174.     char path[OS_PATHSIZE];
  175.     OSSize sz;
  176.     const char *filename = OS_NameSpecToString1(&spec->name);
  177.  
  178.     if (!filename || !*filename || strcmp(filename, "-") == 0) 
  179.         file = stdout;
  180.     else {
  181.         OS_SpecToString2(spec, path);
  182.         file = fopen(path, "wt");
  183.     }
  184.  
  185.     if (!file) {
  186.         logger(_L | LOG_ERROR | LOG_USER, "Cannot write to %s\n", path);
  187.         return 0;
  188.     }
  189.  
  190.     if (OS_NewHandle(0, &config) != OS_NOERR)
  191.         logger(_L | LOG_FATAL, "Out of memory for config file\n");
  192.  
  193.     fprintf(file, "#!%s %s\n", OS_SpecToString1(&v9t9_progspec), path);
  194.     fprintf(file, "#\n" "#  v9t9 configuration file\n" "#\n");
  195.  
  196.     dump_symbol_table(universe, session);
  197.  
  198.     str = OS_LockHandle(&config);
  199.     if (OS_GetHandleSize(&config, &sz) != OS_NOERR)
  200.         sz = strlen(str);
  201.     fwrite(str, sz, 1, file);
  202.     OS_UnlockHandle(&config);
  203.  
  204.     if (file != stdout)
  205.         fclose(file);
  206.  
  207. #if defined(UNDER_UNIX)
  208.     chmod(path, 0777);
  209. #endif
  210.     return 1;
  211. }
  212.  
  213. /*
  214.  *    Find a file in the given path, returning 1 for success,
  215.  *    or 0 for failure.  If failed, 'spec' points to the file in the
  216.  *    first path element.
  217.  */
  218. int
  219. config_find_file(const char *filename, const char *path, OSSpec *spec)
  220. {
  221.     OSError err;
  222.     if (OS_GetFileNamePtr(filename) != filename &&
  223.         (err = OS_MakeFileSpec(filename, spec)) == OS_NOERR &&
  224.         OS_Status(spec) == OS_NOERR) {
  225.         // found it
  226.         return 1;
  227.     } else
  228.     if ((err = OS_FindFileInPath(filename, path, spec)) != OS_NOERR) {
  229.         return 0;
  230.     } else {
  231.         return 1;
  232.     }
  233. }
  234.  
  235. int 
  236. config_load_file(const char *path, const char *filename, bool session)
  237. {
  238.     OSSpec spec;
  239.     if (!config_find_file(filename, path, &spec))
  240.         return 0;
  241.     return config_load_spec(&spec, session);
  242. }
  243.  
  244. int 
  245. config_save_file(const char *path, const char *filename, bool session)
  246. {
  247.     OSSpec spec;
  248.     config_find_file(filename, path, &spec);
  249.     return config_save_spec(&spec, session);
  250. }
  251.  
  252. DECL_SYMBOL_ACTION(save_config)
  253. {
  254.     char *filename;
  255.     int ret;
  256.     command_arg_get_string(SYM_ARG_1st, &filename);
  257.     ret = config_save_file(configspath, filename, false);
  258.     if (!ret) {
  259.         logger(_L|LOG_USER, "Could not save config file to '%s' in:\n%s\n", 
  260.                filename, configspath);
  261.     }
  262.     return ret;
  263. }
  264.  
  265. DECL_SYMBOL_ACTION(load_config)
  266. {
  267.     char *filename;
  268.     int ret;
  269.     command_arg_get_string(SYM_ARG_1st, &filename);
  270.     ret = config_load_file(configspath, filename, false);
  271.     if (!ret) {
  272.         logger(_L|LOG_USER, "Could not find config file '%s' in:\n%s\n", 
  273.                filename, configspath);
  274.     }
  275.     return ret;
  276. }
  277.  
  278. DECL_SYMBOL_ACTION(save_session)
  279. {
  280.     char *filename;
  281.     int ret;
  282.     command_arg_get_string(SYM_ARG_1st, &filename);
  283.     ret = config_save_file(sessionspath, filename, true);
  284.     if (!ret) {
  285.         logger(_L|LOG_USER, "Could not save session to '%s' in:\n%s\n", 
  286.                filename, sessionspath);
  287.     }
  288.     return ret;
  289. }
  290.  
  291. DECL_SYMBOL_ACTION(load_session)
  292. {
  293.     char *filename;
  294.     int ret;
  295.     command_arg_get_string(SYM_ARG_1st, &filename);
  296.     ret = config_load_file(sessionspath, filename, true);
  297.     if (!ret) {
  298.         logger(_L|LOG_USER, "Could not find session file '%s' in:\n%s\n", 
  299.                filename, sessionspath);
  300.     }
  301.     return ret;
  302. }
  303.  
  304.