1 /* gEDA - GPL Electronic Design Automation
2 * gnetlist - gEDA Netlist
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <sys/param.h>
27 #include <sys/types.h>
40 #include <libgeda/libgeda.h>
41 #include <libgeda/libgedaguile.h>
43 #include "../include/globals.h"
44 #include "../include/prototype.h"
45 #include "../include/gettext.h"
47 #ifdef HAVE_LIBDMALLOC
51 void gnetlist_quit(void)
55 s_rename_destroy_all();
56 /* o_text_freeallfonts(); */
58 /* Free GSList *backend_params */
59 g_slist_free (backend_params
);
61 g_slist_free (input_files
);
65 /* \brief Print a list of available backends.
66 * \par Function Description
67 * Prints a list of available gnetlist backends by searching for files
68 * in each of the directories in the current Guile %load-path. A file
69 * is considered to be a gnetlist backend if its basename begins with
70 * "gnet-" and ends with ".scm".
72 * \param pr_current Current #TOPLEVEL structure.
75 gnetlist_backends (TOPLEVEL
*pr_current
)
78 GList
*backend_names
= NULL
, *iter
= NULL
;
80 /* Look up the current Guile %load-path */
81 s_load_path
= scm_variable_ref (scm_c_lookup ("%load-path"));
83 for ( ; s_load_path
!= SCM_EOL
; s_load_path
= scm_cdr (s_load_path
)) {
84 SCM s_dir_name
= scm_car (s_load_path
);
87 struct dirent
*dentry
;
89 /* Get directory name from Scheme */
90 g_assert (scm_is_true (scm_list_p (s_load_path
))); /* Sanity check */
91 g_assert (scm_is_string (scm_car (s_load_path
))); /* Sanity check */
92 dir_name
= scm_to_utf8_string (s_dir_name
);
95 dptr
= opendir (dir_name
);
97 g_warning (_("Can't open directory %s: %s\n"),
98 dir_name
, strerror (errno
));
106 dentry
= readdir (dptr
);
107 if (dentry
== NULL
) break;
109 /* Check that filename has the right format to be a gnetlist
111 if (!(g_str_has_prefix (dentry
->d_name
, "gnet-")
112 && g_str_has_suffix (dentry
->d_name
, ".scm")))
115 /* Copy filename and remove prefix & suffix. Add to list of
117 name
= g_strdup (dentry
->d_name
+ 5);
118 name
[strlen(name
)-4] = '\0';
119 backend_names
= g_list_prepend (backend_names
, name
);
122 /* Close directory */
126 /* Sort the list of backends */
127 backend_names
= g_list_sort (backend_names
, (GCompareFunc
) strcmp
);
129 printf (_("List of available backends: \n\n"));
131 for (iter
= backend_names
; iter
!= NULL
; iter
= g_list_next (iter
)) {
132 printf ("%s\n", (char *) iter
->data
);
136 scm_remember_upto_here_1 (s_load_path
);
140 void main_prog(void *closure
, int argc
, char *argv
[])
148 TOPLEVEL
*pr_current
;
150 /* set default output filename */
151 output_filename
= g_strdup("output.net");
153 argv_index
= parse_commandline(argc
, argv
);
154 cwd
= g_get_current_dir();
156 scm_set_program_arguments (argc
, argv
, NULL
);
158 /* this is a kludge to make sure that spice mode gets set */
159 /* Hacked by SDB to allow spice netlisters of arbitrary name
160 * as long as they begin with "spice". For example, this spice
161 * netlister is valid: "spice-sdb".
164 if (strncmp(guile_proc
, "spice", 5) == 0) {
165 netlist_mode
= SPICE
;
171 /* create log file right away */
172 /* even if logging is enabled */
173 s_log_init ("gnetlist");
176 "gEDA/gnetlist version %s%s.%s\n"
177 "gEDA/gnetlist comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n"
178 "This is free software, and you are welcome to redistribute it under certain\n"
179 "conditions; please see the COPYING file for more details.\n\n"),
180 PREPEND_VERSION_STRING
, PACKAGE_DOTTED_VERSION
, PACKAGE_DATE_VERSION
);
182 #if defined(__MINGW32__) && defined(DEBUG)
183 fprintf(stderr
, _("This is the MINGW32 port.\n\n"));
186 /* register guile (scheme) functions */
189 scm_dynwind_begin (0);
190 pr_current
= s_toplevel_new ();
191 edascm_dynwind_toplevel (pr_current
);
193 /* Evaluate Scheme expressions that need to be run before rc files
195 scm_eval (pre_rc_list
, scm_current_module ());
197 g_rc_parse (pr_current
, argv
[0], "gnetlistrc", rc_filename
);
198 /* immediately setup user params */
199 i_vars_init_gnetlist_defaults ();
200 i_vars_set (pr_current
);
205 gnetlist_backends(pr_current
);
209 /* Evaluate the first set of Scheme expressions before we load any
211 scm_eval (pre_backend_list
, scm_current_module ());
214 while (argv
[i
] != NULL
) {
217 if (g_path_is_absolute(argv
[i
])) {
218 /* Path is already absolute so no need to do any concat of cwd */
219 filename
= g_strdup (argv
[i
]);
221 filename
= g_build_filename (cwd
, argv
[i
], NULL
);
225 s_log_message (_("Loading schematic [%s]\n"), filename
);
226 printf (_("Loading schematic [%s]\n"), filename
);
229 s_page_goto (pr_current
, s_page_new (pr_current
, filename
));
231 if (!f_open (pr_current
, pr_current
->page_current
, filename
, &err
)) {
232 g_warning ("%s\n", err
->message
);
233 fprintf (stderr
, _("ERROR: Failed to load '%s': %s\n"),
234 filename
, err
->message
);
239 /* collect input filenames for backend use */
240 input_files
= g_slist_append(input_files
, argv
[i
]);
246 /* Change back to the directory where we started. This is done */
247 /* since gnetlist is a command line utility and will deposit its output */
248 /* in the current directory. Having the output go to a different */
249 /* directory will confuse the user (confused me, at first). */
251 /* Error occured with chdir */
252 #warning FIME: What do we do?
254 /* free(cwd); - Defered; see below */
256 if (argv
[argv_index
] == NULL
) {
258 "ERROR: No schematics files specified for processing.\n"
259 "\nRun `%s --help' for more information.\n"), argv
[0]);
264 s_page_print_all(pr_current
);
267 /* Load basic gnetlist functions */
268 scm_primitive_load_path (scm_from_utf8_string ("gnetlist.scm"));
273 /* Search for backend scm file in load path */
274 str
= g_strdup_printf("gnet-%s.scm", guile_proc
);
275 s_backend_path
= scm_sys_search_load_path (scm_from_locale_string (str
));
278 /* If it couldn't be found, fail. */
279 if (scm_is_false (s_backend_path
)) {
281 "ERROR: Could not find backend `%s' in load path.\n"
282 "\nRun `%s --list-backends' for a full list of available backends.\n"),
283 guile_proc
, argv
[0]);
287 /* Load backend code. */
288 scm_primitive_load (s_backend_path
);
290 /* Evaluate second set of Scheme expressions. */
291 scm_eval (post_backend_list
, scm_current_module ());
295 s_traverse_start(pr_current
);
297 /* Change back to the directory where we started AGAIN. This is done */
298 /* because the s_traverse functions can change the Current Working Directory. */
300 /* Error occured with chdir */
301 #warning FIXME: What do we do?
305 /* Run post-traverse code. */
306 scm_primitive_load_path (scm_from_utf8_string ("gnetlist-post.scm"));
308 if (interactive_mode
) {
309 scm_c_eval_string ("(set-repl-prompt! \"gnetlist> \")");
311 } else if (guile_proc
) {
312 /* check size here hack */
313 str
= g_strdup_printf ("(%s \"%s\")", guile_proc
, output_filename
);
314 scm_c_eval_string (str
);
316 /* gh_eval_str_with_stack_saving_handler (input_str); */
319 _("You gave neither backend to execute nor interactive mode!\n"));
327 int main(int argc
, char *argv
[])
329 scm_boot_guile (argc
, argv
, main_prog
, 0);