1 /*!
2  * \file src/main.c
3  *
4  * \brief Main program, initializes some stuff and handles user input.
5  *
6  * <hr>
7  *
8  * <h1><b>Copyright.</b></h1>\n
9  *
10  * PCB, interactive printed circuit board design
11  *
12  * Copyright (C) 1994,1995,1996, 2004 Thomas Nau
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27  *
28  * Contact addresses for paper mail and Email:
29  * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
30  * Thomas.Nau@rz.uni-ulm.de
31  */
32 
33 
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 
38 #include <stdlib.h>
39 #ifdef HAVE_STRING_H
40 #include <string.h>
41 #endif
42 
43 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
44 #include <locale.h>
45 #endif
46 
47 #include <signal.h>
48 #include <unistd.h>
49 #include <sys/stat.h>
50 #include <time.h> /* Seed for srand() */
51 
52 #include "global.h"
53 #include "data.h"
54 #include "buffer.h"
55 #include "create.h"
56 #include "crosshair.h"
57 #include "draw.h"
58 #include "error.h"
59 #include "file.h"
60 #include "set.h"
61 #include "action.h"
62 #include "misc.h"
63 #include "lrealpath.h"
64 #include "free_atexit.h"
65 #include "polygon.h"
66 #include "gettext.h"
67 #include "pcb-printf.h"
68 #include "strflags.h"
69 
70 #include "hid/common/actions.h"
71 
72 /* This next one is so we can print the help messages. */
73 #include "hid/hidint.h"
74 
75 #ifdef HAVE_DBUS
76 #include "dbus.h"
77 #endif
78 
79 #ifdef HAVE_LIBDMALLOC
80 #include <dmalloc.h>
81 #endif
82 
83 #define PCBLIBPATH ".:" PCBLIBDIR
84 
85 
86 #ifdef HAVE_LIBSTROKE
87 extern void stroke_init (void);
88 #endif
89 
90 
91 /*!
92  * \brief Initialize signal and error handlers.
93  */
94 static void
InitHandler(void)95 InitHandler (void)
96 {
97 /*
98 	signal(SIGHUP, CatchSignal);
99 	signal(SIGQUIT, CatchSignal);
100 	signal(SIGABRT, CatchSignal);
101 	signal(SIGSEGV, CatchSignal);
102 	signal(SIGTERM, CatchSignal);
103 	signal(SIGINT, CatchSignal);
104 */
105 
106   /* calling external program by popen() may cause a PIPE signal,
107    * so we ignore it
108    */
109 #ifdef SIGPIPE
110   signal (SIGPIPE, SIG_IGN);
111 #endif
112 }
113 
114 
115   /* ----------------------------------------------------------------------
116      |  command line and rc file processing.
117    */
118 static char *command_line_pcb;
119 
120 /*!
121  * \brief Print the copyright notice.
122  */
123 void
copyright(void)124 copyright (void)
125 {
126   printf ("\n"
127 	  "                COPYRIGHT for %s version %s\n\n"
128 	  "    PCB, interactive printed circuit board design\n"
129 	  "    Copyright (C) 1994,1995,1996,1997 Thomas Nau\n"
130 	  "    Copyright (C) 1998, 1999, 2000 Harry Eaton\n\n"
131 	  "    This program is free software; you can redistribute it and/or modify\n"
132 	  "    it under the terms of the GNU General Public License as published by\n"
133 	  "    the Free Software Foundation; either version 2 of the License, or\n"
134 	  "    (at your option) any later version.\n\n"
135 	  "    This program is distributed in the hope that it will be useful,\n"
136 	  "    but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
137 	  "    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
138 	  "    GNU General Public License for more details.\n\n"
139 	  "    You should have received a copy of the GNU General Public License along\n"
140 	  "    with this program; if not, write to the Free Software Foundation, Inc.,\n"
141 	  "    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n",
142 	  Progname, VERSION);
143   exit (0);
144 }
145 
146 static inline void
u(const char * fmt,...)147 u (const char *fmt, ...)
148 {
149   va_list ap;
150   va_start (ap, fmt);
151   vfprintf (stderr, fmt, ap);
152   fputc ('\n', stderr);
153   va_end (ap);
154 }
155 
156 typedef struct UsageNotes {
157   struct UsageNotes *next;
158   HID_Attribute *seen;
159 } UsageNotes;
160 
161 static UsageNotes *usage_notes = NULL;
162 
163 static void
usage_attr(HID_Attribute * a)164 usage_attr (HID_Attribute * a)
165 {
166   int i, n;
167   const Unit *unit_list;
168   static char buf[200];
169 
170   if (a->help_text == ATTR_UNDOCUMENTED)
171     return;
172 
173   switch (a->type)
174     {
175     case HID_Label:
176       return;
177     case HID_Integer:
178     case HID_Real:
179       sprintf (buf, "--%s <num>", a->name);
180       break;
181     case HID_Coord:
182       sprintf (buf, "--%s <measure>", a->name);
183       break;
184     case HID_String:
185       sprintf (buf, "--%s <string>", a->name);
186       break;
187     case HID_Boolean:
188       sprintf (buf, "--%s", a->name);
189       break;
190     case HID_Mixed:
191     case HID_Enum:
192       sprintf (buf, "--%s ", a->name);
193       if (a->type == HID_Mixed)
194 	strcat (buf, " <val>");
195       for (i = 0; a->enumerations[i]; i++)
196 	{
197 	  strcat (buf, i ? "|" : "<");
198 	  strcat (buf, a->enumerations[i]);
199 	}
200       strcat (buf, ">");
201       break;
202     case HID_Path:
203       sprintf (buf, "--%s <path>", a->name);
204       break;
205     case HID_Unit:
206       unit_list = get_unit_list ();
207       n = get_n_units ();
208       sprintf (buf, "--%s ", a->name);
209       for (i = 0; i < n; i++)
210 	{
211 	  strcat (buf, i ? "|" : "<");
212 	  strcat (buf, unit_list[i].suffix);
213 	}
214       strcat (buf, ">");
215       break;
216     }
217 
218   if (strlen (buf) <= 30)
219     {
220       if (a->help_text)
221 	fprintf (stderr, " %-30s\t%s\n", buf, a->help_text);
222       else
223 	fprintf (stderr, " %-30s\n", buf);
224     }
225   else if (a->help_text && strlen (a->help_text) + strlen (buf) < 72)
226     fprintf (stderr, " %s\t%s\n", buf, a->help_text);
227   else if (a->help_text)
228     fprintf (stderr, " %s\n\t\t\t%s\n", buf, a->help_text);
229   else
230     fprintf (stderr, " %s\n", buf);
231 }
232 
233 static void
usage_hid(HID * h)234 usage_hid (HID * h)
235 {
236   HID_Attribute *attributes;
237   int i, n_attributes = 0;
238   UsageNotes *note;
239 
240   if (h->gui)
241     {
242       fprintf (stderr, "\n%s gui options:\n", h->name);
243       attributes = h->get_export_options (&n_attributes);
244     }
245   else
246     {
247       fprintf (stderr, "\n%s options:\n", h->name);
248       exporter = h;
249       attributes = exporter->get_export_options (&n_attributes);
250       exporter = NULL;
251     }
252 
253   note = (UsageNotes *)malloc (sizeof (UsageNotes));
254   note->next = usage_notes;
255   note->seen = attributes;
256   usage_notes = note;
257 
258   for (i = 0; i < n_attributes; i++)
259     usage_attr (attributes + i);
260 }
261 
262 static void
usage(void)263 usage (void)
264 {
265   HID **hl = hid_enumerate ();
266   HID_AttrNode *ha;
267   UsageNotes *note;
268   int i;
269   int n_printer = 0, n_gui = 0, n_exporter = 0;
270 
271   for (i = 0; hl[i]; i++)
272     {
273       if (hl[i]->gui)
274 	n_gui++;
275       if (hl[i]->printer)
276 	n_printer++;
277       if (hl[i]->exporter)
278 	n_exporter++;
279     }
280 
281   u ("PCB Printed Circuit Board editing program, http://pcb.geda-project.org");
282   u ("%s [-h|-V|--copyright]\t\t\tHelp, version, copyright", Progname);
283   u ("%s [gui options] <pcb file>\t\tto edit", Progname);
284   u ("Available GUI hid%s:", n_gui == 1 ? "" : "s");
285   for (i = 0; hl[i]; i++)
286     if (hl[i]->gui)
287       fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
288   u ("%s -p [printing options] <pcb file>\tto print", Progname);
289   u ("Available printing hid%s:", n_printer == 1 ? "" : "s");
290   for (i = 0; hl[i]; i++)
291     if (hl[i]->printer)
292       fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
293   u ("%s -x hid [export options] <pcb file>\tto export", Progname);
294   u ("Available export hid%s:", n_exporter == 1 ? "" : "s");
295   for (i = 0; hl[i]; i++)
296     if (hl[i]->exporter)
297       fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
298 
299   for (i = 0; hl[i]; i++)
300     if (hl[i]->gui)
301       usage_hid (hl[i]);
302   for (i = 0; hl[i]; i++)
303     if (hl[i]->printer)
304       usage_hid (hl[i]);
305   for (i = 0; hl[i]; i++)
306     if (hl[i]->exporter)
307       usage_hid (hl[i]);
308 
309   u ("\nCommon options:");
310   for (ha = hid_attr_nodes; ha; ha = ha->next)
311     {
312       for (note = usage_notes; note && note->seen != ha->attributes; note = note->next)
313 	;
314       if (note)
315 	continue;
316       for (i = 0; i < ha->n; i++)
317 	{
318 	  usage_attr (ha->attributes + i);
319 	}
320     }
321 
322   exit (1);
323 }
324 
325 static void
print_defaults_1(HID_Attribute * a,void * value)326 print_defaults_1 (HID_Attribute * a, void *value)
327 {
328   int i;
329   Coord c;
330   double d;
331   const char *s;
332 
333   /* Remember, at this point we've parsed the command line, so they
334      may be in the global variable instead of the default_val.  */
335   switch (a->type)
336     {
337     case HID_Integer:
338       i = value ? *(int *) value : a->default_val.int_value;
339       fprintf (stderr, "%s %d\n", a->name, i);
340       break;
341     case HID_Boolean:
342       i = value ? *(char *) value : a->default_val.int_value;
343       fprintf (stderr, "%s %s\n", a->name, i ? "yes" : "no");
344       break;
345     case HID_Real:
346       d = value ? *(double *) value : a->default_val.real_value;
347       fprintf (stderr, "%s %g\n", a->name, d);
348       break;
349     case HID_Coord:
350       c = value ? *(Coord *) value : a->default_val.coord_value;
351       pcb_fprintf (stderr, "%s %$mS\n", a->name, c);
352       break;
353     case HID_String:
354     case HID_Path:
355       s = value ? *(char **) value : a->default_val.str_value;
356       fprintf (stderr, "%s \"%s\"\n", a->name, s);
357       break;
358     case HID_Enum:
359       i = value ? *(int *) value : a->default_val.int_value;
360       fprintf (stderr, "%s %s\n", a->name, a->enumerations[i]);
361       break;
362     case HID_Mixed:
363       i = value ?
364         ((HID_Attr_Val*)value)->int_value  : a->default_val.int_value;
365       d = value ?
366         ((HID_Attr_Val*)value)->real_value : a->default_val.real_value;
367       fprintf (stderr, "%s %g%s\n", a->name, d, a->enumerations[i]);
368       break;
369     case HID_Label:
370       break;
371     case HID_Unit:
372       i = value ? *(int *) value : a->default_val.int_value;
373       fprintf (stderr, "%s %s\n", a->name, get_unit_list()[i].suffix);
374     }
375 }
376 
377 static void
print_defaults()378 print_defaults ()
379 {
380   HID **hl = hid_enumerate ();
381   HID_Attribute *e;
382   int i, n, hi;
383 
384   for (hi = 0; hl[hi]; hi++)
385     {
386       HID *h = hl[hi];
387       if (h->gui)
388 	{
389 	  HID_AttrNode *ha;
390 	  fprintf (stderr, "\ngui defaults:\n");
391 	  for (ha = hid_attr_nodes; ha; ha = ha->next)
392 	    for (i = 0; i < ha->n; i++)
393 	      print_defaults_1 (ha->attributes + i, ha->attributes[i].value);
394 	}
395       else
396 	{
397 	  fprintf (stderr, "\n%s defaults:\n", h->name);
398 	  exporter = h;
399 	  e = exporter->get_export_options (&n);
400 	  exporter = NULL;
401 	  if (e)
402 	    for (i = 0; i < n; i++)
403 	      print_defaults_1 (e + i, 0);
404 	}
405     }
406   exit (1);
407 }
408 
409 #define SSET(F,D,N,H) { N, H, \
410 	HID_String,  0, 0, { 0, D, 0 }, 0, &Settings.F }
411 #define ISET(F,D,N,H) { N, H, \
412 	HID_Integer, 0, 0, { D, 0, 0 }, 0, &Settings.F }
413 #define BSET(F,D,N,H) { N, H, \
414 	HID_Boolean, 0, 0, { D, 0, 0 }, 0, &Settings.F }
415 #define RSET(F,D,N,H) { N, H, \
416 	HID_Real,    0, 0, { 0, 0, D }, 0, &Settings.F }
417 #define CSET(F,D,N,H) { N, H, \
418 	HID_Coord,    0, 0, { 0, 0, 0, D }, 0, &Settings.F }
419 
420 #define COLOR(F,D,N,H) { N, H, \
421 	HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.F }
422 #define LAYERCOLOR(N,D) { "layer-color-" #N, "Color for layer " #N, \
423 	HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.LayerColor[N-1] }
424 #define LAYERNAME(N,D) { "layer-name-" #N, "Name for layer " #N, \
425 	HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.DefaultLayerName[N-1] }
426 #define LAYERSELCOLOR(N) { "layer-selected-color-" #N, "Color for layer " #N " when selected", \
427 	HID_String, 0, 0, { 0, "#00ffff", 0 }, 0, &Settings.LayerSelectedColor[N-1] }
428 
429 static int show_help = 0;
430 static int show_version = 0;
431 static int show_copyright = 0;
432 static int show_defaults = 0;
433 static int show_actions = 0;
434 static int do_dump_actions = 0;
435 static char *grid_units;
436 static Increments increment_mm  = { 0 };
437 static Increments increment_mil = { 0 };
438 
save_increments(const Increments * mm,const Increments * mil)439 void save_increments (const Increments *mm, const Increments *mil)
440 {
441   memcpy (&increment_mm,  mm,  sizeof (*mm));
442   memcpy (&increment_mil, mil, sizeof (*mil));
443 }
444 
445 HID_Attribute main_attribute_list[] = {
446 
447 /* %start-doc options "1 General Options"
448 @ftable @code
449 @item --help
450 Show help on command line options.
451 @end ftable
452 %end-doc
453 */
454   {"help", "Show help on command line options", HID_Boolean, 0, 0, {0, 0, 0}, 0,
455   &show_help},
456 
457 /* %start-doc options "1 General Options"
458 @ftable @code
459 @item --version
460 Show version.
461 @end ftable
462 %end-doc
463 */
464   {"version", "Show version", HID_Boolean, 0, 0, {0, 0, 0}, 0, &show_version},
465 
466 /* %start-doc options "1 General Options"
467 @ftable @code
468 @item --verbose
469 Be verbose on stdout.
470 @end ftable
471 %end-doc
472 */
473   {"verbose", "Be verbose on stdout", HID_Boolean, 0, 0, {0, 0, 0}, 0,
474    &Settings.verbose},
475 
476 /* %start-doc options "1 General Options"
477 @ftable @code
478 @item --copyright
479 Show copyright.
480 @end ftable
481 %end-doc
482 */
483   {"copyright", "Show Copyright", HID_Boolean, 0, 0, {0, 0, 0}, 0,
484    &show_copyright},
485 
486 /* %start-doc options "1 General Options"
487 @ftable @code
488 @item --show-defaults
489 Show option defaults.
490 @end ftable
491 %end-doc
492 */
493   {"show-defaults", "Show option defaults", HID_Boolean, 0, 0, {0, 0, 0}, 0,
494    &show_defaults},
495 
496 /* %start-doc options "1 General Options"
497 @ftable @code
498 @item --show-actions
499 Show available actions and exit.
500 @end ftable
501 %end-doc
502 */
503   {"show-actions", "Show available actions", HID_Boolean, 0, 0, {0, 0, 0}, 0,
504    &show_actions},
505 
506 /* %start-doc options "1 General Options"
507 @ftable @code
508 @item --dump-actions
509 Dump actions (for documentation).
510 @end ftable
511 %end-doc
512 */
513   {"dump-actions", "Dump actions (for documentation)", HID_Boolean, 0, 0,
514    {0, 0, 0}, 0, &do_dump_actions},
515 
516 /* %start-doc options "1 General Options"
517 @ftable @code
518 @item --grid-units-mm <string>
519 Set default grid units. Can be mm or mil. Defaults to mil.
520 @end ftable
521 %end-doc
522 */
523   {"grid-units", "Default grid units (mm|mil)", HID_String, 0, 0, {0, "mil", 0},
524   0, &grid_units},
525 
526 /* %start-doc options "1 General Options"
527 @ftable @code
528 @item --clear-increment-mm <string>
529 Set default clear increment (amount to change when user presses k or K)
530 when user is using a metric grid unit.
531 @end ftable
532 %end-doc
533 */
534   {"clear-increment-mm", "Default clear increment amount (metric)", HID_Coord, 0, 0, {0, 0, 0},
535   0, &increment_mm.clear},
536 
537 /* %start-doc options "1 General Options"
538 @ftable @code
539 @item --grid-increment-mm <string>
540 Set default grid increment (amount to change when user presses g or G)
541 when user is using a metric grid unit.
542 @end ftable
543 %end-doc
544 */
545   {"grid-increment-mm", "Default grid increment amount (metric)", HID_Coord, 0, 0, {0, 0, 0},
546   0, &increment_mm.grid},
547 
548 /* %start-doc options "1 General Options"
549 @ftable @code
550 @item --line-increment-mm <string>
551 Set default line increment (amount to change when user presses l or L)
552 when user is using a metric grid unit.
553 @end ftable
554 %end-doc
555 */
556   {"line-increment-mm", "Default line increment amount (metric)", HID_Coord, 0, 0, {0, 0, 0},
557   0, &increment_mm.line},
558 
559 /* %start-doc options "1 General Options"
560 @ftable @code
561 @item --size-increment-mm <string>
562 Set default size increment (amount to change when user presses s or S)
563 when user is using a metric grid unit.
564 @end ftable
565 %end-doc
566 */
567   {"size-increment-mm", "Default size increment amount (metric)", HID_Coord, 0, 0, {0, 0, 0},
568   0, &increment_mm.size},
569 
570 /* %start-doc options "1 General Options"
571 @ftable @code
572 @item --clear-increment-mil <string>
573 Set default clear increment (amount to change when user presses k or K)
574 when user is using an imperial grid unit.
575 @end ftable
576 %end-doc
577 */
578   {"clear-increment-mil", "Default clear increment amount (imperial)", HID_Coord, 0, 0, {0, 0, 0},
579   0, &increment_mil.clear},
580 
581 /* %start-doc options "1 General Options"
582 @ftable @code
583 @item --grid-increment-mil <string>
584 Set default grid increment (amount to change when user presses g or G)
585 when user is using a imperial grid unit.
586 @end ftable
587 %end-doc
588 */
589   {"grid-increment-mil", "Default grid increment amount (imperial)", HID_Coord, 0, 0, {0, 0, 0},
590   0, &increment_mil.grid},
591 
592 /* %start-doc options "1 General Options"
593 @ftable @code
594 @item --line-increment-mil <string>
595 Set default line increment (amount to change when user presses l or L)
596 when user is using a imperial grid unit.
597 @end ftable
598 %end-doc
599 */
600   {"line-increment-mil", "Default line increment amount (imperial)", HID_Coord, 0, 0, {0, 0, 0},
601   0, &increment_mil.line},
602 
603 /* %start-doc options "1 General Options"
604 @ftable @code
605 @item --size-increment-mil <string>
606 Set default size increment (amount to change when user presses s or S)
607 when user is using a imperial grid unit.
608 @end ftable
609 %end-doc
610 */
611   {"size-increment-mil", "Default size increment amount (imperial)", HID_Coord, 0, 0, {0, 0, 0},
612   0, &increment_mil.size},
613 
614 /* %start-doc options "3 Colors"
615 @ftable @code
616 @item --black-color <string>
617 Color value for black. Default: @samp{#000000}
618 @end ftable
619 %end-doc
620 */
621   COLOR (BlackColor, "#000000", "black-color", "color value of 'black'"),
622 
623 /* %start-doc options "3 Colors"
624 @ftable @code
625 @item --black-color <string>
626 Color value for white. Default: @samp{#ffffff}
627 @end ftable
628 %end-doc
629 */
630   COLOR (WhiteColor, "#ffffff", "white-color", "color value of 'white'"),
631 
632 /* %start-doc options "3 Colors"
633 @ftable @code
634 @item --background-color <string>
635 Background color of the canvas. Default: @samp{#e5e5e5}
636 @end ftable
637 %end-doc
638 */
639   COLOR (BackgroundColor, "#e5e5e5", "background-color",
640 	 "color for background"),
641 
642 /* %start-doc options "3 Colors"
643 @ftable @code
644 @item --crosshair-color <string>
645 Color of the crosshair. Default: @samp{#ff0000}
646 @end ftable
647 %end-doc
648 */
649   COLOR (CrosshairColor, "#ff0000", "crosshair-color",
650 	 "color for the crosshair"),
651 
652 /* %start-doc options "3 Colors"
653 @ftable @code
654 @item --cross-color <string>
655 Color of the cross. Default: @samp{#cdcd00}
656 @end ftable
657 %end-doc
658 */
659   COLOR (CrossColor, "#cdcd00", "cross-color", "color of the cross"),
660 
661 /* %start-doc options "3 Colors"
662 @ftable @code
663 @item --via-color <string>
664 Color of vias. Default: @samp{#7f7f7f}
665 @end ftable
666 %end-doc
667 */
668   COLOR (ViaColor, "#7f7f7f", "via-color", "color of vias"),
669 
670 /* %start-doc options "3 Colors"
671 @ftable @code
672 @item --via-selected-color <string>
673 Color of selected vias. Default: @samp{#00ffff}
674 @end ftable
675 %end-doc
676 */
677   COLOR (ViaSelectedColor, "#00ffff", "via-selected-color",
678 	 "color for selected vias"),
679 
680 /* %start-doc options "3 Colors"
681 @ftable @code
682 @item --pin-color <string>
683 Color of pins. Default: @samp{#4d4d4d}
684 @end ftable
685 %end-doc
686 */
687   COLOR (PinColor, "#4d4d4d", "pin-color", "color of pins"),
688 
689 /* %start-doc options "3 Colors"
690 @ftable @code
691 @item --pin-selected-color <string>
692 Color of selected pins. Default: @samp{#00ffff}
693 @end ftable
694 %end-doc
695 */
696   COLOR (PinSelectedColor, "#00ffff", "pin-selected-color",
697 	 "color of selected pins"),
698 
699 /* %start-doc options "3 Colors"
700 @ftable @code
701 @item --pin-name-color <string>
702 Color of pin names and pin numbers. Default: @samp{#ff0000}
703 @end ftable
704 %end-doc
705 */
706   COLOR (PinNameColor, "#ff0000", "pin-name-color",
707 	 "color for pin names and pin numbers"),
708 
709 /* %start-doc options "3 Colors"
710 @ftable @code
711 @item --element-color <string>
712 Color of components. Default: @samp{#000000}
713 @end ftable
714 %end-doc
715 */
716   COLOR (ElementColor, "#000000", "element-color", "color of components"),
717 
718 /* %start-doc options "3 Colors"
719 @ftable @code
720 @item --rat-color <string>
721 Color of ratlines. Default: @samp{#b8860b}
722 @end ftable
723 %end-doc
724 */
725   COLOR (RatColor, "#b8860b", "rat-color", "color of ratlines"),
726 
727 /* %start-doc options "3 Colors"
728 @ftable @code
729 @item --invisible-objects-color <string>
730 Color of invisible objects. Default: @samp{#cccccc}
731 @end ftable
732 %end-doc
733 */
734   COLOR (InvisibleObjectsColor, "#cccccc", "invisible-objects-color",
735 	 "color of invisible objects"),
736 
737 /* %start-doc options "3 Colors"
738 @ftable @code
739 @item --invisible-mark-color <string>
740 Color of invisible marks. Default: @samp{#cccccc}
741 @end ftable
742 %end-doc
743 */
744   COLOR (InvisibleMarkColor, "#cccccc", "invisible-mark-color",
745 	 "color of invisible marks"),
746 
747 /* %start-doc options "3 Colors"
748 @ftable @code
749 @item --element-selected-color <string>
750 Color of selected components. Default: @samp{#00ffff}
751 @end ftable
752 %end-doc
753 */
754   COLOR (ElementSelectedColor, "#00ffff", "element-selected-color",
755 	 "color of selected components"),
756 
757 /* %start-doc options "3 Colors"
758 @ftable @code
759 @item --rat-selected-color <string>
760 Color of selected rats. Default: @samp{#00ffff}
761 @end ftable
762 %end-doc
763 */
764   COLOR (RatSelectedColor, "#00ffff", "rat-selected-color",
765 	 "color of selected rats"),
766 
767 /* %start-doc options "3 Colors"
768 @ftable @code
769 @item --connected-color <string>
770 Color to indicate physical connections. Default: @samp{#00ff00}
771 @end ftable
772 %end-doc
773 */
774   COLOR (ConnectedColor, "#00ff00", "connected-color",
775 	 "color to indicate physically connected objects"),
776 
777 /* %start-doc options "3 Colors"
778 @ftable @code
779 @item --found-color <string>
780 Color to indicate logical connections. Default: @samp{#ff00ff}
781 @end ftable
782 %end-doc
783 */
784   COLOR (FoundColor, "#ff00ff", "found-color",
785 	 "color to indicate logically connected objects"),
786 
787 /* %start-doc options "3 Colors"
788 @ftable @code
789 @item --off-limit-color <string>
790 Color of off-canvas area. Default: @samp{#cccccc}
791 @end ftable
792 %end-doc
793 */
794   COLOR (OffLimitColor, "#cccccc", "off-limit-color",
795 	 "color of off-canvas area"),
796 
797 /* %start-doc options "3 Colors"
798 @ftable @code
799 @item --grid-color <string>
800 Color of the grid. Default: @samp{#ff0000}
801 @end ftable
802 %end-doc
803 */
804   COLOR (GridColor, "#ff0000", "grid-color", "color of the grid"),
805 
806 /* %start-doc options "3 Colors"
807 @ftable @code
808 @item --layer-color-<n> <string>
809 Color of layer @code{<n>}, where @code{<n>} is an integer from 1 to 16.
810 @end ftable
811 %end-doc
812 */
813   LAYERCOLOR (1, "#8b2323"),
814   LAYERCOLOR (2, "#3a5fcd"),
815   LAYERCOLOR (3, "#104e8b"),
816   LAYERCOLOR (4, "#cd3700"),
817   LAYERCOLOR (5, "#548b54"),
818   LAYERCOLOR (6, "#8b7355"),
819   LAYERCOLOR (7, "#00868b"),
820   LAYERCOLOR (8, "#228b22"),
821   LAYERCOLOR (9, "#8b2323"),
822   LAYERCOLOR (10, "#3a5fcd"),
823   LAYERCOLOR (11, "#104e8b"),
824   LAYERCOLOR (12, "#cd3700"),
825   LAYERCOLOR (13, "#548b54"),
826   LAYERCOLOR (14, "#8b7355"),
827   LAYERCOLOR (15, "#00868b"),
828   LAYERCOLOR (16, "#228b22"),
829 /* %start-doc options "3 Colors"
830 @ftable @code
831 @item --layer-selected-color-<n> <string>
832 Color of layer @code{<n>}, when selected. @code{<n>} is an integer from 1 to 16.
833 @end ftable
834 %end-doc
835 */
836   LAYERSELCOLOR (1),
837   LAYERSELCOLOR (2),
838   LAYERSELCOLOR (3),
839   LAYERSELCOLOR (4),
840   LAYERSELCOLOR (5),
841   LAYERSELCOLOR (6),
842   LAYERSELCOLOR (7),
843   LAYERSELCOLOR (8),
844   LAYERSELCOLOR (9),
845   LAYERSELCOLOR (10),
846   LAYERSELCOLOR (11),
847   LAYERSELCOLOR (12),
848   LAYERSELCOLOR (13),
849   LAYERSELCOLOR (14),
850   LAYERSELCOLOR (15),
851   LAYERSELCOLOR (16),
852 
853 /* %start-doc options "3 Colors"
854 @ftable @code
855 @item --warn-color <string>
856 Color of offending objects during DRC. Default value is @code{"#ff8000"}
857 @end ftable
858 %end-doc
859 */
860   COLOR (WarnColor, "#ff8000", "warn-color", "color of offending objects during DRC"),
861 
862 /* %start-doc options "3 Colors"
863 @ftable @code
864 @item --mask-color <string>
865 Color of the mask layer. Default value is @code{"#ff0000"}
866 @end ftable
867 %end-doc
868 */
869   COLOR (MaskColor, "#ff0000", "mask-color", "color for solder mask"),
870 
871 
872 /* %start-doc options "5 Sizes"
873 All parameters should be given with an unit. If no unit is given, 1/100 mil
874 (cmil) will be used. Write units without space to the
875 number like @code{3mm}, not @code{3 mm}.
876 Valid Units are:
877  @table @samp
878    @item km
879     Kilometer
880    @item m
881     Meter
882    @item cm
883     Centimeter
884    @item mm
885     Millimeter
886    @item um
887     Micrometer
888    @item nm
889     Nanometer
890    @item in
891     Inch (1in = 0.0254m)
892    @item mil
893     Mil (1000mil = 1in)
894    @item cmil
895     Centimil (1/100 mil)
896 @end table
897 
898 @ftable @code
899 @item --via-thickness <num>
900 Default diameter of vias. Default value is @code{60mil}.
901 @end ftable
902 %end-doc
903 */
904   CSET (ViaThickness, MIL_TO_COORD(60), "via-thickness",
905   "default diameter of vias in 1/100 mil"),
906 
907 /* %start-doc options "5 Sizes"
908 @ftable @code
909 @item --via-drilling-hole <num>
910 Default diameter of holes. Default value is @code{28mil}.
911 @end ftable
912 %end-doc
913 */
914   CSET (ViaDrillingHole, MIL_TO_COORD(28), "via-drilling-hole",
915   "default diameter of holes"),
916 
917 /* %start-doc options "5 Sizes"
918 @ftable @code
919 @item --via-solder-mask-clerance <num>
920 Default soldermask clearance around vias. Default value is @code{0mil}.
921 @end ftable
922 %end-doc
923 */
924   CSET (ViaMaskAperture, MIL_TO_COORD(0), "via-solder-mask-aperture",
925         "default solder mask aperture for vias"),
926 
927 /* %start-doc options "5 Sizes"
928 @ftable @code
929 @item --line-thickness <num>
930 Default thickness of new lines. Default value is @code{10mil}.
931 @end ftable
932 %end-doc
933 */
934   CSET (LineThickness, MIL_TO_COORD(10), "line-thickness",
935 	"initial thickness of new lines"),
936 
937 /* %start-doc options "5 Sizes"
938 @ftable @code
939 @item --rat-thickness <num><unit>
940 Thickness of rats. If no unit is given, PCB units are assumed (i.e. 100
941 means "1 nm"). This option allows for a special unit @code{px} which
942 sets the rat thickness to a fixed value in terms of screen pixels.
943 Maximum fixed thickness is 100px. Minimum saling rat thickness is 101nm.
944 Default value is @code{10mil}.
945 @end ftable
946 %end-doc
947 */
948   CSET (RatThickness, MIL_TO_COORD(10), "rat-thickness", "thickness of rat lines"),
949 
950 /* %start-doc options "5 Sizes"
951 @ftable @code
952 @item --keepaway <num>
953 Default minimum distance between a track and adjacent copper.
954 Default value is @code{10mil}.
955 @end ftable
956 %end-doc
957 */
958   CSET (Keepaway, MIL_TO_COORD(10), "keepaway", "minimum distance between adjacent copper"),
959 
960 /* %start-doc options "5 Sizes"
961 @ftable @code
962 @item --default-PCB-width <num>
963 Default width of the canvas. Default value is @code{6000mil}.
964 @end ftable
965 %end-doc
966 */
967   CSET (MaxWidth, MIL_TO_COORD(6000), "default-PCB-width",
968   "default width of the canvas"),
969 
970 /* %start-doc options "5 Sizes"
971 @ftable @code
972 @item --default-PCB-height <num>
973 Default height of the canvas. Default value is @code{5000mil}.
974 @end ftable
975 %end-doc
976 */
977   CSET (MaxHeight, MIL_TO_COORD(5000), "default-PCB-height",
978   "default height of the canvas"),
979 
980 /* %start-doc options "5 Sizes"
981 @ftable @code
982 @item --text-scale <num>
983 Default text scale. This value is in percent. Default value is @code{100}.
984 @end ftable
985 %end-doc
986 */
987   ISET (TextScale, 100, "text-scale", "default text scale in percent"),
988 
989 /* %start-doc options "5 Sizes"
990 @ftable @code
991 @item --alignment-distance <num>
992 Specifies the distance between the board outline and alignment targets.
993 Default value is @code{2mil}.
994 @end ftable
995 %end-doc
996 */
997   CSET (AlignmentDistance, MIL_TO_COORD(2), "alignment-distance",
998   "distance between the boards outline and alignment targets"),
999 
1000 /* %start-doc options "7 DRC Options"
1001 All parameters should be given with an unit. If no unit is given, 1/100 mil
1002 (cmil) will be used for backward compability. Valid units are given in section
1003 @ref{Sizes}.
1004 %end-doc
1005 */
1006 
1007 
1008 /* %start-doc options "7 DRC Options"
1009 @ftable @code
1010 @item --bloat <num>
1011 Minimum spacing. Default value is @code{10mil}.
1012 @end ftable
1013 %end-doc
1014 */
1015   CSET (Bloat, MIL_TO_COORD(10), "bloat", "DRC minimum spacing in 1/100 mil"),
1016 
1017 /* %start-doc options "7 DRC Options"
1018 @ftable @code
1019 @item --shrink <num>
1020 Minimum touching overlap. Default value is @code{10mil}.
1021 @end ftable
1022 %end-doc
1023 */
1024   CSET (Shrink, MIL_TO_COORD(10), "shrink", "DRC minimum overlap in 1/100 mils"),
1025 
1026 /* %start-doc options "7 DRC Options"
1027 @ftable @code
1028 @item --min-width <num>
1029 Minimum width of copper. Default value is @code{10mil}.
1030 @end ftable
1031 %end-doc
1032 */
1033   CSET (minWid, MIL_TO_COORD(10), "min-width", "DRC minimum copper spacing"),
1034 
1035 /* %start-doc options "7 DRC Options"
1036 @ftable @code
1037 @item --min-silk <num>
1038 Minimum width of lines in silk. Default value is @code{10mil}.
1039 @end ftable
1040 %end-doc
1041 */
1042   CSET (minSlk, MIL_TO_COORD(10), "min-silk", "DRC minimum silk width"),
1043 
1044 /* %start-doc options "7 DRC Options"
1045 @ftable @code
1046 @item --min-drill <num>
1047 Minimum diameter of holes. Default value is @code{15mil}.
1048 @end ftable
1049 %end-doc
1050 */
1051   CSET (minDrill, MIL_TO_COORD(15), "min-drill", "DRC minimum drill diameter"),
1052 
1053 /* %start-doc options "7 DRC Options"
1054 @ftable @code
1055 @item --min-ring <num>
1056 Minimum width of annular ring. Default value is @code{10mil}.
1057 @end ftable
1058 %end-doc
1059 */
1060   CSET (minRing, MIL_TO_COORD(10), "min-ring", "DRC minimum annular ring"),
1061 
1062 
1063 /* %start-doc options "5 Sizes"
1064 @ftable @code
1065 @item --grid <num>
1066 Initial grid size. Default value is @code{10mil}.
1067 @end ftable
1068 %end-doc
1069 */
1070   CSET (Grid, MIL_TO_COORD(10), "grid", "Initial grid size in 1/100 mil"),
1071 
1072 /* %start-doc options "5 Sizes"
1073 @ftable @code
1074 @item --minimum polygon area <num>
1075 Minimum polygon area.
1076 @end ftable
1077 %end-doc
1078 */
1079   RSET (IsleArea, MIL_TO_COORD(100) * MIL_TO_COORD(100), "minimum polygon area", 0),
1080 
1081 
1082 /* %start-doc options "5 Sizes"
1083 @ftable @code
1084 @item --paste-adjust <num>
1085 Adjust pad thickness in paste layer. Default value is @code{0}.
1086 Shrinking the pads is done with a negative amount.
1087 
1088 Example:
1089 @example
1090 pcb -x gerber --paste-adjust -0.07mm filename.pcb
1091 @end example
1092 @end ftable
1093 %end-doc
1094 */
1095   CSET (PasteAdjust, MIL_TO_COORD(0), "paste-adjust", "Adjustment to pad thickness in paste layer in 1/100 mil"),
1096 
1097 
1098 /* %start-doc options "1 General Options"
1099 @ftable @code
1100 @item --backup-interval
1101 Time between automatic backups in seconds. Set to @code{0} to disable.
1102 The default value is @code{60}.
1103 @end ftable
1104 %end-doc
1105 */
1106   ISET (BackupInterval, 60, "backup-interval",
1107   "Time between automatic backups in seconds. Set to 0 to disable"),
1108 
1109 /* %start-doc options "4 Layer Names"
1110 @ftable @code
1111 @item --layer-name-1 <string>
1112 Name of the 1st Layer. Default is @code{"top"}.
1113 @end ftable
1114 %end-doc
1115 */
1116   LAYERNAME (1, "top"),
1117 
1118 /* %start-doc options "4 Layer Names"
1119 @ftable @code
1120 @item --layer-name-2 <string>
1121 Name of the 2nd Layer. Default is @code{"ground"}.
1122 @end ftable
1123 %end-doc
1124 */
1125   LAYERNAME (2, "ground"),
1126 
1127 /* %start-doc options "4 Layer Names"
1128 @ftable @code
1129 @item --layer-name-3 <string>
1130 Name of the 3nd Layer. Default is @code{"signal2"}.
1131 @end ftable
1132 %end-doc
1133 */
1134   LAYERNAME (3, "signal2"),
1135 
1136 /* %start-doc options "4 Layer Names"
1137 @ftable @code
1138 @item --layer-name-4 <string>
1139 Name of the 4rd Layer. Default is @code{"signal3"}.
1140 @end ftable
1141 %end-doc
1142 */
1143   LAYERNAME (4, "signal3"),
1144 
1145 /* %start-doc options "4 Layer Names"
1146 @ftable @code
1147 @item --layer-name-5 <string>
1148 Name of the 5rd Layer. Default is @code{"power"}.
1149 @end ftable
1150 %end-doc
1151 */
1152   LAYERNAME (5, "power"),
1153 
1154 /* %start-doc options "4 Layer Names"
1155 @ftable @code
1156 @item --layer-name-6 <string>
1157 Name of the 6rd Layer. Default is @code{"bottom"}.
1158 @end ftable
1159 %end-doc
1160 */
1161   LAYERNAME (6, "bottom"),
1162 
1163 /* %start-doc options "4 Layer Names"
1164 @ftable @code
1165 @item --layer-name-7 <string>
1166 Name of the 7rd Layer. Default is @code{"outline"}.
1167 @end ftable
1168 %end-doc
1169 */
1170   LAYERNAME (7, "outline"),
1171 
1172 /* %start-doc options "4 Layer Names"
1173 @ftable @code
1174 @item --layer-name-8 <string>
1175 Name of the 8rd Layer. Default is @code{"spare"}.
1176 @end ftable
1177 %end-doc
1178 */
1179   LAYERNAME (8, "spare"),
1180 
1181 /* %start-doc options "1 General Options"
1182 @ftable @code
1183 @item --groups <string>
1184 Layer group string. Defaults to @code{"1,c:2:3:4:5:6,s:7:8"}.
1185 @end ftable
1186 %end-doc
1187 */
1188   SSET (Groups, "1,c:2:3:4:5:6,s:7:8", "groups", "Layer group string"),
1189 
1190 
1191 /* %start-doc options "6 Commands"
1192 pcb uses external commands for input output operations. These commands can be
1193 configured at start-up to meet local requirements. The command string may include
1194 special sequences @code{%f}, @code{%p} or @code{%a}. These are replaced when the
1195 command is called. The sequence @code{%f} is replaced by the file name,
1196 @code{%p} gets the path and @code{%a} indicates a package name.
1197 %end-doc
1198 */
1199 
1200 /* %start-doc options "6 Commands"
1201 @ftable @code
1202 @item --font-command <string>
1203 Command to load a font.
1204 @end ftable
1205 %end-doc
1206 */
1207   SSET (FontCommand, "", "font-command", "Command to load a font"),
1208 
1209 /* %start-doc options "6 Commands"
1210 @ftable @code
1211 @item --file-command <string>
1212 Command to read a file.
1213 @end ftable
1214 %end-doc
1215 */
1216   SSET (FileCommand, "", "file-command", "Command to read a file"),
1217 
1218 /* %start-doc options "6 Commands"
1219 @ftable @code
1220 @item --element-command <string>
1221 Command to read a footprint. @*
1222 Defaults to @code{"M4PATH='%p';export M4PATH;echo 'include(%f)' | m4"}
1223 @end ftable
1224 %end-doc
1225 */
1226   SSET (ElementCommand,
1227 	"M4PATH='%p';export M4PATH;echo 'include(%f)' | " GNUM4,
1228 	"element-command", "Command to read a footprint"),
1229 
1230 /* %start-doc options "6 Commands"
1231 @ftable @code
1232 @item --print-file <string>
1233 Command to print to a file.
1234 @end ftable
1235 %end-doc
1236 */
1237   SSET (PrintFile, "%f.output", "print-file", "Command to print to a file"),
1238 
1239 /* %start-doc options "6 Commands"
1240 @ftable @code
1241 @item --lib-command-dir <string>
1242 Path to the command that queries the library.
1243 @end ftable
1244 %end-doc
1245 */
1246   SSET (LibraryCommandDir, PCBLIBDIR, "lib-command-dir",
1247        "Path to the command that queries the library"),
1248 
1249 /* %start-doc options "6 Commands"
1250 @ftable @code
1251 @item --lib-command <string>
1252 Command to query the library. @*
1253 Defaults to @code{"QueryLibrary.sh '%p' '%f' %a"}
1254 @end ftable
1255 %end-doc
1256 */
1257   SSET (LibraryCommand, "QueryLibrary.sh '%p' '%f' %a",
1258        "lib-command", "Command to query the library"),
1259 
1260 /* %start-doc options "6 Commands"
1261 @ftable @code
1262 @item --lib-contents-command <string>
1263 Command to query the contents of the library. @*
1264 Defaults to @code{"ListLibraryContents.sh %p %f"} or,
1265 on Windows builds, an empty string (to disable this feature).
1266 @end ftable
1267 %end-doc
1268 */
1269   SSET (LibraryContentsCommand,
1270 #ifdef __WIN32__
1271 	"",
1272 #else
1273 	"ListLibraryContents.sh '%p' '%f'",
1274 #endif
1275 	"lib-contents-command", "Command to query the contents of the library"),
1276 
1277 /* %start-doc options "5 Paths"
1278 @ftable @code
1279 @item --lib-newlib <string>
1280 Top level directory for the newlib style library.
1281 @end ftable
1282 %end-doc
1283 */
1284   SSET (LibraryTree, PCBTREEPATH, "lib-newlib",
1285 	"Top level directory for the newlib style library"),
1286 
1287 /* %start-doc options "6 Commands"
1288 @ftable @code
1289 @item --save-command <string>
1290 Command to save to a file.
1291 @end ftable
1292 %end-doc
1293 */
1294   SSET (SaveCommand, "", "save-command", "Command to save to a file"),
1295 
1296 /* %start-doc options "5 Paths"
1297 @ftable @code
1298 @item --lib-name <string>
1299 The default filename for the library.
1300 @end ftable
1301 %end-doc
1302 */
1303   SSET (LibraryFilename, LIBRARYFILENAME, "lib-name",
1304 				"The default filename for the library"),
1305 
1306 /* %start-doc options "5 Paths"
1307 @ftable @code
1308 @item --default-font <string>
1309 The name of the default font.
1310 @end ftable
1311 %end-doc
1312 */
1313   SSET (FontFile, "default_font", "default-font",
1314 	"File name of default font"),
1315 
1316 /* %start-doc options "1 General Options"
1317 @ftable @code
1318 @item --route-styles <string>
1319 A string that defines the route styles. Parameters are (in order):
1320 line width, via hole size, via ring size, clearance, solder mask clearance.
1321 The units are cmils. Defaults to @*
1322 @code{"Signal,1000,3600,2000,1000,0:Power,2500,6000,3500,1000,0
1323 	:Fat,4000,6000,3500,1000,0:Skinny,600,2402,1181,600,0"}
1324 @end ftable
1325 %end-doc
1326 */
1327   SSET (Routes, "Signal,1000,3600,2000,1000,0:Power,2500,6000,3500,1000,0"
1328 	":Fat,4000,6000,3500,1000,0:Skinny,600,2402,1181,600,0", "route-styles",
1329 	"A string that defines the route styles"),
1330 
1331 /* %start-doc options "5 Paths"
1332 @ftable @code
1333 @item --file-path <string>
1334 A colon separated list of directories or commands (starts with '|'). The path
1335 is passed to the program specified in @option{--file-command} together with the selected
1336 filename.
1337 @end ftable
1338 %end-doc
1339 */
1340   SSET (FilePath, "", "file-path", 0),
1341 
1342 /* %start-doc options "6 Commands"
1343 @ftable @code
1344 @item --rat-command <string>
1345 Command for reading a netlist. Sequence @code{%f} is replaced by the netlist filename.
1346 @end ftable
1347 %end-doc
1348 */
1349   SSET (RatCommand, "", "rat-command", "Command for reading a netlist"),
1350 
1351 /* %start-doc options "5 Paths"
1352 @ftable @code
1353 @item --font-path <string>
1354 A colon separated list of directories to search the default font. Defaults to
1355 the default library path.
1356 @end ftable
1357 %end-doc
1358 */
1359   SSET (FontPath, PCBLIBPATH, "font-path",
1360        "Colon separated list of directories to search the default font"),
1361 
1362 /* %start-doc options "1 General Options"
1363 @ftable @code
1364 @item --element-path <string>
1365 A colon separated list of directories or commands (starts with '|').
1366 The path is passed to the program specified in @option{--element-command}.
1367 @end ftable
1368 %end-doc
1369 */
1370   SSET(ElementPath, PCBLIBPATH, "element-path",
1371       "A colon separated list of directories or commands (starts with '|')"),
1372 
1373 /* %start-doc options "5 Paths"
1374 @ftable @code
1375 @item --lib-path <string>
1376 A colon separated list of directories that will be passed to the commands specified
1377 by @option{--element-command} and @option{--element-contents-command}.
1378 @end ftable
1379 %end-doc
1380 */
1381   SSET (LibraryPath, PCBLIBPATH, "lib-path",
1382        "A colon separated list of directories"),
1383 
1384 /* %start-doc options "1 General Options"
1385 @ftable @code
1386 @item --action-script <string>
1387 If set, this file is executed at startup.
1388 @end ftable
1389 %end-doc
1390 */
1391   SSET (ScriptFilename, 0, "action-script",
1392 	     "If set, this file is executed at startup"),
1393 
1394 /* %start-doc options "1 General Options"
1395 @ftable @code
1396 @item --action-string <string>
1397 If set, this string of actions is executed at startup.
1398 @end ftable
1399 %end-doc
1400 */
1401   SSET (ActionString, 0, "action-string",
1402        "If set, this is executed at startup"),
1403 
1404 /* %start-doc options "1 General Options"
1405 @ftable @code
1406 @item --fab-author <string>
1407 Name of author to be put in the Gerber files.
1408 @end ftable
1409 %end-doc
1410 */
1411   SSET (FabAuthor, "", "fab-author",
1412        "Name of author to be put in the Gerber files"),
1413 
1414 /* %start-doc options "1 General Options"
1415 @ftable @code
1416 @item --layer-stack <string>
1417 Initial layer stackup, for setting up an export. A comma separated list of layer
1418 names, layer numbers and layer groups.
1419 @end ftable
1420 %end-doc
1421 */
1422   SSET (InitialLayerStack, "", "layer-stack",
1423 	"Initial layer stackup, for setting up an export."),
1424 
1425   SSET (MakeProgram, NULL, "make-program",
1426 	"Sets the name and optionally full path to a make(3) program"),
1427   SSET (GnetlistProgram, NULL, "gnetlist",
1428 	"Sets the name and optionally full path to the gnetlist(3) program"),
1429 
1430 /* %start-doc options "2 General GUI Options"
1431 @ftable @code
1432 @item --pinout-offset-x <num>
1433 Horizontal offset of the pin number display. Defaults to @code{100mil}.
1434 @end ftable
1435 %end-doc
1436 */
1437   CSET (PinoutOffsetX, MIL_TO_COORD(1), "pinout-offset-x",
1438        "Horizontal offset of the pin number display in mil"),
1439 
1440 /* %start-doc options "2 General GUI Options"
1441 @ftable @code
1442 @item --pinout-offset-y <num>
1443 Vertical offset of the pin number display. Defaults to @code{100mil}.
1444 @end ftable
1445 %end-doc
1446 */
1447   CSET (PinoutOffsetY, MIL_TO_COORD(1), "pinout-offset-y",
1448        "Vertical offset of the pin number display in mil"),
1449 
1450 /* %start-doc options "2 General GUI Options"
1451 @ftable @code
1452 @item --pinout-text-offset-x <num>
1453 Horizontal offset of the pin name display. Defaults to @code{800mil}.
1454 @end ftable
1455 %end-doc
1456 */
1457   CSET (PinoutTextOffsetX, MIL_TO_COORD(8), "pinout-text-offset-x",
1458        "Horizontal offset of the pin name display in mil"),
1459 
1460 /* %start-doc options "2 General GUI Options"
1461 @ftable @code
1462 @item --pinout-text-offset-y <num>
1463 Vertical offset of the pin name display. Defaults to @code{-100mil}.
1464 @end ftable
1465 %end-doc
1466 */
1467   CSET (PinoutTextOffsetY, MIL_TO_COORD(-1), "pinout-text-offset-y",
1468        "Vertical offset of the pin name display in mil"),
1469 
1470 /* %start-doc options "2 General GUI Options"
1471 @ftable @code
1472 @item --draw-grid
1473 If set, draw the grid at start-up.
1474 @end ftable
1475 %end-doc
1476 */
1477   BSET (DrawGrid, 0, "draw-grid", "If set, draw the grid at start-up"),
1478 
1479 /* %start-doc options "2 General GUI Options"
1480 @ftable @code
1481 @item --clear-line
1482 If set, new lines clear polygons.
1483 @end ftable
1484 %end-doc
1485 */
1486   BSET (ClearLine, 1, "clear-line", "If set, new lines clear polygons"),
1487 
1488 /* %start-doc options "2 General GUI Options"
1489 @ftable @code
1490 @item --full-poly
1491 If set, new polygons are full ones.
1492 @end ftable
1493 %end-doc
1494 */
1495   BSET (FullPoly, 0, "full-poly", 0),
1496 
1497 /* %start-doc options "2 General GUI Options"
1498 @ftable @code
1499 @item --unique-names
1500 If set, you will not be permitted to change the name of an component to match that
1501 of another component.
1502 @end ftable
1503 %end-doc
1504 */
1505   BSET (UniqueNames, 1, "unique-names", "Prevents identical component names"),
1506 
1507 /* %start-doc options "2 General GUI Options"
1508 @ftable @code
1509 @item --snap-pin
1510 If set, pin centers and pad end points are treated as additional grid points
1511 that the cursor can snap to.
1512 @end ftable
1513 %end-doc
1514 */
1515   BSET (SnapPin, 1, "snap-pin",
1516        "If set, the cursor snaps to pads and pin centers"),
1517 
1518 /* %start-doc options "1 General Options"
1519 @ftable @code
1520 @item --save-last-command
1521 If set, the last user command is saved.
1522 @end ftable
1523 %end-doc
1524 */
1525   BSET (SaveLastCommand, 0, "save-last-command", 0),
1526 
1527 /* %start-doc options "1 General Options"
1528 @ftable @code
1529 @item --save-in-tmp
1530 If set, all data which would otherwise be lost are saved in a temporary file
1531 @file{/tmp/PCB.%i.save} . Sequence @samp{%i} is replaced by the process ID.
1532 @end ftable
1533 %end-doc
1534 */
1535   BSET (SaveInTMP, 0, "save-in-tmp",
1536        "When set, all data which would otherwise be lost are saved in /tmp"),
1537 
1538 /* %start-doc options "1 General Options"
1539 @ftable @code
1540 @item --save-metric-only
1541 If set, save pcb files using only mm unit suffix rather than 'smart' mil/mm.
1542 @end ftable
1543 %end-doc
1544 */
1545   BSET (SaveMetricOnly, 0, "save-metric-only",
1546         "If set, save pcb files using only mm unit suffix rather than 'smart' mil/mm."),
1547 
1548 /* %start-doc options "2 General GUI Options"
1549 @ftable @code
1550 @item --all-direction-lines
1551 Allow all directions, when drawing new lines.
1552 @end ftable
1553 %end-doc
1554 */
1555   BSET (AllDirectionLines, 0, "all-direction-lines",
1556        "Allow all directions, when drawing new lines"),
1557 
1558 /* %start-doc options "2 General GUI Options"
1559 @ftable @code
1560 @item --show-number
1561 Pinout shows number.
1562 @end ftable
1563 %end-doc
1564 */
1565   BSET (ShowNumber, 0, "show-number", "Pinout shows number"),
1566 
1567 /* %start-doc options "1 General Options"
1568 @ftable @code
1569 @item --reset-after-element
1570 If set, all found connections are reset before a new component is scanned.
1571 @end ftable
1572 %end-doc
1573 */
1574   BSET (ResetAfterElement, 1, "reset-after-element",
1575        "If set, all found connections are reset before a new component is scanned"),
1576 
1577 /* %start-doc options "1 General Options"
1578 @ftable @code
1579 @item --auto-buried-vias
1580 Enables automatically created vias (during line moves and layer switch) to be buriad/blind vias
1581 @end ftable
1582 %end-doc
1583 */
1584   BSET (AutoBuriedVias, 0, "auto-buried-vias",
1585        "Enables automatically created vias to be buriad/blind vias"),
1586 
1587 /* %start-doc options "1 General Options"
1588 @ftable @code
1589 @item --ring-bell-finished
1590 Execute the bell command when all rats are routed.
1591 @end ftable
1592 %end-doc
1593 */
1594   BSET (RingBellWhenFinished, 0, "ring-bell-finished",
1595        "Execute the bell command when all rats are routed"),
1596 };
1597 
REGISTER_ATTRIBUTES(main_attribute_list)1598 REGISTER_ATTRIBUTES (main_attribute_list)
1599 /* ----------------------------------------------------------------------
1600  * post-process settings.
1601  */
1602      static void settings_post_process ()
1603 {
1604   char *tmps;
1605 
1606   if (Settings.LibraryCommand != NULL &&
1607       Settings.LibraryCommand[0] != '\0' &&
1608       Settings.LibraryCommand[0] != PCB_DIR_SEPARATOR_C &&
1609       Settings.LibraryCommand[0] != '.')
1610     {
1611       Settings.LibraryCommand
1612 	=
1613 	Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
1614 		Settings.LibraryCommand,
1615 		NULL);
1616     }
1617   if (Settings.LibraryContentsCommand != NULL &&
1618       Settings.LibraryContentsCommand[0] != '\0' &&
1619       Settings.LibraryContentsCommand[0] != PCB_DIR_SEPARATOR_C &&
1620       Settings.LibraryContentsCommand[0] != '.')
1621     {
1622       Settings.LibraryContentsCommand
1623 	=
1624 	Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
1625 		Settings.LibraryContentsCommand, NULL);
1626     }
1627 
1628   if (Settings.LineThickness > MAX_LINESIZE
1629       || Settings.LineThickness < MIN_LINESIZE)
1630     Settings.LineThickness = MIL_TO_COORD(10);
1631 
1632   if (Settings.ViaThickness > MAX_PINORVIASIZE
1633       || Settings.ViaThickness < MIN_PINORVIASIZE)
1634     Settings.ViaThickness = MIL_TO_COORD(40);
1635 
1636   if (Settings.ViaDrillingHole <= 0)
1637     Settings.ViaDrillingHole =
1638       DEFAULT_DRILLINGHOLE * Settings.ViaThickness / 100;
1639 
1640   Settings.MaxWidth  = CLAMP (Settings.MaxWidth, MIN_SIZE, MAX_COORD);
1641   Settings.MaxHeight = CLAMP (Settings.MaxHeight, MIN_SIZE, MAX_COORD);
1642 
1643   ParseRouteString (Settings.Routes, &Settings.RouteStyle[0], "cmil");
1644 
1645   /*
1646    * Make sure we have settings for some various programs we may wish
1647    * to call
1648    */
1649   if (Settings.MakeProgram == NULL) {
1650     tmps = getenv ("PCB_MAKE_PROGRAM");
1651     if (tmps != NULL)
1652       Settings.MakeProgram = strdup (tmps);
1653   }
1654   if (Settings.MakeProgram == NULL) {
1655     Settings.MakeProgram = strdup ("make");
1656   }
1657 
1658   if (Settings.GnetlistProgram == NULL) {
1659     tmps = getenv ("PCB_GNETLIST");
1660     if (tmps != NULL)
1661       Settings.GnetlistProgram = strdup (tmps);
1662   }
1663   if (Settings.GnetlistProgram == NULL) {
1664     Settings.GnetlistProgram = strdup ("gnetlist");
1665   }
1666 
1667   if (grid_units)
1668     Settings.grid_unit = get_unit_struct (grid_units);
1669   if (!grid_units || Settings.grid_unit == NULL)
1670     Settings.grid_unit = get_unit_struct ("mil");
1671 
1672   copy_nonzero_increments (get_increments_struct (METRIC), &increment_mm);
1673   copy_nonzero_increments (get_increments_struct (IMPERIAL), &increment_mil);
1674 
1675   Settings.increments = get_increments_struct (Settings.grid_unit->family);
1676 }
1677 
1678 /*!
1679  * \brief Print help or version messages.
1680  */
1681 static void
print_version()1682 print_version ()
1683 {
1684   printf ("PCB version %s\n", VERSION);
1685   exit (0);
1686 }
1687 
1688 /* ----------------------------------------------------------------------
1689  * Figure out the canonical name of the executed program
1690  * and fix up the defaults for various paths
1691  */
1692 char *bindir = NULL;
1693 char *exec_prefix = NULL;
1694 char *pcblibdir = NULL;
1695 char *pcblibpath = NULL;
1696 char *pcbtreedir = NULL;
1697 char *pcbtreepath = NULL;
1698 char *homedir = NULL;
1699 
1700 /*!
1701  * \brief See if argv0 has enough of a path to let lrealpath give the
1702  * real path.
1703  *
1704  * This should be the case if you invoke pcb with something like
1705  * /usr/local/bin/pcb or ./pcb or ./foo/pcb but if you just use pcb and
1706  * it exists in your path, you'll just get back pcb again.
1707  */
1708 static void
InitPaths(char * argv0)1709 InitPaths (char *argv0)
1710 {
1711   size_t l;
1712   int i;
1713   int haspath;
1714   char *t1, *t2;
1715   int found_bindir = 0;
1716 
1717   haspath = 0;
1718   for (i = 0; i < strlen (argv0) ; i++)
1719     {
1720       if (argv0[i] == PCB_DIR_SEPARATOR_C)
1721 	haspath = 1;
1722     }
1723 
1724 #ifdef DEBUG
1725   printf ("InitPaths (%s): haspath = %d\n", argv0, haspath);
1726 #endif
1727 
1728   if (haspath)
1729     {
1730       bindir = strdup (lrealpath (argv0));
1731       found_bindir = 1;
1732     }
1733   else
1734     {
1735       char *path, *p, *tmps;
1736       struct stat sb;
1737       int r;
1738 
1739       tmps = getenv ("PATH");
1740 
1741       if (tmps != NULL)
1742 	{
1743 	  path = strdup (tmps);
1744 
1745 	  /* search through the font path for a font file */
1746 	  for (p = strtok (path, PCB_PATH_DELIMETER); p && *p;
1747 	       p = strtok (NULL, PCB_PATH_DELIMETER))
1748 	    {
1749 #ifdef DEBUG
1750 	      printf ("Looking for %s in %s\n", argv0, p);
1751 #endif
1752 	      if ( (tmps = (char *)malloc ( (strlen (argv0) + strlen (p) + 2) * sizeof (char))) == NULL )
1753 		{
1754 		  fprintf (stderr, "InitPaths():  malloc failed\n");
1755 		  exit (1);
1756 		}
1757 	      sprintf (tmps, "%s%s%s", p, PCB_DIR_SEPARATOR_S, argv0);
1758 	      r = stat (tmps, &sb);
1759 	      if (r == 0)
1760 		{
1761 #ifdef DEBUG
1762 		  printf ("Found it:  \"%s\"\n", tmps);
1763 #endif
1764 		  bindir = lrealpath (tmps);
1765 		  found_bindir = 1;
1766 		  free (tmps);
1767 		  break;
1768 		}
1769 	      free (tmps);
1770 	    }
1771 	  free (path);
1772 	}
1773     }
1774 
1775 #ifdef DEBUG
1776   printf ("InitPaths():  bindir = \"%s\"\n", bindir);
1777 #endif
1778 
1779   if (found_bindir)
1780     {
1781       /* strip off the executible name leaving only the path */
1782       t2 = NULL;
1783       t1 = strchr (bindir, PCB_DIR_SEPARATOR_C);
1784       while (t1 != NULL && *t1 != '\0')
1785         {
1786           t2 = t1;
1787           t1 = strchr (t2 + 1, PCB_DIR_SEPARATOR_C);
1788         }
1789       if (t2 != NULL)
1790         *t2 = '\0';
1791 
1792 #ifdef DEBUG
1793       printf ("After stripping off the executible name, we found\n");
1794       printf ("bindir = \"%s\"\n", bindir);
1795 #endif
1796     }
1797   else
1798     {
1799       /* we have failed to find out anything from argv[0] so fall back to the original
1800        * install prefix
1801        */
1802        bindir = strdup (BINDIR);
1803     }
1804 
1805   /* now find the path to exec_prefix */
1806   l = strlen (bindir) + 1 + strlen (BINDIR_TO_EXECPREFIX) + 1;
1807   if ( (exec_prefix = (char *) malloc (l * sizeof (char) )) == NULL )
1808     {
1809       fprintf (stderr, "InitPaths():  malloc failed\n");
1810       exit (1);
1811     }
1812   sprintf (exec_prefix, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
1813 	   BINDIR_TO_EXECPREFIX);
1814 
1815   /* now find the path to PCBLIBDIR */
1816   l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBLIBDIR) + 1;
1817   if ( (pcblibdir = (char *) malloc (l * sizeof (char) )) == NULL )
1818     {
1819       fprintf (stderr, "InitPaths():  malloc failed\n");
1820       exit (1);
1821     }
1822   sprintf (pcblibdir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
1823 	   BINDIR_TO_PCBLIBDIR);
1824 
1825   /* and the path to PCBTREEDIR */
1826   l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBTREEDIR) + 1;
1827   if ( (pcbtreedir = (char *) malloc (l * sizeof (char) )) == NULL )
1828     {
1829       fprintf (stderr, "InitPaths():  malloc failed\n");
1830       exit (1);
1831     }
1832   sprintf (pcbtreedir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
1833 	   BINDIR_TO_PCBTREEDIR);
1834 
1835   /* and the search path including PCBLIBDIR */
1836   l = strlen (pcblibdir) + 3;
1837   if ( (pcblibpath = (char *) malloc (l * sizeof (char) )) == NULL )
1838     {
1839       fprintf (stderr, "InitPaths():  malloc failed\n");
1840       exit (1);
1841     }
1842   sprintf (pcblibpath, ".%s%s", PCB_PATH_DELIMETER, pcblibdir);
1843 
1844   /* and the newlib search path */
1845   l = strlen (pcblibdir) + 1 + strlen (pcbtreedir)
1846     + strlen ("pcblib-newlib") + 2;
1847   if ( (pcbtreepath = (char *) malloc (l * sizeof (char) )) == NULL )
1848     {
1849       fprintf (stderr, "InitPaths():  malloc failed\n");
1850       exit (1);
1851     }
1852   sprintf (pcbtreepath, "%s%s%s%spcblib-newlib", pcbtreedir,
1853 	PCB_PATH_DELIMETER, pcblibdir,
1854 	PCB_DIR_SEPARATOR_S);
1855 
1856 #ifdef DEBUG
1857   printf ("bindir      = %s\n", bindir);
1858   printf ("pcblibdir   = %s\n", pcblibdir);
1859   printf ("pcblibpath  = %s\n", pcblibpath);
1860   printf ("pcbtreedir  = %s\n", pcbtreedir);
1861   printf ("pcbtreepath = %s\n", pcbtreepath);
1862 #endif
1863 
1864   l = sizeof (main_attribute_list) / sizeof (main_attribute_list[0]);
1865   for (i = 0; i < l ; i++)
1866     {
1867       if (NSTRCMP (main_attribute_list[i].name, "lib-command-dir") == 0)
1868 	{
1869 	  main_attribute_list[i].default_val.str_value = pcblibdir;
1870 	}
1871 
1872       if ( (NSTRCMP (main_attribute_list[i].name, "font-path") == 0)
1873 	   || (NSTRCMP (main_attribute_list[i].name, "element-path") == 0)
1874 	   || (NSTRCMP (main_attribute_list[i].name, "lib-path") == 0) )
1875 	{
1876 	  main_attribute_list[i].default_val.str_value = pcblibpath;
1877 	}
1878 
1879       if (NSTRCMP (main_attribute_list[i].name, "lib-newlib") == 0)
1880 	{
1881 	  main_attribute_list[i].default_val.str_value = pcbtreepath;
1882 	}
1883 
1884     }
1885 
1886     {
1887       char *tmps;
1888 
1889       tmps = getenv ("HOME");
1890 
1891       if (tmps == NULL) {
1892           tmps = getenv ("USERPROFILE");
1893       }
1894 
1895       if (tmps != NULL) {
1896           homedir = strdup (tmps);
1897       } else {
1898           homedir = NULL;
1899       }
1900 
1901     }
1902 }
1903 
1904 /* ----------------------------------------------------------------------
1905  * main program
1906  */
1907 
1908 char *program_name = 0;
1909 char *program_basename = 0;
1910 char *program_directory = 0;
1911 
1912 #include "dolists.h"
1913 
1914 /*!
1915  * \brief Free up memory allocated to the PCB.
1916  *
1917  * Why bother when we're about to exit ?\n
1918  * Because it removes some false positives from heap bug detectors such
1919  * as lib dmalloc.
1920  */
1921 void
pcb_main_uninit(void)1922 pcb_main_uninit (void)
1923 {
1924   if (gui->uninit != NULL)
1925     gui->uninit (gui);
1926 
1927   hid_uninit ();
1928 
1929   UninitBuffers ();
1930 
1931   FreePCBMemory (PCB);
1932   free (PCB);
1933   PCB = NULL;
1934 
1935   /*!
1936    * \warning Please do not free the below variables like:
1937    * \code
1938   for (i = 0; i < MAX_LAYER; i++)
1939     free (Settings.DefaultLayerName[i]);
1940 
1941   if (Settings.FontFile != NULL)
1942     {
1943       free (Settings.FontFile);
1944       Settings.FontFile = NULL;
1945     }
1946    * \endcode
1947    * as these are initialized to static strings and freeing them
1948    * causes segfaults when terminating the program.
1949    */
1950 
1951   uninit_strflags_buf ();
1952   uninit_strflags_layerlist ();
1953 
1954 #define free0(ptr) \
1955   do \
1956     { \
1957       if (ptr != NULL) \
1958         { \
1959           free (ptr); \
1960           ptr = 0; \
1961         } \
1962     } while (0)
1963 
1964   free0 (pcblibdir);
1965   free0 (homedir);
1966   free0 (bindir);
1967   free0 (exec_prefix);
1968   free0 (program_directory);
1969   free0 (Settings.MakeProgram);
1970   free0 (Settings.GnetlistProgram);
1971 
1972 #undef free0
1973 }
1974 
1975 /*!
1976  * \brief Main program.
1977  *
1978  * Init application:
1979  *
1980  * - make program name available for error handlers
1981  * - evaluate special options
1982  * - initialize toplevel shell and resources
1983  * - create an empty PCB with default symbols
1984  * - initialize all other widgets
1985  * - update screen and get size of drawing area
1986  * - evaluate command-line arguments
1987  * - register 'call on exit()' function
1988  */
1989 int
main(int argc,char * argv[])1990 main (int argc, char *argv[])
1991 {
1992   int i;
1993 
1994 #include "core_lists.h"
1995   setbuf (stdout, 0);
1996   InitPaths (argv[0]);
1997 
1998   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1999   textdomain (GETTEXT_PACKAGE);
2000   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2001 
2002 #ifdef ENABLE_NLS
2003   setlocale (LC_ALL, "");
2004   setlocale (LC_NUMERIC, "C");
2005 #endif
2006 
2007   srand ( time(NULL) ); /* Set seed for rand() */
2008 
2009   initialize_units();
2010   polygon_init ();
2011   hid_init ();
2012 
2013   hid_load_settings ();
2014 
2015   program_name = argv[0];
2016   program_basename = strrchr (program_name, PCB_DIR_SEPARATOR_C);
2017   if (program_basename)
2018     {
2019       program_directory = strdup (program_name);
2020       *strrchr (program_directory, PCB_DIR_SEPARATOR_C) = 0;
2021       program_basename++;
2022     }
2023   else
2024     {
2025       program_directory = strdup (".");
2026       program_basename = program_name;
2027     }
2028   Progname = program_basename;
2029 
2030   /* Print usage or version if requested.  Then exit.  */
2031   if (argc > 1 &&
2032       (strcmp (argv[1], "-h") == 0 ||
2033        strcmp (argv[1], "-?") == 0 ||
2034        strcmp (argv[1], "--help") == 0))
2035     usage ();
2036   if (argc > 1 && strcmp (argv[1], "-V") == 0)
2037     print_version ();
2038   /* Export pcb from command line if requested.  */
2039   if (argc > 1 && strcmp (argv[1], "-p") == 0)
2040     {
2041       exporter = gui = hid_find_printer ();
2042       argc--;
2043       argv++;
2044     }
2045   else if (argc > 2 && strcmp (argv[1], "-x") == 0)
2046     {
2047       exporter = gui = hid_find_exporter (argv[2]);
2048       argc -= 2;
2049       argv += 2;
2050     }
2051     /* Otherwise start GUI. */
2052   else
2053     gui = hid_find_gui ();
2054 
2055   /* Exit with error if GUI failed to start. */
2056   if (!gui)
2057     exit (1);
2058 
2059   /* Set up layers. */
2060   for (i = 0; i < MAX_LAYER; i++)
2061     {
2062       char buf[20];
2063       sprintf (buf, "signal%d", i + 1);
2064       Settings.DefaultLayerName[i] = strdup (buf);
2065       Settings.LayerColor[i] = "#c49350";
2066       Settings.LayerSelectedColor[i] = "#00ffff";
2067     }
2068 
2069   gui->parse_arguments (&argc, &argv);
2070 
2071   if (show_help || (argc > 1 && argv[1][0] == '-'))
2072     usage ();
2073   if (show_version)
2074     print_version ();
2075   if (show_defaults)
2076     print_defaults ();
2077   if (show_copyright)
2078     copyright ();
2079 
2080   settings_post_process ();
2081 
2082 
2083   if (show_actions)
2084     {
2085       print_actions ();
2086       exit (0);
2087     }
2088 
2089   if (do_dump_actions)
2090     {
2091       extern void dump_actions (void);
2092       dump_actions ();
2093       exit (0);
2094     }
2095 
2096   /* Create a new PCB object in memory */
2097   PCB = CreateNewPCB ();
2098   ParseGroupString (Settings.Groups, &PCB->LayerGroups, &PCB->Data->LayerN);
2099   /* Add silk layers to newly created PCB */
2100   CreateNewPCBPost (PCB, 1);
2101   if (argc > 1)
2102     command_line_pcb = argv[1];
2103 
2104   ResetStackAndVisibility ();
2105 
2106   InitCrosshair ();
2107   InitHandler ();
2108   InitBuffers ();
2109   SetMode (ARROW_MODE);
2110 
2111   if (command_line_pcb)
2112     {
2113       if (access(command_line_pcb, F_OK))
2114         {
2115 	   /* File does not exist, save the filename and continue with empty board */
2116 	   PCB->Filename = strdup (command_line_pcb);
2117 	} else {
2118 	   /* Hard fail if file exists and fails to load */
2119            if (LoadPCB (command_line_pcb))
2120              {
2121 	       fprintf(stderr, "LoadPCB: Failed to load existing file \"%s\". Is it supported PCB file?\n", command_line_pcb);
2122 	       exit(1);
2123 	     }
2124         }
2125     }
2126 
2127   if (Settings.InitialLayerStack
2128       && Settings.InitialLayerStack[0])
2129     {
2130       LayerStringToLayerStack (Settings.InitialLayerStack);
2131     }
2132 
2133   /* This must be called before any other atexit functions
2134    * are registered, as it configures an atexit function to
2135    * clean up and free various items of allocated memory,
2136    * and must be the last last atexit function to run.
2137    */
2138   leaky_init ();
2139 
2140   /* Register a function to be called when the program terminates.
2141    * This makes sure that data is saved even if LEX/YACC routines
2142    * abort the program.
2143    * If the OS doesn't have at least one of them,
2144    * the critical sections will be handled by parse_l.l
2145    */
2146   atexit (EmergencySave);
2147 
2148   /* read the library file and display it if it's not empty
2149    */
2150   if (!ReadLibraryContents () && Library.MenuN)
2151     hid_action ("LibraryChanged");
2152 
2153 #ifdef HAVE_LIBSTROKE
2154   stroke_init ();
2155 #endif
2156 
2157   if (Settings.ScriptFilename)
2158     {
2159       Message (_("Executing startup script file %s\n"),
2160 	       Settings.ScriptFilename);
2161       hid_actionl ("ExecuteFile", Settings.ScriptFilename, NULL);
2162     }
2163   if (Settings.ActionString)
2164     {
2165       Message (_("Executing startup action %s\n"), Settings.ActionString);
2166       hid_parse_actions (Settings.ActionString);
2167     }
2168 
2169   if (gui->printer || gui->exporter)
2170     {
2171       gui->do_export (0);
2172       exit (0);
2173     }
2174 
2175 #if HAVE_DBUS
2176   pcb_dbus_setup();
2177 #endif
2178 
2179   EnableAutosave ();
2180 
2181 #ifdef DEBUG
2182   printf ("Settings.LibraryCommandDir = \"%s\"\n",
2183           Settings.LibraryCommandDir);
2184   printf ("Settings.FontPath          = \"%s\"\n",
2185           Settings.FontPath);
2186   printf ("Settings.ElementPath       = \"%s\"\n",
2187           Settings.ElementPath);
2188   printf ("Settings.LibraryPath       = \"%s\"\n",
2189           Settings.LibraryPath);
2190   printf ("Settings.LibraryTree       = \"%s\"\n",
2191           Settings.LibraryTree);
2192   printf ("Settings.MakeProgram = \"%s\"\n",
2193           UNKNOWN (Settings.MakeProgram));
2194   printf ("Settings.GnetlistProgram = \"%s\"\n",
2195           UNKNOWN (Settings.GnetlistProgram));
2196 #endif
2197 
2198   gui->do_export (0);
2199 #if HAVE_DBUS
2200   pcb_dbus_finish();
2201 #endif
2202 
2203   pcb_main_uninit ();
2204 
2205   return (0);
2206 }
2207 
2208