Reduce visibility of functions used in only one file.
[geda-gaf/berndj.git] / gnetlist / src / gnetlist.c
blob20186911d002b7da1983af5a3aa943826a3719bf
1 /* gEDA - GPL Electronic Design Automation
2 * gnetlist - gEDA Netlist
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
21 #include <config.h>
23 #include <stdio.h>
24 #include <sys/param.h>
25 #include <sys/types.h>
26 #ifdef HAVE_ERRNO_H
27 #include <errno.h>
28 #endif
29 #ifdef HAVE_DIRENT_H
30 #include <dirent.h>
31 #endif
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #endif
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
40 #include <libgeda/libgeda.h>
42 #include "../include/globals.h"
43 #include "../include/prototype.h"
45 #ifdef HAVE_LIBDMALLOC
46 #include <dmalloc.h>
47 #endif
49 #define BACKEND_LIST_COLS 3
51 void gnetlist_quit(void)
53 s_clib_free();
54 s_slib_free();
55 s_rename_destroy_all();
56 libgeda_fini();
57 /* o_text_freeallfonts(); */
59 /* Free GSList *backend_params */
60 g_slist_free (backend_params);
63 /** @brief Prints a list of all installed gnetlist backends to standard output.
65 * @param current Pointer to the toplevel struct.
67 void gnetlist_backends(TOPLEVEL *current)
69 DIR *schemedir;
70 struct dirent *entry;
71 char *filename;
72 int n;
74 schemedir=opendir(current->scheme_directory);
75 if(schemedir==NULL) {
76 fprintf(stderr, "\nERROR! Can't open directory %s: %s\n",
77 current->scheme_directory,
78 strerror(errno));
79 return;
82 printf("List of available backends:\n\n");
84 n=1;
85 while(1) {
86 entry=readdir(schemedir);
87 if(entry==NULL) break;
89 filename=strdup(entry->d_name);
91 if(g_str_has_prefix(filename, "gnet-")&&
92 g_str_has_suffix(filename, ".scm")) {
94 /* strip the suffix */
95 filename[strlen(filename)-4]='\0';
96 /* and skip the prefix */
97 printf("%-25s", &filename[5]);
98 if(n>=BACKEND_LIST_COLS) {
99 printf("\n");
100 n=0;
102 n++;
105 free(filename);
107 printf("\n");
110 void main_prog(void *closure, int argc, char *argv[])
112 int i;
113 char input_str[2048];
114 int argv_index;
115 char *cwd;
116 GSList *list_pnt;
117 gchar *logfile;
119 TOPLEVEL *pr_current;
121 /* set default output filename */
122 output_filename = g_strdup("output.net");
124 argv_index = parse_commandline(argc, argv);
125 cwd = g_get_current_dir();
127 /* this is a kludge to make sure that spice mode gets set */
128 /* Hacked by SDB to allow spice netlisters of arbitrary name
129 * as long as they begin with "spice". For example, this spice
130 * netlister is valid: "spice-sdb".
132 if (guile_proc) {
133 if (strncmp(guile_proc, "spice", 5) == 0) {
134 netlist_mode = SPICE;
135 command_line = create_command_line(argc, argv);
137 printf("Command line passed = %s \n", command_line);
142 libgeda_init(TRUE);
144 /* create log file right away */
145 /* even if logging is enabled */
146 logfile = g_build_filename (cwd, "gnetlist.log", NULL);
147 s_log_init (logfile);
148 g_free (logfile);
150 s_log_message("gEDA/gnetlist version %s%s.%s\n", PREPEND_VERSION_STRING,
151 DOTTED_VERSION, DATE_VERSION);
152 s_log_message
153 ("gEDA/gnetlist comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n");
154 s_log_message
155 ("This is free software, and you are welcome to redistribute it under certain\n");
156 s_log_message
157 ("conditions; please see the COPYING file for more details.\n\n");
159 if (!quiet_mode) {
160 fprintf(stderr, "gEDA/gnetlist version %s%s.%s\n",
161 PREPEND_VERSION_STRING, DOTTED_VERSION, DATE_VERSION);
162 fprintf(stderr,
163 "gEDA/gnetlist comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n");
164 fprintf(stderr,
165 "This is free software, and you are welcome to redistribute it under certain\n");
166 fprintf(stderr,
167 "conditions; please see the COPYING file for more details.\n\n");
170 #ifdef __MINGW32__
171 fprintf(stderr, "This is the MINGW32 port.\n\n");
172 #endif
174 s_log_message ("Remember to check that your schematic has no errors using the drc2 backend.\n");
175 s_log_message ("You can do it running 'gnetlist -g drc2 your_schematic.sch -o drc_output.txt'\n");
176 s_log_message ("and seeing the contents of the file drc_output.txt.\n\n");
178 if (!quiet_mode) {
179 fprintf (stderr, "Remember to check that your schematic has no errors using the drc2 backend.\n");
180 fprintf (stderr, "You can do it running 'gnetlist -g drc2 your_schematic.sch -o drc_output.txt'\n");
181 fprintf (stderr, "and seeing the contents of the file drc_output.txt.\n\n");
183 /* register guile (scheme) functions */
184 g_register_funcs();
186 pr_current = s_toplevel_new ();
187 g_rc_parse(pr_current, "gnetlistrc", rc_filename);
188 /* immediately setup user params */
189 i_vars_set (pr_current);
191 s_rename_init();
193 if(guile_proc!=NULL) {
194 if(!strcmp(guile_proc, "help")) {
195 gnetlist_backends(pr_current);
196 exit(0);
200 /* Load the first set of scm files before we load any schematic files */
201 list_pnt = pre_backend_list;
202 while (list_pnt) {
203 if (g_read_file(list_pnt->data) != -1) {
204 s_log_message("Read scm file [%s]\n",
205 (char *) list_pnt->data);
206 } else {
207 s_log_message("Failed to read scm file [%s]\n",
208 (char *) list_pnt->data);
209 fprintf(stderr, "Failed to read scm file [%s]\n",
210 (char *) list_pnt->data);
212 list_pnt = g_slist_next(list_pnt);
214 /* Free now the list of configuration files */
215 g_slist_free(pre_backend_list);
217 i = argv_index;
218 while (argv[i] != NULL) {
219 PAGE *page;
220 gchar *filename;
221 GError *err = NULL;
223 if (g_path_is_absolute(argv[i])) {
224 /* Path is already absolute so no need to do any concat of cwd */
225 filename = g_strdup (argv[i]);
226 } else {
227 filename = g_build_filename (cwd, argv[i], NULL);
230 if (!quiet_mode) {
231 s_log_message ("Loading schematic [%s]\n", filename);
232 printf ("Loading schematic [%s]\n", filename);
235 page = s_page_new(pr_current, filename);
236 s_toplevel_goto_page(pr_current, page);
238 if (!f_open(pr_current, page, filename, &err)) {
239 g_warning ("%s\n", err->message);
240 fprintf (stderr, "%s\n", err->message);
241 g_error_free (err);
244 i++;
245 g_free (filename);
248 /* Change back to the directory where we started. This is done */
249 /* since gnetlist is a command line utility and will deposit its output */
250 /* in the current directory. Having the output go to a different */
251 /* directory will confuse the user (confused me, at first). */
252 if (chdir (cwd)) {
253 /* Error occurred with chdir */
254 #warning FIXME: What do we do?
256 /* free(cwd); - Defered; see below */
258 if (argv[argv_index] == NULL) {
259 fprintf(stderr,
260 "\nERROR! You must specify at least one filename\n\n");
261 usage(argv[0]);
264 g_set_project_current(pr_current);
265 #if DEBUG
266 s_page_print_all(pr_current);
267 #endif
269 /* temporarly reuse input_str */
270 sprintf(input_str, "%s%cgnetlist.scm", pr_current->scheme_directory,
271 G_DIR_SEPARATOR);
273 if (g_read_file(input_str) != -1) {
274 s_log_message("Read init scm file [%s]\n", input_str);
275 } else {
276 s_log_message("Failed to read init scm file [%s]\n", input_str);
277 fprintf(stderr, "Failed to read init scm file [%s]\n", input_str);
280 if (guile_proc) {
281 /* load the appropriate scm file */
282 sprintf(input_str, "%s%cgnet-%s.scm", pr_current->scheme_directory,
283 G_DIR_SEPARATOR, guile_proc);
285 if (g_read_file(input_str) != -1) {
286 s_log_message("Read %s scm file [%s]\n", guile_proc,
287 input_str);
288 } else {
289 s_log_message("Failed to read %s scm file [%s]\n",
290 guile_proc, input_str);
291 fprintf(stderr, "Failed to read %s scm file [%s]\n",
292 guile_proc, input_str);
295 /* Load second set of scm files */
296 list_pnt = post_backend_list;
297 while (list_pnt) {
298 if (g_read_file(list_pnt->data) != -1) {
299 s_log_message("Read scm file [%s]\n",
300 (char *) list_pnt->data);
301 } else {
302 s_log_message("Failed to read scm file [%s]\n",
303 (char *) list_pnt->data);
304 fprintf(stderr, "Failed to read scm file [%s]\n",
305 (char *) list_pnt->data);
307 list_pnt = g_slist_next(list_pnt);
309 /* Free now the list of configuration files */
310 g_slist_free(post_backend_list);
313 s_traverse_init();
314 s_traverse_start(pr_current);
316 /* Change back to the directory where we started AGAIN. This is done */
317 /* because the s_traverse functions can change the Current Working Directory. */
318 if (chdir (cwd)) {
319 /* Error occurred with chdir */
320 #warning FIXME: What do we do?
322 g_free(cwd);
324 /* temporarly reuse input_str */
325 sprintf(input_str, "%s%cgnetlist-post.scm", pr_current->scheme_directory,
326 G_DIR_SEPARATOR);
328 if (g_read_file(input_str) != -1) {
329 s_log_message("Read post traversal scm file [%s]\n", input_str);
330 } else {
331 s_log_message("Failed to read post traversal scm file [%s]\n", input_str);
332 fprintf(stderr, "Failed to read post traversal scm file [%s]\n", input_str);
335 if (guile_proc) {
336 SCM retval;
337 int exception_caught = 0;
339 retval = g_scm_apply_protected(g_scm_safe_ref_lookup(guile_proc),
340 scm_list_1(scm_from_locale_string(output_filename)),
341 &g_scm_exception_witness, &exception_caught);
343 gnetlist_quit();
344 if (exception_caught || scm_is_false(retval)) {
345 exit(1);
346 } else {
347 exit(0);
349 } else if (interactive_mode) {
350 /* FIXME: set-repl-prompt! is deprecated or nonexistent. */
351 scm_c_eval_string ("(set-repl-prompt! \"gnetlist> \")");
352 /* FIXME scm_shell does not return, so arrange to call gnetlist_quit. */
353 scm_shell (0, NULL);
354 } else {
355 fprintf(stderr,
356 "You gave neither backend to execute nor interactive mode!\n");
359 /* However we got here, it's an error. */
360 gnetlist_quit();
361 exit(1);
364 int main(int argc, char *argv[])
366 /* disable the deprecated warnings in guile 1.6.3 */
367 /* Eventually the warnings will need to be fixed */
368 if(getenv("GUILE_WARN_DEPRECATED")==NULL)
369 putenv("GUILE_WARN_DEPRECATED=no");
371 scm_boot_guile (argc, argv, main_prog, 0);
372 return 0;