16 #include <sys/types.h>
20 #if defined(WIN32) && defined(HAVE_WINDOWS_H)
26 #include "../hidint.h"
28 /* for dlopen() and friends on windows */
35 #ifdef HAVE_LIBDMALLOC
41 #define HID_DEF(x) extern void hid_ ## x ## _init(void);
42 #include "hid/common/hidlist.h"
50 HID
*gui
= &hid_nogui
;
56 hid_load_dir (char *dirname
)
61 dir
= opendir (dirname
);
67 while ((de
= readdir (dir
)) != NULL
)
72 char *basename
, *path
, *symname
;
75 basename
= strdup (de
->d_name
);
76 if (strlen (basename
) > 3
77 && strcasecmp (basename
+strlen(basename
)-3, ".so") == 0)
78 basename
[strlen(basename
)-3] = 0;
79 else if (strlen (basename
) > 4
80 && strcasecmp (basename
+strlen(basename
)-4, ".dll") == 0)
81 basename
[strlen(basename
)-4] = 0;
82 path
= Concat (dirname
, PCB_DIR_SEPARATOR_S
, de
->d_name
, NULL
);
84 if (stat (path
, &st
) == 0
86 /* mingw and win32 do not support S_IXGRP or S_IXOTH */
88 (st
.st_mode
& S_IXGRP
) ||
91 (st
.st_mode
& S_IXOTH
) ||
93 (st
.st_mode
& S_IXUSR
) )
94 && S_ISREG (st
.st_mode
))
96 if ((so
= dlopen (path
, RTLD_NOW
| RTLD_GLOBAL
)) == NULL
)
98 fprintf(stderr
, "dl_error: %s\n", dlerror ());
102 symname
= Concat ("hid_", basename
, "_init", NULL
);
103 if ((sym
= dlsym (so
, symname
)) != NULL
)
105 symv
= (void (*)()) sym
;
108 else if ((sym
= dlsym (so
, "pcb_plugin_init")) != NULL
)
110 symv
= (void (*)()) sym
;
127 #define HID_DEF(x) hid_ ## x ## _init();
128 #include "hid/common/hidlist.h"
131 hid_load_dir (Concat (exec_prefix
, PCB_DIR_SEPARATOR_S
, "lib",
132 PCB_DIR_SEPARATOR_S
, "pcb",
133 PCB_DIR_SEPARATOR_S
, "plugins",
134 PCB_DIR_SEPARATOR_S
, HOST
, NULL
));
135 hid_load_dir (Concat (exec_prefix
, PCB_DIR_SEPARATOR_S
, "lib",
136 PCB_DIR_SEPARATOR_S
, "pcb",
137 PCB_DIR_SEPARATOR_S
, "plugins", NULL
));
139 /* homedir is set by the core immediately on startup */
142 hid_load_dir (Concat (homedir
, PCB_DIR_SEPARATOR_S
, ".pcb",
143 PCB_DIR_SEPARATOR_S
, "plugins",
144 PCB_DIR_SEPARATOR_S
, HOST
, NULL
));
145 hid_load_dir (Concat (homedir
, PCB_DIR_SEPARATOR_S
, ".pcb",
146 PCB_DIR_SEPARATOR_S
, "plugins", NULL
));
148 hid_load_dir (Concat ("plugins", PCB_DIR_SEPARATOR_S
, HOST
, NULL
));
149 hid_load_dir (Concat ("plugins", NULL
));
153 hid_register_hid (HID
* hid
)
156 int sz
= (hid_num_hids
+ 2) * sizeof (HID
*);
158 if (hid
->struct_size
!= sizeof (HID
))
160 fprintf (stderr
, "Warning: hid \"%s\" has an incompatible ABI.\n",
165 for (i
=0; i
<hid_num_hids
; i
++)
166 if (hid
== hid_list
[i
])
171 hid_list
= (HID
**) realloc (hid_list
, sz
);
173 hid_list
= (HID
**) malloc (sz
);
175 hid_list
[hid_num_hids
- 1] = hid
;
176 hid_list
[hid_num_hids
] = 0;
179 static void (*gui_start
) (int *, char ***) = 0;
180 static HID
*default_gui
= 0;
183 hid_register_gui (HID
* Pgui
, void (*func
) (int *, char ***))
198 for (i
= 0; i
< hid_num_hids
; i
++)
199 if (!hid_list
[i
]->printer
&& !hid_list
[i
]->exporter
)
202 fprintf (stderr
, "Error: No GUI available.\n");
211 for (i
= 0; i
< hid_num_hids
; i
++)
212 if (hid_list
[i
]->printer
)
219 hid_find_exporter (const char *which
)
223 for (i
= 0; i
< hid_num_hids
; i
++)
224 if (hid_list
[i
]->exporter
&& strcmp (which
, hid_list
[i
]->name
) == 0)
227 fprintf (stderr
, "Invalid exporter %s, available ones:", which
);
228 for (i
= 0; i
< hid_num_hids
; i
++)
229 if (hid_list
[i
]->exporter
)
230 fprintf (stderr
, " %s", hid_list
[i
]->name
);
231 fprintf (stderr
, "\n");
242 HID_AttrNode
*hid_attr_nodes
= 0;
245 hid_register_attributes (HID_Attribute
* a
, int n
)
249 /* printf("%d attributes registered\n", n); */
250 ha
= (HID_AttrNode
*) malloc (sizeof (HID_AttrNode
));
251 ha
->next
= hid_attr_nodes
;
258 hid_parse_command_line (int *argc
, char ***argv
)
266 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
267 for (i
= 0; i
< ha
->n
; i
++)
269 HID_Attribute
*a
= ha
->attributes
+ i
;
276 *(int *) a
->value
= a
->default_val
.int_value
;
280 *(char *) a
->value
= a
->default_val
.int_value
;
284 *(double *) a
->value
= a
->default_val
.real_value
;
288 *(char **) a
->value
= a
->default_val
.str_value
;
292 *(int *) a
->value
= a
->default_val
.int_value
;
299 while (*argc
&& (*argv
)[0][0] == '-' && (*argv
)[0][1] == '-')
307 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
308 for (i
= 0; i
< ha
->n
; i
++)
309 if (strcmp ((*argv
)[0] + arg_ofs
, ha
->attributes
[i
].name
) == 0)
311 HID_Attribute
*a
= ha
->attributes
+ i
;
313 switch (ha
->attributes
[i
].type
)
319 *(int *) a
->value
= strtol ((*argv
)[1], 0, 0);
321 a
->default_val
.int_value
= strtol ((*argv
)[1], 0, 0);
327 *(double *) a
->value
= strtod ((*argv
)[1], 0);
329 a
->default_val
.real_value
= strtod ((*argv
)[1], 0);
335 *(char **) a
->value
= (*argv
)[1];
337 a
->default_val
.str_value
= (*argv
)[1];
343 *(char *) a
->value
= bool_val
;
345 a
->default_val
.int_value
= bool_val
;
349 a
->default_val
.real_value
= strtod ((*argv
)[1], &ep
);
355 for (e
= 0; a
->enumerations
[e
]; e
++)
356 if (strcmp (a
->enumerations
[e
], (*argv
)[1]) == 0)
359 a
->default_val
.int_value
= e
;
360 a
->default_val
.str_value
= ep
;
366 "ERROR: \"%s\" is an unknown value for the --%s option\n",
367 (*argv
)[1], a
->name
);
375 a
->default_val
.str_value
= (*argv
)[1];
385 if (bool_val
== 1 && strncmp ((*argv
)[0], "--no-", 5) == 0)
391 fprintf (stderr
, "unrecognized option: %s\n", (*argv
)[0]);
401 attr_hash (HID_Attribute
*a
)
403 unsigned char *cp
= (unsigned char *)a
;
405 for (i
=0; i
<(int)((char *)&(a
->hash
) - (char *)a
); i
++)
406 rv
= (rv
* 13) ^ (rv
>> 16) ^ cp
[i
];
411 hid_save_settings (int locally
)
421 fname
= Concat ("pcb.settings", NULL
);
427 fname
= Concat (homedir
, PCB_DIR_SEPARATOR_S
, ".pcb", NULL
);
429 if (stat (fname
, &st
))
433 if (mkdir (fname
, 0777))
441 fname
= Concat (homedir
, PCB_DIR_SEPARATOR_S
, ".pcb",
442 PCB_DIR_SEPARATOR_S
, "settings", NULL
);
445 f
= fopen (fname
, "w");
448 Message ("Can't open %s", fname
);
453 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
455 for (i
= 0; i
< ha
->n
; i
++)
458 HID_Attribute
*a
= ha
->attributes
+ i
;
460 if (a
->hash
== attr_hash (a
))
467 fprintf (f
, "%s = %d\n",
469 a
->value
? *(int *)a
->value
: a
->default_val
.int_value
);
472 fprintf (f
, "%s = %d\n",
474 a
->value
? *(char *)a
->value
: a
->default_val
.int_value
);
477 fprintf (f
, "%s = %f\n",
479 a
->value
? *(double *)a
->value
: a
->default_val
.real_value
);
483 str
= a
->value
? *(char **)a
->value
: a
->default_val
.str_value
;
484 fprintf (f
, "%s = %s\n",
489 fprintf (f
, "%s = %s\n",
491 a
->enumerations
[a
->value
? *(int *)a
->value
: a
->default_val
.int_value
]);
505 hid_set_attribute (char *name
, char *value
)
510 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
511 for (i
= 0; i
< ha
->n
; i
++)
512 if (strcmp (name
, ha
->attributes
[i
].name
) == 0)
514 HID_Attribute
*a
= ha
->attributes
+ i
;
515 switch (ha
->attributes
[i
].type
)
520 a
->default_val
.int_value
= strtol (value
, 0, 0);
523 a
->default_val
.real_value
= strtod (value
, 0);
526 a
->default_val
.str_value
= strdup (value
);
529 a
->default_val
.int_value
= 1;
533 a
->default_val
.real_value
= strtod (value
, &value
);
537 for (e
= 0; a
->enumerations
[e
]; e
++)
538 if (strcmp (a
->enumerations
[e
], value
) == 0)
541 a
->default_val
.int_value
= e
;
542 a
->default_val
.str_value
= value
;
548 "ERROR: \"%s\" is an unknown value for the %s option\n",
554 a
->default_val
.str_value
= value
;
561 hid_load_settings_1 (char *fname
)
563 char line
[1024], *namep
, *valp
, *cp
;
566 f
= fopen (fname
, "r");
574 while (fgets (line
, sizeof(line
), f
) != NULL
)
576 for (namep
=line
; *namep
&& isspace ((int) *namep
); namep
++)
580 for (valp
=namep
; *valp
&& !isspace((int) *valp
); valp
++)
585 while (*valp
&& (isspace ((int) *valp
) || *valp
== '='))
589 cp
= valp
+ strlen(valp
) - 1;
590 while (cp
>= valp
&& isspace ((int) *cp
))
592 hid_set_attribute (namep
, valp
);
604 for (ha
= hid_attr_nodes
; ha
; ha
= ha
->next
)
605 for (i
= 0; i
< ha
->n
; i
++)
606 ha
->attributes
[i
].hash
= attr_hash (ha
->attributes
+i
);
608 hid_load_settings_1 (Concat (pcblibdir
, PCB_DIR_SEPARATOR_S
, "settings", NULL
));
610 hid_load_settings_1 (Concat (homedir
, PCB_DIR_SEPARATOR_S
, ".pcb",
611 PCB_DIR_SEPARATOR_S
, "settings", NULL
));
612 hid_load_settings_1 (Concat ("pcb.settings", NULL
));
617 typedef struct ecache
624 typedef struct ccache
626 ecache
*colors
[HASH_SIZE
];
631 copy_color (int set
, hidval
* cval
, hidval
* aval
)
634 memcpy (cval
, aval
, sizeof (hidval
));
636 memcpy (aval
, cval
, sizeof (hidval
));
640 hid_cache_color (int set
, const char *name
, hidval
* val
, void **vcache
)
647 cache
= (ccache
*) * vcache
;
649 cache
= *vcache
= (void *) calloc (sizeof (ccache
), 1);
651 if (cache
->lru
&& strcmp (cache
->lru
->name
, name
) == 0)
653 copy_color (set
, &(cache
->lru
->val
), val
);
657 /* djb2: this algorithm (k=33) was first reported by dan bernstein many
658 * years ago in comp.lang.c. another version of this algorithm (now favored
659 * by bernstein) uses xor: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic
660 * of number 33 (why it works better than many other constants, prime or
661 * not) has never been adequately explained.
664 for (cp
= name
, hash
= 0; *cp
; cp
++)
665 hash
= ((hash
<< 5) + hash
) + (*cp
& 0xff); /* hash * 33 + c */
668 for (e
= cache
->colors
[hash
]; e
; e
= e
->next
)
669 if (strcmp (e
->name
, name
) == 0)
671 copy_color (set
, &(e
->val
), val
);
678 e
= (ecache
*) malloc (sizeof (ecache
));
679 e
->next
= cache
->colors
[hash
];
680 cache
->colors
[hash
] = e
;
681 e
->name
= strdup (name
);
682 memcpy (&(e
->val
), val
, sizeof (hidval
));
688 /* otherwise homeless function, refactored out of the five export HIDs */
690 derive_default_filename(const char *pcbfile
, HID_Attribute
*filename_attrib
, const char *suffix
, char **memory
)
696 pf
= strdup ("unknown.pcb");
698 pf
= strdup (pcbfile
);
700 if (!pf
|| (memory
&& filename_attrib
->default_val
.str_value
!= *memory
)) return;
702 buf
= malloc (strlen (pf
) + strlen(suffix
) + 1);
703 if (memory
) *memory
= buf
;
708 if (bl
> 4 && strcmp (buf
+ bl
- 4, ".pcb") == 0)
711 if (filename_attrib
->default_val
.str_value
)
712 free(filename_attrib
->default_val
.str_value
);
713 filename_attrib
->default_val
.str_value
= buf
;