missing NULL terminator in set_config_x
[geda-gaf.git] / libgeda / src / scheme_config.c
blobbe6d25a3d9f6b6553f6f3b118ae4b9da4cff9b21
1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library - Scheme API
3 * Copyright (C) 2011-2012 Peter Brett <peter@peter-b.co.uk>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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
13 * GNU General Public License for more details.
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 USA
20 /*!
21 * \file scheme_config.c
22 * \brief Scheme API configuration procedures.
25 #include <config.h>
27 #include "libgeda_priv.h"
28 #include "libgedaguile_priv.h"
30 SCM_SYMBOL (system_error_sym, "system-error");
31 SCM_SYMBOL (config_error_sym, "config-error");
32 SCM_SYMBOL (unknown_encoding_sym, "unknown-encoding");
33 SCM_SYMBOL (parse_sym, "parse");
34 SCM_SYMBOL (key_not_found_sym, "key-not-found");
35 SCM_SYMBOL (group_not_found_sym, "group-not-found");
36 SCM_SYMBOL (invalid_value_sym, "invalid-value");
38 #define ASSERT_CFG_GROUP_KEY(subr) do { \
39 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1, subr); \
40 SCM_ASSERT (scm_is_string (group_s), group_s, SCM_ARG2, subr); \
41 SCM_ASSERT (scm_is_string (key_s), key_s, SCM_ARG3, subr); \
42 } while (0);
44 /*! \brief Convert a GError to a Scheme error.
46 * Raise a Scheme exception for the given \a error, with the procedure
47 * name \a subr. The \a error will be freed with g_clear_error(). Does
48 * not return.
50 * The \a error will be converted to a Scheme error according to the
51 * following rules:
53 * - If \a error is a GFileError, it will be converted to a
54 * system-error.
56 * - If \a error is an EdaConfigError, it will be converted to a
57 * config-error.
59 * - Otherwise, it will be converted to a misc-error.
61 * \bug For GFileErrors, the GLib error code will be returned rather
62 * than the system error code.
64 * \param subr name of failed procedure, or NULL.
65 * \param error error to be converted to a Scheme exception.
67 static void
68 error_from_gerror (const gchar *subr, GError **error)
70 if (error == NULL || *error == NULL) {
71 scm_misc_error (subr, "Unknown error", SCM_EOL);
74 GError *err = *error;
76 scm_dynwind_begin (0);
77 /* Make sure that the GError gets cleaned up when the non-local exit
78 * occurs. */
79 scm_dynwind_unwind_handler ((void (*)(void *)) g_clear_error, error,
80 SCM_F_WIND_EXPLICITLY);
82 SCM rest;
84 if (err->domain == G_IO_ERROR) {
85 /* File-related errors */
86 scm_error (system_error_sym, subr, err->message, SCM_EOL,
87 scm_list_1 (scm_from_int (err->code)));
90 if (err->domain == EDA_CONFIG_ERROR) {
91 /* Configuration context-related errors */
92 switch (err->code) {
93 case EDA_CONFIG_ERROR_UNKNOWN_ENCODING:
94 rest = scm_list_1 (unknown_encoding_sym);
95 break;
96 case EDA_CONFIG_ERROR_PARSE:
97 rest = scm_list_1 (parse_sym);
98 break;
99 case EDA_CONFIG_ERROR_KEY_NOT_FOUND:
100 rest = scm_list_1 (key_not_found_sym);
101 break;
102 case EDA_CONFIG_ERROR_GROUP_NOT_FOUND:
103 rest = scm_list_1 (group_not_found_sym);
104 break;
105 case EDA_CONFIG_ERROR_INVALID_VALUE:
106 rest = scm_list_1 (invalid_value_sym);
107 break;
108 default:
109 rest = SCM_BOOL_F;
110 break;
112 scm_error (config_error_sym, subr, err->message, SCM_EOL, rest);
115 /* All other errors */
116 scm_misc_error (subr, err->message, SCM_EOL);
118 scm_dynwind_end ();
119 g_warn_if_reached ();
122 /*! \brief Get the default configuration context.
123 * \par Function Description
124 * Returns the configuration context for compiled-in default settings.
126 * \see eda_config_get_default_context().
128 * \note Scheme API: Implements the \%default-config-context procedure
129 * in the (geda core config) module.
131 * \return an #EdaConfig smob for the default context.
133 SCM_DEFINE (default_config_context, "%default-config-context", 0, 0, 0,
134 (), "Get default configuration context.")
136 return edascm_from_config (eda_config_get_default_context ());
139 /*! \brief Get the system configuration context.
140 * \par Function Description
141 * Returns the configuration context for system settings.
143 * \see eda_config_get_system_context().
145 * \note Scheme API: Implements the \%system-config-context procedure
146 * in the (geda core config) module.
148 * \return an #EdaConfig smob for the system context.
150 SCM_DEFINE (system_config_context, "%system-config-context", 0, 0, 0,
151 (), "Get system configuration context.")
153 return edascm_from_config (eda_config_get_system_context ());
156 /*! \brief Get the user configuration context.
157 * \par Function Description
158 * Returns the configuration context for user settings.
160 * \see eda_config_get_user_context().
162 * \note Scheme API: Implements the \%user-config-context procedure
163 * in the (geda core config) module.
165 * \return an #EdaConfig smob for the user context.
167 SCM_DEFINE (user_config_context, "%user-config-context", 0, 0, 0,
168 (), "Get user configuration context.")
170 return edascm_from_config (eda_config_get_user_context ());
173 /*! \brief Get the configuration context for a path.
174 * \par Function Description
175 * Looks for a configuration file named "geda.conf" in \a path or a
176 * parent directory.
178 * \see eda_config_get_context_for_path().
180 * \note Scheme API: Implements the \%path-config-context procedure in
181 * the (geda core config) module.
183 * \param [in] path_s Path to get context for, as a string.
184 * \return an #EdaConfig smob for \a path.
186 SCM_DEFINE (path_config_context, "%path-config-context", 1, 0, 0,
187 (SCM path_s), "Get configuration context for a path.")
189 SCM_ASSERT (scm_is_string (path_s), path_s, SCM_ARG1,
190 s_path_config_context);
192 scm_dynwind_begin (0);
193 char *path = scm_to_utf8_string (path_s);
194 scm_dynwind_free (path);
195 GFile *file = g_file_parse_name (path);
196 scm_dynwind_unwind_handler (g_object_unref, file,
197 SCM_F_WIND_EXPLICITLY);
199 EdaConfig *cfg = eda_config_get_context_for_file (file);
200 SCM result = edascm_from_config (cfg);
202 scm_dynwind_end ();
203 scm_remember_upto_here_1 (path_s);
204 return result;
207 /*! \brief Get a configuration context's filename.
208 * \par Function Description
209 * Returns the underlying filename for the configuration context \a
210 * cfg, or #f if it has no filename associated with it.
212 * \see eda_config_get_file().
214 * \note Scheme API: Implements the \%config-filename procedure in the
215 * (geda core config) module.
217 * \param cfg_s #EdaConfig smob for configuration context.
218 * \return string containing configuration filename.
220 SCM_DEFINE (config_filename, "%config-filename", 1, 0, 0,
221 (SCM cfg_s), "Get configuration filename.")
223 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
224 s_config_filename);
226 scm_dynwind_begin (0);
227 EdaConfig *cfg = edascm_to_config (cfg_s);
228 GFile *file = eda_config_get_file (cfg);
229 gchar *path = NULL;
230 if (file != NULL) {
231 path = g_file_get_parse_name (file);
232 scm_dynwind_free (path);
235 SCM result = (path == NULL) ? SCM_BOOL_F : scm_from_utf8_string (path);
236 scm_dynwind_end ();
237 return result;
240 /*! \brief Load configuration parameters from file.
241 * \par Function Description
242 * Attempt to load configuration parameters for \a cfg_s from file.
243 * Raises a system-error on failure.
245 * \see eda_config_load().
247 * \note Scheme API: Implements the \%config-load! procedure in the
248 * (geda core config) module.
250 * \param cfg_s #EdaConfig smob for configuration context to load.
251 * \return \a cfg_s.
253 SCM_DEFINE (config_load_x, "%config-load!", 1, 0, 0,
254 (SCM cfg_s), "Load configuration parameters from file.")
256 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
257 s_config_load_x);
259 EdaConfig *cfg = edascm_to_config (cfg_s);
260 GError *error = NULL;
261 if (!eda_config_load (cfg, &error)) {
262 error_from_gerror (s_config_load_x, &error);
264 return cfg_s;
267 /*! \brief Test if configuration context has been loaded.
268 * \par Function Description
269 * Returns #t if \a cfg_s has been loaded from file at some point, and
270 * #f otherwise.
272 * \see eda_config_is_loaded().
274 * \note Scheme API: Implements the \%config-loaded? procedure in the
275 * (geda core config) module.
277 * \param cfg_s #EdaConfig smob of configuration context.
278 * \return #t if \a cfg_s has been loaded; #f otherwise.
280 SCM_DEFINE (config_loaded_p, "%config-loaded?", 1, 0, 0,
281 (SCM cfg_s), "Test if configuration context has been loaded")
283 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
284 s_config_loaded_p);
286 EdaConfig *cfg = edascm_to_config (cfg_s);
287 return eda_config_is_loaded (cfg) ? SCM_BOOL_T : SCM_BOOL_F;
290 /*! \brief Save changes to a configuration context.
291 * \par Function Description
292 * Attempt to save configuration parameters for the context \a cfg_s
293 * to its ssociated file. Raises a system-error on failure.
295 * \see eda_config_save().
297 * \note Scheme API: Implements the \%config-save! procedure in the
298 * (geda core config) module.
300 * \param cfg_s #EdaConfig smob of configuration context.
301 * \return \a cfg_s.
303 SCM_DEFINE (config_save_x, "%config-save!", 1, 0, 0,
304 (SCM cfg_s), "Save changes to a configuration context")
306 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
307 s_config_save_x);
309 EdaConfig *cfg = edascm_to_config (cfg_s);
310 GError *error = NULL;
311 if (!eda_config_save (cfg, &error)) {
312 error_from_gerror (s_config_load_x, &error);
314 return cfg_s;
317 /*! \brief Test whether a configuration context was changed since last save/load.
318 * \par Function Description
319 * Determine whether the configuration context \a cfg has been altered
320 * since it was last synchronised with the on-disk version by loading
321 * or saving it.
323 * \see eda_config_is_changed().
325 * \note Scheme API: Implements the \%config-changed? procedure in the
326 * (geda core config) module.
328 * \param cfg_s #EdaConfig smob of configuration context.
329 * \return #t if \a cfg_s has unsaved changes, #f otherwise.
331 SCM_DEFINE (config_changed_p, "%config-changed?", 1, 0, 0,
332 (SCM cfg_s),
333 "Test whether a configuration context was changed since last save/load.")
335 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
336 s_config_changed_p);
338 EdaConfig *cfg = edascm_to_config (cfg_s);
339 return eda_config_is_changed (cfg) ? SCM_BOOL_T : SCM_BOOL_F;
342 /*! \brief Get a configuration context's parent context.
343 * \par Function Description
344 * Return the parent context of the configuration context \a cfg, if
345 * it has one, or #f otherwise.
347 * \see eda_config_get_parent().
349 * \note Scheme API: Implements the \%config-parent procedure in the
350 * (geda core config) module.
352 * \param cfg_s #EdaConfig smob of configuration context.
353 * \return parent context of \a cfg_s, or #f.
355 SCM_DEFINE (config_parent, "%config-parent", 1, 0, 0,
356 (SCM cfg_s), "Get a configuration context's parent context.")
358 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
359 s_config_parent);
361 EdaConfig *cfg = edascm_to_config (cfg_s);
362 EdaConfig *parent = eda_config_get_parent (cfg);
363 return (parent == NULL) ? SCM_BOOL_F : edascm_from_config (parent);
366 /*! \brief Set a configuration context's parent context.
367 * \par Function Description
368 * Set the parent context of the configuration context \a cfg to \a
369 * parent. If \a parent is #f, sets \a cfg as having no parent
370 * context.
372 * \see eda_config_set_parent().
374 * \note Scheme API: Implements the \%set-config-parent! procedure in
375 * the (geda core config) module.
377 * \param cfg_s #EdaConfig smob of configuration context.
378 * \param parent_s #EdaConfig smob of new parent context, or #f.
379 * \return cfg_s.
381 SCM_DEFINE (set_config_parent_x, "%set-config-parent!", 2, 0, 0,
382 (SCM cfg_s, SCM parent_s), "Set a configuration context's parent context.")
384 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
385 s_set_config_parent_x);
386 SCM_ASSERT (scm_is_false (parent_s) || EDASCM_CONFIGP (parent_s), cfg_s,
387 SCM_ARG2, s_set_config_parent_x);
389 EdaConfig *cfg = edascm_to_config (cfg_s);
390 EdaConfig *parent = EDASCM_CONFIGP (parent_s) ? edascm_to_config (parent_s) : NULL;
391 eda_config_set_parent (cfg, parent);
392 return cfg_s;
395 /*! \brief Test if a configuration context is trusted.
396 * \par Function Description
397 * Tests if \a cfg_s is a "trusted" configuration context
398 * (i.e. if it is permitted as a source for risky configuration
399 * parameters such as system commands).
401 * \see eda_config_is_trusted().
403 * \note Scheme API: Implements the \%config-trusted? procedure in
404 * the (geda core config) module.
406 * \param cfg_s #EdaConfig smob of configuration context.
407 * \return #t if \a cfg_s is trusted, #f otherwise.
409 SCM_DEFINE (config_trusted_p, "%config-trusted?", 1, 0, 0,
410 (SCM cfg_s), "Test if a configuration context is trusted.")
412 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
413 s_config_trusted_p);
414 EdaConfig *cfg = edascm_to_config (cfg_s);
415 return eda_config_is_trusted (cfg) ? SCM_BOOL_T : SCM_BOOL_F;
418 /*! \brief Set whether a configuration context is trusted.
419 * \par Function Description
420 * Set whether the configuration context \a cfg_s is trusted as a
421 * source for risky configuration parameters.
423 * \see eda_config_set_trusted().
425 * \note Scheme API: Implements the \%set-config-trusted! procedure in
426 * the (geda core config) module.
428 * \param cfg_s #EdaConfig smob of configuration context.
429 * \param trusted_s #f if \a cfg_s is not to be trusted.
430 * \return cfg_s
432 SCM_DEFINE (set_config_trusted_x, "%set-config-trusted!", 2, 0, 0,
433 (SCM cfg_s, SCM trusted_s),
434 "Set whether configuration context is trusted.")
436 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
437 s_set_config_trusted_x);
439 EdaConfig *cfg = edascm_to_config (cfg_s);
440 eda_config_set_trusted (cfg, scm_is_true (trusted_s));
441 return cfg_s;
444 /*! \brief Get a list of available configuration groups.
445 * \par Function Description.
446 * Returns a list of the all groups available in \a cfg_s and its parent
447 * contexts.
449 * \see eda_config_get_groups().
451 * \note Scheme API: Implements the \%config-groups procedure in
452 * the (geda core config) module.
454 * \param cfg_s #EdaConfig smob of configuration context.
455 * \return a list of available group names as strings.
457 SCM_DEFINE (config_groups, "%config-groups", 1, 0, 0,
458 (SCM cfg_s),
459 "Get a list of available configuration groups.")
461 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
462 s_config_groups);
464 EdaConfig *cfg = edascm_to_config (cfg_s);
465 gsize i, len;
466 gchar **groups = eda_config_get_groups (cfg, &len);
467 SCM lst_s = SCM_EOL;
469 scm_dynwind_begin (0);
470 scm_dynwind_unwind_handler ((void (*)(void *)) g_strfreev,
471 groups, SCM_F_WIND_EXPLICITLY);
473 for (i = 0; i < len; i++) {
474 lst_s = scm_cons (scm_from_utf8_string (groups[i]), lst_s);
477 scm_dynwind_end ();
479 return scm_reverse_x (lst_s, SCM_EOL);
482 /*! \brief Test whether a configuration context has a particular group.
483 * \par Function Description
484 * Tests whether the configuration context \a cfg_s, or any of its
485 * parent contexts, contains the \a group_s.
487 * \see eda_config_has_group().
489 * \note Scheme API: Implements the \%config-has-group? procedure in
490 * the (geda core config) module.
492 * \param cfg_s #EdaConfig smob of configuration context.
493 * \param group_s Group name as a string.
494 * \return #t if \a cfg_s or any ancestor contains \a group, #f
495 * otherwise.
497 SCM_DEFINE (config_has_group_p, "%config-has-group?", 2, 0, 0,
498 (SCM cfg_s, SCM group_s),
499 "Test whether a configuration context has a particular group.")
501 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
502 s_config_has_group_p);
503 SCM_ASSERT (scm_is_string (group_s), group_s, SCM_ARG2,
504 s_config_has_group_p);
506 EdaConfig *cfg = edascm_to_config (cfg_s);
507 char *group = scm_to_utf8_string (group_s);
508 gboolean result = eda_config_has_group (cfg, group);
509 free (group);
510 return result ? SCM_BOOL_T : SCM_BOOL_F;
513 /*! \brief Get a list of available configuration keys.
514 * \par Function Description.
515 * Returns a list of the all keys available in \a cfg_s and \a
516 * group_s. If the \a group_s cannot be found, raises a
517 * 'config-error'.
519 * \see eda_config_get_keys().
521 * \note Scheme API: Implements the \%config-keys procedure in
522 * the (geda core config) module.
524 * \param cfg_s #EdaConfig smob of configuration context.
525 * \param group_s Group name as a string.
526 * \return a list of available key names as strings.
528 SCM_DEFINE (config_keys, "%config-keys", 2, 0, 0,
529 (SCM cfg_s, SCM group_s),
530 "Get a list of available configuration keys.")
532 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1,
533 s_config_keys);
534 SCM_ASSERT (scm_is_string (group_s), group_s, SCM_ARG2,
535 s_config_keys);
537 EdaConfig *cfg = edascm_to_config (cfg_s);
538 char *group = scm_to_utf8_string (group_s);
539 gsize i, len;
540 GError *error = NULL;
541 gchar **keys = eda_config_get_keys (cfg, group, &len, &error);
542 SCM lst_s = SCM_EOL;
544 free (group);
545 if (keys == NULL) error_from_gerror (s_config_keys, &error);
547 scm_dynwind_begin (0);
548 scm_dynwind_unwind_handler ((void (*)(void *)) g_strfreev,
549 keys, SCM_F_WIND_EXPLICITLY);
551 for (i = 0; i < len; i++) {
552 lst_s = scm_cons (scm_from_utf8_string (keys[i]), lst_s);
555 scm_dynwind_end ();
557 return scm_reverse_x (lst_s, SCM_EOL);
560 /*! \brief Get the originating context for a configuration parameter.
561 * \par Function Description
562 * Returns the configuration context (either \a cfg_s or one of its
563 * parent contexts) in which the configuration parameter with the
564 * given \a group_s and \a key_s has a value specified. If the group
565 * or key cannot be found, raises a 'config-error'.
567 * \see eda_config_get_source().
569 * \note Scheme API: Implements the \%config-source procedure in the
570 * (geda core config module).
572 * \param cfg_s #EdaConfig smob of configuration context.
573 * \param group_s Group name as a string.
574 * \param key_s Key name as a string.
575 * \return #EdaConfig smob of originating context of parameter.
577 SCM_DEFINE (config_source, "%config-source", 3, 0, 0,
578 (SCM cfg_s, SCM group_s, SCM key_s),
579 "Get the originating context for a configuration parameter")
581 ASSERT_CFG_GROUP_KEY (s_config_source);
583 scm_dynwind_begin (0);
584 EdaConfig *cfg = edascm_to_config (cfg_s);
585 char *group = scm_to_utf8_string (group_s);
586 scm_dynwind_free (group);
587 char *key = scm_to_utf8_string (key_s);
588 scm_dynwind_free (key);
589 GError *error = NULL;
590 EdaConfig *src = eda_config_get_source (cfg, group, key, &error);
591 if (src == NULL) error_from_gerror (s_config_source, &error);
592 scm_dynwind_end ();
593 return edascm_from_config (src);
596 /*! \brief Get a configuration parameter's value as a string.
597 * \par Function Description
598 * Get the value of the configuration parameter specified by \a
599 * group_s and \a key_s in the configuration context \a cfg_s, as a
600 * string.
602 * \see eda_config_get_string().
604 * \note Scheme API: Implements the \%config-string procedure in the
605 * (geda core config) module.
607 * \param cfg_s #EdaConfig smob of configuration context.
608 * \param group_s Group name as a string.
609 * \param key_s Key name as a string.
610 * \return configuration value as a string.
612 SCM_DEFINE (config_string, "%config-string", 3, 0, 0,
613 (SCM cfg_s, SCM group_s, SCM key_s),
614 "Get a configuration parameter's value as a string.")
616 ASSERT_CFG_GROUP_KEY (s_config_string);
618 scm_dynwind_begin (0);
619 EdaConfig *cfg = edascm_to_config (cfg_s);
620 char *group = scm_to_utf8_string (group_s);
621 scm_dynwind_free (group);
622 char *key = scm_to_utf8_string (key_s);
623 scm_dynwind_free (key);
624 GError *error = NULL;
625 gchar *value = eda_config_get_string (cfg, group, key, &error);
626 if (value == NULL) error_from_gerror (s_config_string, &error);
627 scm_dynwind_unwind_handler ((void (*)(void *)) g_free, value,
628 SCM_F_WIND_EXPLICITLY);
629 SCM value_s = scm_from_utf8_string (value);
630 scm_dynwind_end ();
631 return value_s;
634 /*! \brief Get a configuration parameter's value as a boolean.
635 * \par Function Description
636 * Get the value of the configuration parameter specified by \a
637 * group_s and \a key_s in the configuration context \a cfg_s, as a
638 * boolean.
640 * \see eda_config_get_boolean().
642 * \note Scheme API: Implements the \%config-boolean procedure in the
643 * (geda core config) module.
645 * \param cfg_s #EdaConfig smob of configuration context.
646 * \param group_s Group name as a string.
647 * \param key_s Key name as a string.
648 * \return configuration value as a boolean.
650 SCM_DEFINE (config_boolean, "%config-boolean", 3, 0, 0,
651 (SCM cfg_s, SCM group_s, SCM key_s),
652 "Get a configuration parameter's value as a boolean.")
654 ASSERT_CFG_GROUP_KEY (s_config_boolean);
656 scm_dynwind_begin (0);
657 EdaConfig *cfg = edascm_to_config (cfg_s);
658 char *group = scm_to_utf8_string (group_s);
659 scm_dynwind_free (group);
660 char *key = scm_to_utf8_string (key_s);
661 scm_dynwind_free (key);
662 GError *error = NULL;
663 gboolean value = eda_config_get_boolean (cfg, group, key, &error);
664 if (error != NULL) error_from_gerror (s_config_boolean, &error);
665 scm_dynwind_end ();
666 return value ? SCM_BOOL_T : SCM_BOOL_F;
669 /*! \brief Get a configuration parameter's value as an integer.
670 * \par Function Description
671 * Get the value of the configuration parameter specified by \a
672 * group_s and \a key_s in the configuration context \a cfg_s, as a
673 * integer.
675 * \see eda_config_get_int().
677 * \note Scheme API: Implements the \%config-int procedure in the
678 * (geda core config) module.
680 * \param cfg_s #EdaConfig smob of configuration context.
681 * \param group_s Group name as a string.
682 * \param key_s Key name as a string.
683 * \return configuration value as an integer.
685 SCM_DEFINE (config_int, "%config-int", 3, 0, 0,
686 (SCM cfg_s, SCM group_s, SCM key_s),
687 "Get a configuration parameter's value as an integer.")
689 ASSERT_CFG_GROUP_KEY (s_config_int);
691 scm_dynwind_begin (0);
692 EdaConfig *cfg = edascm_to_config (cfg_s);
693 char *group = scm_to_utf8_string (group_s);
694 scm_dynwind_free (group);
695 char *key = scm_to_utf8_string (key_s);
696 scm_dynwind_free (key);
697 GError *error = NULL;
698 gint value = eda_config_get_int (cfg, group, key, &error);
699 if (error != NULL) error_from_gerror (s_config_int, &error);
700 scm_dynwind_end ();
701 return scm_from_int (value);
704 /*! \brief Get a configuration parameter's value as a real.
705 * \par Function Description
706 * Get the value of the configuration parameter specified by \a
707 * group_s and \a key_s in the configuration context \a cfg_s, as an
708 * inexact real number.
710 * \see eda_config_get_double().
712 * \note Scheme API: Implements the \%config-real procedure in the
713 * (geda core config) module.
715 * \param cfg_s #EdaConfig smob of configuration context.
716 * \param group_s Group name as a string.
717 * \param key_s Key name as a string.
718 * \return configuration value as an inexact real.
720 SCM_DEFINE (config_real, "%config-real", 3, 0, 0,
721 (SCM cfg_s, SCM group_s, SCM key_s),
722 "Get a configuration parameter's value as a real.")
724 ASSERT_CFG_GROUP_KEY (s_config_real);
726 scm_dynwind_begin (0);
727 EdaConfig *cfg = edascm_to_config (cfg_s);
728 char *group = scm_to_utf8_string (group_s);
729 scm_dynwind_free (group);
730 char *key = scm_to_utf8_string (key_s);
731 scm_dynwind_free (key);
732 GError *error = NULL;
733 gdouble value = eda_config_get_double (cfg, group, key, &error);
734 if (error != NULL) error_from_gerror (s_config_real, &error);
735 scm_dynwind_end ();
736 return scm_from_double (value);
739 /*! \brief Get a configuration parameter's value as a string list.
740 * \par Function Description
741 * Get the value of the configuration parameter specified by \a
742 * group_s and \a key_s in the configuration context \a cfg_s, as a
743 * list of strings.
745 * \see eda_config_get_string_list().
747 * \note Scheme API: Implements the \%config-string-list procedure in
748 * the (geda core config) module.
750 * \param cfg_s #EdaConfig smob of configuration context.
751 * \param group_s Group name as a string.
752 * \param key_s Key name as a string.
753 * \return configuration value as a list of strings.
755 SCM_DEFINE (config_string_list, "%config-string-list", 3, 0, 0,
756 (SCM cfg_s, SCM group_s, SCM key_s),
757 "Get a configuration parameter's value as a string list.")
759 ASSERT_CFG_GROUP_KEY (s_config_string_list);
761 scm_dynwind_begin (0);
762 EdaConfig *cfg = edascm_to_config (cfg_s);
763 char *group = scm_to_utf8_string (group_s);
764 scm_dynwind_free (group);
765 char *key = scm_to_utf8_string (key_s);
766 scm_dynwind_free (key);
767 gsize length, i;
768 GError *error = NULL;
769 gchar **value = eda_config_get_string_list (cfg, group, key,
770 &length, &error);
771 if (value == NULL) error_from_gerror (s_config_string_list, &error);
772 scm_dynwind_unwind_handler ((void (*)(void *)) g_strfreev, value,
773 SCM_F_WIND_EXPLICITLY);
774 SCM value_s = SCM_EOL;
775 for (i = 0; i < length; i++) {
776 value_s = scm_cons (scm_from_utf8_string (value[i]), value_s);
778 scm_dynwind_end ();
779 return scm_reverse_x (value_s, SCM_EOL);
782 /*! \brief Get a configuration parameter's value as a boolean list.
783 * \par Function Description
784 * Get the value of the configuration parameter specified by \a
785 * group_s and \a key_s in the configuration context \a cfg_s, as a
786 * list of booleans.
788 * \see eda_config_get_boolean_list().
790 * \note Scheme API: Implements the \%config-boolean-list procedure in
791 * the (geda core config) module.
793 * \param cfg_s #EdaConfig smob of configuration context.
794 * \param group_s Group name as a string.
795 * \param key_s Key name as a string.
796 * \return configuration value as a list of booleans.
798 SCM_DEFINE (config_boolean_list, "%config-boolean-list", 3, 0, 0,
799 (SCM cfg_s, SCM group_s, SCM key_s),
800 "Get a configuration parameter's value as a boolean list.")
802 ASSERT_CFG_GROUP_KEY (s_config_boolean_list);
804 scm_dynwind_begin (0);
805 EdaConfig *cfg = edascm_to_config (cfg_s);
806 char *group = scm_to_utf8_string (group_s);
807 scm_dynwind_free (group);
808 char *key = scm_to_utf8_string (key_s);
809 scm_dynwind_free (key);
810 gsize length, i;
811 GError *error = NULL;
812 gboolean *value = eda_config_get_boolean_list (cfg, group, key,
813 &length, &error);
814 if (value == NULL) error_from_gerror (s_config_boolean_list, &error);
815 scm_dynwind_unwind_handler (g_free, value,
816 SCM_F_WIND_EXPLICITLY);
817 SCM value_s = SCM_EOL;
818 for (i = 0; i < length; i++) {
819 value_s = scm_cons (value[i] ? SCM_BOOL_T : SCM_BOOL_F, value_s);
821 scm_dynwind_end ();
822 return scm_reverse_x (value_s, SCM_EOL);
825 /*! \brief Get a configuration parameter's value as an integer list.
826 * \par Function Description
827 * Get the value of the configuration parameter specified by \a
828 * group_s and \a key_s in the configuration context \a cfg_s, as a
829 * list of integers.
831 * \see eda_config_get_int_list().
833 * \note Scheme API: Implements the \%config-int-list procedure in
834 * the (geda core config) module.
836 * \param cfg_s #EdaConfig smob of configuration context.
837 * \param group_s Group name as a string.
838 * \param key_s Key name as a string.
839 * \return configuration value as a list of integers.
841 SCM_DEFINE (config_int_list, "%config-int-list", 3, 0, 0,
842 (SCM cfg_s, SCM group_s, SCM key_s),
843 "Get a configuration parameter's value as an integer list.")
845 ASSERT_CFG_GROUP_KEY (s_config_int_list);
847 scm_dynwind_begin (0);
848 EdaConfig *cfg = edascm_to_config (cfg_s);
849 char *group = scm_to_utf8_string (group_s);
850 scm_dynwind_free (group);
851 char *key = scm_to_utf8_string (key_s);
852 scm_dynwind_free (key);
853 gsize length, i;
854 GError *error = NULL;
855 gint *value = eda_config_get_int_list (cfg, group, key,
856 &length, &error);
857 if (value == NULL) error_from_gerror (s_config_int_list, &error);
858 scm_dynwind_unwind_handler (g_free, value,
859 SCM_F_WIND_EXPLICITLY);
860 SCM value_s = SCM_EOL;
861 for (i = 0; i < length; i++) {
862 value_s = scm_cons (scm_from_int (value[i]), value_s);
864 scm_dynwind_end ();
865 return scm_reverse_x (value_s, SCM_EOL);
868 /*! \brief Get a configuration parameter's value as a list of reals.
869 * \par Function Description
870 * Get the value of the configuration parameter specified by \a
871 * group_s and \a key_s in the configuration context \a cfg_s, as a
872 * list of inexact real numbers.
874 * \see eda_config_get_double_list().
876 * \note Scheme API: Implements the \%config-real-list procedure in
877 * the (geda core config) module.
879 * \param cfg_s #EdaConfig smob of configuration context.
880 * \param group_s Group name as a string.
881 * \param key_s Key name as a string.
882 * \return configuration value as a list of inexact real numbers.
884 SCM_DEFINE (config_real_list, "%config-real-list", 3, 0, 0,
885 (SCM cfg_s, SCM group_s, SCM key_s),
886 "Get a configuration parameter's value as a list of reals.")
888 ASSERT_CFG_GROUP_KEY (s_config_real_list);
890 scm_dynwind_begin (0);
891 EdaConfig *cfg = edascm_to_config (cfg_s);
892 char *group = scm_to_utf8_string (group_s);
893 scm_dynwind_free (group);
894 char *key = scm_to_utf8_string (key_s);
895 scm_dynwind_free (key);
896 gsize length, i;
897 GError *error = NULL;
898 gdouble *value = eda_config_get_double_list (cfg, group, key,
899 &length, &error);
900 if (value == NULL) error_from_gerror (s_config_real_list, &error);
901 scm_dynwind_unwind_handler (g_free, value,
902 SCM_F_WIND_EXPLICITLY);
903 SCM value_s = SCM_EOL;
904 for (i = 0; i < length; i++) {
905 value_s = scm_cons (scm_from_double (value[i]), value_s);
907 scm_dynwind_end ();
908 return scm_reverse_x (value_s, SCM_EOL);
911 /*! \brief Set a configuration parameter's value.
912 * \par Function Description
913 * Set the value of the configuration parameter specified by \a
914 * group_s and \a key_s in the configuration context \a cfg_s to \a
915 * value_s. The supported types for \a value_s are strings, integers,
916 * real numbers, and booleans, along with homogenous lists of strings,
917 * integers, real numbers or booleans.
919 * \note Scheme API: Implements the \%set-config! procedure in the
920 * (geda core config) module.
922 * \param cfg_s #EdaConfig smob of configuration context.
923 * \param group_s Group name as a string.
924 * \param key_s Key name as a string.
925 * \param value_s New value for parameter.
926 * \return \a cfg_s.
928 SCM_DEFINE (set_config_x, "%set-config!", 4, 0, 0,
929 (SCM cfg_s, SCM group_s, SCM key_s, SCM value_s),
930 "Set a configuration parameter's value.")
932 ASSERT_CFG_GROUP_KEY (s_set_config_x);
934 scm_dynwind_begin (0);
935 EdaConfig *cfg = edascm_to_config (cfg_s);
936 char *group = scm_to_utf8_string (group_s);
937 scm_dynwind_free (group);
938 char *key = scm_to_utf8_string (key_s);
939 scm_dynwind_free (key);
941 /* Figure out what value is */
942 if (scm_is_string (value_s)) {
943 char *value = scm_to_utf8_string (value_s);
944 scm_dynwind_free (value);
945 eda_config_set_string (cfg, group, key, value);
946 } else if (scm_is_bool (value_s)) {
947 gboolean value = scm_is_true (value_s);
948 eda_config_set_boolean (cfg, group, key, value);
949 } else if (scm_is_integer (value_s) && scm_is_true (scm_exact_p (value_s))) {
950 gint value = scm_to_int (value_s);
951 eda_config_set_int (cfg, group, key, value);
952 } else if (scm_is_real (value_s)) {
953 gdouble value = scm_to_double (value_s);
954 eda_config_set_double (cfg, group, key, value);
956 } else if (scm_is_true (scm_list_p (value_s))) {
957 /* Find out what sort of list it is, then process it accordingly. */
958 SCM first_s = scm_car (value_s);
959 int len = scm_to_int (scm_length (value_s));
960 SCM curr_s;
961 int i = 0;
963 if (scm_is_string (first_s)) {
964 gchar **value = g_new0 (gchar *, len + 1); /* null-terminated! */
965 scm_dynwind_unwind_handler ((void (*)(void *)) g_strfreev, value,
966 SCM_F_WIND_EXPLICITLY);
967 for (curr_s = value_s; !scm_is_null (curr_s); curr_s = scm_cdr (curr_s)) {
968 char *tmp = scm_to_utf8_string (scm_car (curr_s));
969 value [i++] = g_strdup (tmp);
970 free (tmp);
972 eda_config_set_string_list (cfg, group, key,
973 (const gchar * const *) value, len);
975 } else if (scm_is_bool (first_s)) {
976 gboolean *value = g_new0 (gboolean, len);
977 scm_dynwind_unwind_handler (g_free, value, SCM_F_WIND_EXPLICITLY);
978 for (curr_s = value_s; !scm_is_null (curr_s); curr_s = scm_cdr (curr_s)) {
979 value[i++] = scm_is_true (scm_car (curr_s));
981 eda_config_set_boolean_list (cfg, group, key, value, len);
983 } else if (scm_is_integer (first_s)
984 && scm_is_true (scm_exact_p (first_s))) {
985 gint *value = g_new0 (gint, len);
986 scm_dynwind_unwind_handler (g_free, value, SCM_F_WIND_EXPLICITLY);
987 for (curr_s = value_s; !scm_is_null (curr_s); curr_s = scm_cdr (curr_s)) {
988 value[i++] = scm_to_int (scm_car (curr_s));
990 eda_config_set_int_list (cfg, group, key, value, len);
992 } else if (scm_is_real (first_s)) {
993 gdouble *value = g_new0 (gdouble, len);
994 scm_dynwind_unwind_handler (g_free, value, SCM_F_WIND_EXPLICITLY);
995 for (curr_s = value_s; !scm_is_null (curr_s); curr_s = scm_cdr (curr_s)) {
996 value[i++] = scm_to_double (scm_car (curr_s));
998 eda_config_set_double_list (cfg, group, key, value, len);
1000 } else {
1001 scm_wrong_type_arg (s_set_config_x, SCM_ARG4, value_s);
1004 } else {
1005 scm_wrong_type_arg (s_set_config_x, SCM_ARG4, value_s);
1008 scm_remember_upto_here_1 (value_s);
1009 scm_dynwind_end ();
1010 return cfg_s;
1013 /*! \brief Dispatch to a Scheme configuration change event handler.
1014 * \par Function Description
1015 * Dispatcher function used by the Scheme API to run Scheme procedures
1016 * when a configuration change occurs.
1018 static void
1019 edascm_config_event_dispatcher (EdaConfig *cfg, const char *group,
1020 const char *key, void *user_data)
1022 SCM proc_s = SCM_PACK ((scm_t_bits) user_data);
1023 SCM expr = scm_list_4 (proc_s,
1024 edascm_from_config (cfg),
1025 scm_from_utf8_string (group),
1026 scm_from_utf8_string (key));
1028 g_scm_eval_protected (expr, scm_interaction_environment ());
1029 scm_remember_upto_here_1 (expr);
1032 /*! \brief Add a configuration change event handler.
1033 * \par Function Description
1034 * Add \a proc_s as a function to be called when configuration is
1035 * modified in the context \a cfg. \a proc_s will be called with the
1036 * following prototype:
1038 * \code
1039 * (proc CFG GROUP KEY)
1040 * \endcode
1042 * If \a proc_s causes an Scheme error to be raised, the error will be
1043 * caught and logged.
1045 * \note Scheme API: Implements the \%add-config-event! procedure in the
1046 * (geda core config) module.
1048 * \param cfg_s #EdaConfig smob of configuration context.
1049 * \param proc_s Procedure to add as configuration change handler.
1050 * \return \a cfg_s.
1052 SCM_DEFINE (add_config_event_x, "%add-config-event!", 2, 0, 0,
1053 (SCM cfg_s, SCM proc_s),
1054 "Add a configuration change event handler.")
1056 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1, s_add_config_event_x);
1057 SCM_ASSERT (scm_is_true (scm_procedure_p (proc_s)),
1058 proc_s, SCM_ARG2, s_add_config_event_x);
1060 EdaConfig *cfg = edascm_to_config (cfg_s);
1062 /* Test if proc_s was already connected. */
1063 guint signal_id = g_signal_lookup ("config-changed", EDA_TYPE_CONFIG);
1064 gulong handler_id =
1065 g_signal_handler_find (cfg,
1066 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
1067 | G_SIGNAL_MATCH_ID,
1068 signal_id,
1070 NULL,
1071 edascm_config_event_dispatcher,
1072 (gpointer) SCM_UNPACK (proc_s));
1073 if (handler_id) {
1074 return cfg_s;
1077 /* Protect proc_s against garbage collection */
1078 g_signal_connect (cfg, "config-changed",
1079 G_CALLBACK (edascm_config_event_dispatcher),
1080 (gpointer) SCM_UNPACK (scm_gc_protect_object (proc_s)));
1081 return cfg_s;
1084 /*! \brief Remove a configuration change event handler.
1085 * \par Function Description
1086 * Stop \a proc_s from being called when configuration is modified in
1087 * the context \a cfg.
1089 * \note Scheme API: Implements the \%remove-config-event! procedure
1090 * in the (geda core config) module.
1092 * \param cfg_s #EdaConfig smob of configuration context.
1093 * \param proc_s Procedure to remove as configuration change handler.
1094 * \return \a cfg_s.
1096 SCM_DEFINE (remove_config_event_x, "%remove-config-event!", 2, 0, 0,
1097 (SCM cfg_s, SCM proc_s),
1098 "Remove a configuration change event handler.")
1100 SCM_ASSERT (EDASCM_CONFIGP (cfg_s), cfg_s, SCM_ARG1, s_add_config_event_x);
1101 SCM_ASSERT (scm_is_true (scm_procedure_p (proc_s)),
1102 proc_s, SCM_ARG2, s_add_config_event_x);
1104 EdaConfig *cfg = edascm_to_config (cfg_s);
1105 guint signal_id = g_signal_lookup ("config-changed", EDA_TYPE_CONFIG);
1106 guint found =
1107 g_signal_handlers_disconnect_matched (cfg,
1108 G_SIGNAL_MATCH_FUNC
1109 | G_SIGNAL_MATCH_DATA
1110 | G_SIGNAL_MATCH_ID,
1111 signal_id,
1113 NULL,
1114 edascm_config_event_dispatcher,
1115 (gpointer) SCM_UNPACK (proc_s));
1116 g_warn_if_fail (found < 2);
1117 if (found) {
1118 scm_gc_unprotect_object (proc_s);
1120 return cfg_s;
1124 * \brief Create the (geda core config) Scheme module.
1125 * \par Function Description
1126 * Defines procedures in the (geda core config) module. The module can
1127 * be accessed using (use-modules (geda core config)).
1129 static void
1130 init_module_geda_core_config ()
1132 /* Register the functions and symbols */
1133 #include "scheme_config.x"
1135 /* Add them to the module's public definitions. */
1136 scm_c_export (s_default_config_context,
1137 s_system_config_context,
1138 s_user_config_context,
1139 s_path_config_context,
1140 s_config_filename,
1141 s_config_load_x,
1142 s_config_loaded_p,
1143 s_config_save_x,
1144 s_config_changed_p,
1145 s_config_parent,
1146 s_set_config_parent_x,
1147 s_config_trusted_p,
1148 s_set_config_trusted_x,
1149 s_config_groups,
1150 s_config_has_group_p,
1151 s_config_keys,
1152 s_config_source,
1153 s_config_string,
1154 s_config_boolean,
1155 s_config_int,
1156 s_config_real,
1157 s_config_string_list,
1158 s_config_boolean_list,
1159 s_config_int_list,
1160 s_config_real_list,
1161 s_set_config_x,
1162 s_add_config_event_x,
1163 s_remove_config_event_x,
1164 NULL);
1168 * \brief Initialise the basic gEDA configuration manipulation procedures.
1169 * \par Function Description
1170 * Registers some Scheme procedures for working with #EdaConfig
1171 * smobs. Should only be called by edascm_init().
1173 void
1174 edascm_init_config ()
1176 /* Define the (geda core object) module */
1177 scm_c_define_module ("geda core config",
1178 init_module_geda_core_config,
1179 NULL);