1 /* gEDA - GPL Electronic Design Automation
2 * gnetlist - gEDA Netlist
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2020 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 void gnetlist_quit(void)
51 s_rename_destroy_all();
52 /* o_text_freeallfonts(); */
54 /* Free GSList *backend_params */
55 g_slist_free (backend_params
);
57 g_slist_free (input_files
);
61 /* \brief Print a list of available backends.
62 * \par Function Description
63 * Prints a list of available gnetlist backends by searching for files
64 * in each of the directories in the current Guile %load-path. A file
65 * is considered to be a gnetlist backend if its basename begins with
66 * "gnet-" and ends with ".scm".
68 * \param pr_current Current #TOPLEVEL structure.
71 gnetlist_backends (TOPLEVEL
*pr_current
)
74 GList
*backend_names
= NULL
, *iter
= NULL
;
76 /* Look up the current Guile %load-path */
77 s_load_path
= scm_variable_ref (scm_c_lookup ("%load-path"));
79 for ( ; !scm_is_null (s_load_path
); s_load_path
= scm_cdr (s_load_path
)) {
80 SCM s_dir_name
= scm_car (s_load_path
);
83 struct dirent
*dentry
;
85 /* Get directory name from Scheme */
86 g_assert (scm_is_true (scm_list_p (s_load_path
))); /* Sanity check */
87 g_assert (scm_is_string (scm_car (s_load_path
))); /* Sanity check */
88 dir_name
= scm_to_utf8_string (s_dir_name
);
91 dptr
= opendir (dir_name
);
93 g_warning (_("Can't open directory %s: %s\n"),
94 dir_name
, strerror (errno
));
102 dentry
= readdir (dptr
);
103 if (dentry
== NULL
) break;
105 /* Check that filename has the right format to be a gnetlist
107 if (!(g_str_has_prefix (dentry
->d_name
, "gnet-")
108 && g_str_has_suffix (dentry
->d_name
, ".scm")))
111 /* Copy filename and remove prefix & suffix. Add to list of
113 name
= g_strdup (dentry
->d_name
+ 5);
114 name
[strlen(name
)-4] = '\0';
115 backend_names
= g_list_prepend (backend_names
, name
);
118 /* Close directory */
122 /* Sort the list of backends */
123 backend_names
= g_list_sort (backend_names
, (GCompareFunc
) strcmp
);
125 printf (_("List of available backends: \n\n"));
127 for (iter
= backend_names
; iter
!= NULL
; iter
= g_list_next (iter
)) {
128 printf ("%s\n", (char *) iter
->data
);
132 scm_remember_upto_here_1 (s_load_path
);
136 void main_prog(void *closure
, int argc
, char *argv
[])
144 TOPLEVEL
*pr_current
;
146 /* set default output filename */
147 output_filename
= g_strdup("output.net");
149 argv_index
= parse_commandline(argc
, argv
);
150 cwd
= g_get_current_dir();
152 scm_set_program_arguments (argc
, argv
, NULL
);
154 /* this is a kludge to make sure that spice mode gets set */
155 /* Hacked by SDB to allow spice netlisters of arbitrary name
156 * as long as they begin with "spice". For example, this spice
157 * netlister is valid: "spice-sdb".
160 if (strncmp(guile_proc
, "spice", 5) == 0) {
161 netlist_mode
= SPICE
;
167 /* create log file right away */
168 /* even if logging is enabled */
169 s_log_init ("gnetlist");
172 "gEDA/gnetlist-legacy version %s%s.%s\n"
173 "gEDA/gnetlist-legacy comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n"
174 "This is free software, and you are welcome to redistribute it under certain\n"
175 "conditions; please see the COPYING file for more details.\n\n"),
176 PREPEND_VERSION_STRING
, PACKAGE_DOTTED_VERSION
, PACKAGE_DATE_VERSION
);
178 #if defined(__MINGW32__) && defined(DEBUG)
179 fprintf(stderr
, _("This is the MINGW32 port.\n\n"));
182 /* register guile (scheme) functions */
185 scm_dynwind_begin (0);
186 pr_current
= s_toplevel_new ();
187 edascm_dynwind_toplevel (pr_current
);
189 /* Evaluate Scheme expressions that need to be run before rc files
191 scm_eval (pre_rc_list
, scm_current_module ());
193 g_rc_parse (pr_current
, argv
[0], "gnetlistrc", rc_filename
);
194 /* immediately setup user params */
195 i_vars_set (pr_current
);
200 gnetlist_backends(pr_current
);
204 /* Evaluate the first set of Scheme expressions before we load any
206 scm_eval (pre_backend_list
, scm_current_module ());
209 while (argv
[i
] != NULL
) {
212 if (g_path_is_absolute(argv
[i
])) {
213 /* Path is already absolute so no need to do any concat of cwd */
214 filename
= g_strdup (argv
[i
]);
216 filename
= g_build_filename (cwd
, argv
[i
], NULL
);
220 s_log_message (_("Loading schematic [%s]\n"), filename
);
221 fprintf (stderr
, _("Loading schematic [%s]\n"), filename
);
224 s_page_goto (pr_current
, s_page_new (pr_current
, filename
));
226 if (!f_open (pr_current
, pr_current
->page_current
, filename
, &err
)) {
227 g_warning ("%s\n", err
->message
);
228 fprintf (stderr
, _("ERROR: Failed to load '%s': %s\n"),
229 filename
, err
->message
);
234 /* collect input filenames for backend use */
235 input_files
= g_slist_append(input_files
, argv
[i
]);
241 /* Change back to the directory where we started. This is done */
242 /* since gnetlist is a command line utility and will deposit its output */
243 /* in the current directory. Having the output go to a different */
244 /* directory will confuse the user (confused me, at first). */
245 if (chdir (cwd
) == -1) {
247 _("ERROR: Failed to restore working directory to `%s': %s\n"),
248 cwd
, g_strerror (errno
));
251 /* free(cwd); - Defered; see below */
253 if (argv
[argv_index
] == NULL
) {
255 "ERROR: No schematics files specified for processing.\n"
256 "\nRun `%s --help' for more information.\n"), argv
[0]);
261 s_page_print_all(pr_current
);
264 /* Load basic gnetlist functions */
265 scm_primitive_load_path (scm_from_utf8_string ("gnetlist.scm"));
270 /* Search for backend scm file in load path */
271 str
= g_strdup_printf("gnet-%s.scm", guile_proc
);
272 s_backend_path
= scm_sys_search_load_path (scm_from_locale_string (str
));
275 /* If it couldn't be found, fail. */
276 if (scm_is_false (s_backend_path
)) {
278 "ERROR: Could not find backend `%s' in load path.\n"
279 "\nRun `%s --list-backends' for a full list of available backends.\n"),
280 guile_proc
, argv
[0]);
284 /* Load backend code. */
285 scm_primitive_load (s_backend_path
);
287 /* Evaluate second set of Scheme expressions. */
288 scm_eval (post_backend_list
, scm_current_module ());
292 s_traverse_start(pr_current
);
294 /* Change back to the directory where we started AGAIN. This is done */
295 /* because the s_traverse functions can change the Current Working Directory. */
296 if (chdir (cwd
) == -1) {
298 _("ERROR: Failed to restore working directory to `%s': %s\n"),
299 cwd
, g_strerror (errno
));
304 /* Run post-traverse code. */
305 scm_primitive_load_path (scm_from_utf8_string ("gnetlist-post.scm"));
307 if (interactive_mode
) {
308 scm_c_eval_string ("(set-repl-prompt! \"gnetlist-legacy> \")");
310 } else if (guile_proc
) {
311 /* check size here hack */
312 str
= g_strdup_printf ("(%s \"%s\")", guile_proc
, output_filename
);
313 scm_c_eval_string (str
);
315 /* gh_eval_str_with_stack_saving_handler (input_str); */
318 _("You gave neither backend to execute nor interactive mode!\n"));
326 int main(int argc
, char *argv
[])
329 setlocale (LC_ALL
, "");
330 setlocale (LC_NUMERIC
, "C");
331 bindtextdomain ("geda-gnetlist-legacy", LOCALEDIR
);
332 textdomain ("geda-gnetlist-legacy");
333 bind_textdomain_codeset("geda-gnetlist-legacy", "UTF-8");
335 scm_boot_guile (argc
, argv
, main_prog
, 0);