1 /*!
2 * \file src/vendor.c
3 *
4 * \brief .
5 *
6 * <hr>
7 *
8 * <h1><b>Copyright.</b></h1>\n
9 *
10 * PCB, interactive printed circuit board design
11 *
12 * Copyright (C) 2004, 2007 Dan McMahill
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
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <ctype.h>
34 #include <math.h>
35 #include <stdio.h>
36
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40
41 #ifdef HAVE_STRING_H
42 #include <string.h>
43 #endif
44
45 #ifdef HAVE_SYS_TYPES_H
46 #include <sys/types.h>
47 #endif
48
49 #ifdef HAVE_REGEX_H
50 #include <regex.h>
51 #else
52 #ifdef HAVE_UNISTD_H
53 #include <unistd.h>
54 #endif
55 #endif
56
57 #include "change.h"
58 #include "data.h"
59 #include "draw.h"
60 #include "error.h"
61 #include "global.h"
62 #include "resource.h"
63 #include "set.h"
64 #include "undo.h"
65 #include "vendor.h"
66
67 #ifdef HAVE_LIBDMALLOC
68 #include <dmalloc.h>
69 #endif
70
71 static void add_to_drills (char *);
72 static void apply_vendor_map (void);
73 static void process_skips (Resource *);
74 static bool rematch (const char *, const char *);
75
76 /* list of vendor drills and a count of them */
77 static int *vendor_drills = NULL;
78 static int n_vendor_drills = 0;
79
80 static int cached_drill = -1;
81 static int cached_map = -1;
82
83 /* lists of elements to ignore */
84 static char **ignore_refdes = NULL;
85 static int n_refdes = 0;
86 static char **ignore_value = NULL;
87 static int n_value = 0;
88 static char **ignore_descr = NULL;
89 static int n_descr = 0;
90
91 /*!
92 * \brief Vendor name.
93 */
94 static char *vendor_name = NULL;
95
96 /*!
97 * \brief Resource file to PCB units scale factor.
98 */
99 static double sf;
100
101
102 /*!
103 * \brief Enable/disable mapping.
104 */
105 static bool vendorMapEnable = false;
106
107 /* type of drill mapping */
108 #define CLOSEST 1
109 #define ROUND_UP 0
110 static int rounding_method = ROUND_UP;
111
112 #define FREE(x) if((x) != NULL) { free (x) ; (x) = NULL; }
113
114 /* ************************************************************ */
115
116 static const char apply_vendor_syntax[] = N_("ApplyVendor()");
117
118 static const char apply_vendor_help[] =
119 N_("Applies the currently loaded vendor drill table to the current design.");
120
121 /* %start-doc actions ApplyVendor
122 @cindex vendor map
123 @cindex vendor drill table
124 @findex ApplyVendor()
125
126 This will modify all of your drill holes to match the list of allowed
127 sizes for your vendor.
128 %end-doc */
129
130 int
ActionApplyVendor(int argc,char ** argv,Coord x,Coord y)131 ActionApplyVendor (int argc, char **argv, Coord x, Coord y)
132 {
133 hid_action ("Busy");
134 apply_vendor_map ();
135 return 0;
136 }
137
138 /* ************************************************************ */
139
140 static const char toggle_vendor_syntax[] = N_("ToggleVendor()");
141
142 static const char toggle_vendor_help[] =
143 N_("Toggles the state of automatic drill size mapping.");
144
145 /* %start-doc actions ToggleVendor
146
147 @cindex vendor map
148 @cindex vendor drill table
149 @findex ToggleVendor()
150
151 When drill mapping is enabled, new instances of pins and vias will
152 have their drill holes mapped to one of the allowed drill sizes
153 specified in the currently loaded vendor drill table. To enable drill
154 mapping, a vendor resource file containing a drill table must be
155 loaded first.
156
157 %end-doc */
158
159 int
ActionToggleVendor(int argc,char ** argv,Coord x,Coord y)160 ActionToggleVendor (int argc, char **argv, Coord x, Coord y)
161 {
162 if (vendorMapEnable)
163 vendorMapEnable = false;
164 else
165 vendorMapEnable = true;
166 return 0;
167 }
168
169 /* ************************************************************ */
170
171 static const char enable_vendor_syntax[] = N_("EnableVendor()");
172
173 static const char enable_vendor_help[] =
174 N_("Enables automatic drill size mapping.");
175
176 /* %start-doc actions EnableVendor
177
178 @cindex vendor map
179 @cindex vendor drill table
180 @findex EnableVendor()
181
182 When drill mapping is enabled, new instances of pins and vias will
183 have their drill holes mapped to one of the allowed drill sizes
184 specified in the currently loaded vendor drill table. To enable drill
185 mapping, a vendor resource file containing a drill table must be
186 loaded first.
187
188 %end-doc */
189
190 int
ActionEnableVendor(int argc,char ** argv,Coord x,Coord y)191 ActionEnableVendor (int argc, char **argv, Coord x, Coord y)
192 {
193 vendorMapEnable = true;
194 return 0;
195 }
196
197 /* ************************************************************ */
198
199 static const char disable_vendor_syntax[] = N_("DisableVendor()");
200
201 static const char disable_vendor_help[] =
202 N_("Disables automatic drill size mapping.");
203
204 /* %start-doc actions DisableVendor
205
206 @cindex vendor map
207 @cindex vendor drill table
208 @findex DisableVendor()
209
210 When drill mapping is enabled, new instances of pins and vias will
211 have their drill holes mapped to one of the allowed drill sizes
212 specified in the currently loaded vendor drill table.
213
214 %end-doc */
215
216 int
ActionDisableVendor(int argc,char ** argv,Coord x,Coord y)217 ActionDisableVendor (int argc, char **argv, Coord x, Coord y)
218 {
219 vendorMapEnable = false;
220 return 0;
221 }
222
223 /* ************************************************************ */
224
225 static const char unload_vendor_syntax[] = N_("UnloadVendor()");
226
227 static const char unload_vendor_help[] =
228 N_("Unloads the current vendor drill mapping table.");
229
230 /* %start-doc actions UnloadVendor
231
232 @cindex vendor map
233 @cindex vendor drill table
234 @findex UnloadVendor()
235
236 %end-doc */
237
238 int
ActionUnloadVendor(int argc,char ** argv,Coord x,Coord y)239 ActionUnloadVendor (int argc, char **argv, Coord x, Coord y)
240 {
241 cached_drill = -1;
242
243 /* Unload any vendor table we may have had */
244 n_vendor_drills = 0;
245 n_refdes = 0;
246 n_value = 0;
247 n_descr = 0;
248 FREE (vendor_drills);
249 FREE (ignore_refdes);
250 FREE (ignore_value);
251 FREE (ignore_descr);
252 return 0;
253 }
254
255 /* ************************************************************ */
256
257 static const char load_vendor_syntax[] = N_("LoadVendorFrom(filename)");
258
259 static const char load_vendor_help[] =
260 N_("Loads the specified vendor resource file.");
261
262 /* %start-doc actions LoadVendorFrom
263
264 @cindex vendor map
265 @cindex vendor drill table
266 @findex LoadVendorFrom()
267
268 @table @var
269 @item filename
270 Name of the vendor resource file. If not specified, the user will
271 be prompted to enter one.
272 @end table
273
274 %end-doc */
275
276 int
ActionLoadVendorFrom(int argc,char ** argv,Coord x,Coord y)277 ActionLoadVendorFrom (int argc, char **argv, Coord x, Coord y)
278 {
279 int i;
280 char *fname = NULL;
281 static char *default_file = NULL;
282 char *sval;
283 Resource *res, *drcres, *drlres;
284 int type;
285 bool free_fname = false;
286
287 cached_drill = -1;
288
289 fname = argc ? argv[0] : 0;
290
291 if (!fname || !*fname)
292 {
293 fname = gui->fileselect (_("Load Vendor Resource File..."),
294 _("Picks a vendor resource file to load.\n"
295 "This file can contain drc settings for a\n"
296 "particular vendor as well as a list of\n"
297 "predefined drills which are allowed."),
298 default_file, ".res", "vendor",
299 HID_FILESELECT_READ);
300 if (fname == NULL)
301 AFAIL (load_vendor);
302
303 free_fname = true;
304
305 free (default_file);
306 default_file = NULL;
307
308 if (fname && *fname)
309 default_file = strdup (fname);
310 }
311
312 /* Unload any vendor table we may have had */
313 n_vendor_drills = 0;
314 n_refdes = 0;
315 n_value = 0;
316 n_descr = 0;
317 FREE (vendor_drills);
318 FREE (ignore_refdes);
319 FREE (ignore_value);
320 FREE (ignore_descr);
321
322
323 /* load the resource file */
324 res = resource_parse (fname, NULL);
325 if (res == NULL)
326 {
327 Message (_("Could not load vendor resource file \"%s\"\n"), fname);
328 return 1;
329 }
330
331 /* figure out the vendor name, if specified */
332 vendor_name = (char *)UNKNOWN (resource_value (res, "vendor"));
333
334 /* figure out the units, if specified */
335 sval = resource_value (res, "units");
336 if (sval == NULL)
337 {
338 sf = MIL_TO_COORD(1);
339 }
340 else if ((NSTRCMP (sval, "mil") == 0) || (NSTRCMP (sval, "mils") == 0))
341 {
342 sf = MIL_TO_COORD(1);
343 }
344 else if ((NSTRCMP (sval, "inch") == 0) || (NSTRCMP (sval, "inches") == 0))
345 {
346 sf = INCH_TO_COORD(1);
347 }
348 else if (NSTRCMP (sval, "mm") == 0)
349 {
350 sf = MM_TO_COORD(1);
351 }
352 else
353 {
354 Message (_("\"%s\" is not a supported units. Defaulting to inch\n"),
355 sval);
356 sf = INCH_TO_COORD(1);
357 }
358
359
360 /* default to ROUND_UP */
361 rounding_method = ROUND_UP;
362
363 /* extract the drillmap resource */
364 drlres = resource_subres (res, "drillmap");
365 if (drlres == NULL)
366 {
367 Message (_("No drillmap resource found\n"));
368 }
369 else
370 {
371 sval = resource_value (drlres, "round");
372 if (sval != NULL)
373 {
374 if (NSTRCMP (sval, "up") == 0)
375 {
376 rounding_method = ROUND_UP;
377 }
378 else if (NSTRCMP (sval, "nearest") == 0)
379 {
380 rounding_method = CLOSEST;
381 }
382 else
383 {
384 Message (_("\"%s\" is not a valid rounding type. "
385 "Defaulting to up\n"),
386 sval);
387 rounding_method = ROUND_UP;
388 }
389 }
390
391 process_skips (resource_subres (drlres, "skips"));
392
393 for (i = 0; i < drlres->c; i++)
394 {
395 type = resource_type (drlres->v[i]);
396 switch (type)
397 {
398 case 10:
399 /* just a number */
400 add_to_drills (drlres->v[i].value);
401 break;
402
403 default:
404 break;
405 }
406 }
407 }
408
409 /* Extract the DRC resource */
410 drcres = resource_subres (res, "drc");
411
412 sval = resource_value (drcres, "copper_space");
413 if (sval != NULL)
414 {
415 PCB->Bloat = floor (sf * atof (sval) + 0.5);
416 Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
417 0.01 * PCB->Bloat);
418 }
419
420 sval = resource_value (drcres, "copper_overlap");
421 if (sval != NULL)
422 {
423 PCB->Shrink = floor (sf * atof (sval) + 0.5);
424 Message (_("Set DRC minimum copper overlap to %.2f mils\n"),
425 0.01 * PCB->Shrink);
426 }
427
428 sval = resource_value (drcres, "copper_width");
429 if (sval != NULL)
430 {
431 PCB->minWid = floor (sf * atof (sval) + 0.5);
432 Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
433 0.01 * PCB->minWid);
434 }
435
436 sval = resource_value (drcres, "silk_width");
437 if (sval != NULL)
438 {
439 PCB->minSlk = floor (sf * atof (sval) + 0.5);
440 Message (_("Set DRC minimum silk width to %.2f mils\n"),
441 0.01 * PCB->minSlk);
442 }
443
444 sval = resource_value (drcres, "min_drill");
445 if (sval != NULL)
446 {
447 PCB->minDrill = floor (sf * atof (sval) + 0.5);
448 Message (_("Set DRC minimum drill diameter to %.2f mils\n"),
449 0.01 * PCB->minDrill);
450 }
451
452 sval = resource_value (drcres, "min_ring");
453 if (sval != NULL)
454 {
455 PCB->minRing = floor (sf * atof (sval) + 0.5);
456 Message (_("Set DRC minimum annular ring to %.2f mils\n"),
457 0.01 * PCB->minRing);
458 }
459
460 Message (_("Loaded %d vendor drills from %s\n"), n_vendor_drills, fname);
461 Message (_("Loaded %d RefDes skips, %d Value skips, %d Descr skips\n"),
462 n_refdes, n_value, n_descr);
463
464 vendorMapEnable = true;
465 apply_vendor_map ();
466 if (free_fname)
467 free (fname);
468 return 0;
469 }
470
471 static void
apply_vendor_map(void)472 apply_vendor_map (void)
473 {
474 int i;
475 int changed, tot;
476 bool state;
477
478 state = vendorMapEnable;
479
480 /* enable mapping */
481 vendorMapEnable = true;
482
483 /* reset our counts */
484 changed = 0;
485 tot = 0;
486
487 /* If we have loaded vendor drills, then apply them to the design */
488 if (n_vendor_drills > 0)
489 {
490
491 /* first all the vias */
492 VIA_LOOP (PCB->Data);
493 {
494 tot++;
495 if (via->DrillingHole != vendorDrillMap (via->DrillingHole))
496 {
497 /* only change unlocked vias */
498 if (!TEST_FLAG (LOCKFLAG, via))
499 {
500 if (ChangeObject2ndSize (VIA_TYPE, via, NULL, NULL,
501 vendorDrillMap (via->DrillingHole),
502 true, false))
503 changed++;
504 else
505 {
506 Message (_("Via at %.2f, %.2f not changed. "
507 "Possible reasons:\n"
508 "\t- pad size too small\n"
509 "\t- new size would be too large or too small\n"),
510 0.01 * via->X, 0.01 * via->Y);
511 }
512 }
513 else
514 {
515 Message (_("Locked via at %.2f, %.2f not changed.\n"),
516 0.01 * via->X, 0.01 * via->Y);
517 }
518 }
519 }
520 END_LOOP;
521
522 /* and now the pins */
523 ELEMENT_LOOP (PCB->Data);
524 {
525 /*
526 * first figure out if this element should be skipped for some
527 * reason
528 */
529 if (vendorIsElementMappable (element))
530 {
531 /* the element is ok to modify, so iterate over its pins */
532 PIN_LOOP (element);
533 {
534 tot++;
535 if (pin->DrillingHole != vendorDrillMap (pin->DrillingHole))
536 {
537 if (!TEST_FLAG (LOCKFLAG, pin))
538 {
539 if (ChangeObject2ndSize (PIN_TYPE, element, pin, NULL,
540 vendorDrillMap (pin->
541 DrillingHole),
542 true, false))
543 changed++;
544 else
545 {
546 Message (_("Pin %s (%s) at %.2f, %.2f "
547 "(element %s, %s, %s) not changed.\n"
548 "\tPossible reasons:\n"
549 "\t- pad size too small\n"
550 "\t- new size would be too large or too small\n"),
551 UNKNOWN (pin->Number), UNKNOWN (pin->Name),
552 0.01 * pin->X, 0.01 * pin->Y,
553 UNKNOWN (NAMEONPCB_NAME (element)),
554 UNKNOWN (VALUE_NAME (element)),
555 UNKNOWN (DESCRIPTION_NAME (element)));
556 }
557 }
558 else
559 {
560 Message (_("Locked pin at %-6.2f, %-6.2f not changed.\n"),
561 0.01 * pin->X, 0.01 * pin->Y);
562 }
563 }
564 }
565 END_LOOP;
566 }
567 }
568 END_LOOP;
569
570 Message (_("Updated %d drill sizes out of %d total\n"), changed, tot);
571
572 /* Update the current Via */
573 if (Settings.ViaDrillingHole !=
574 vendorDrillMap (Settings.ViaDrillingHole))
575 {
576 changed++;
577 Settings.ViaDrillingHole =
578 vendorDrillMap (Settings.ViaDrillingHole);
579 Message (_("Adjusted active via hole size to be %6.2f mils\n"),
580 0.01 * Settings.ViaDrillingHole);
581 }
582
583 /* and update the vias for the various routing styles */
584 for (i = 0; i < NUM_STYLES; i++)
585 {
586 if (PCB->RouteStyle[i].Hole !=
587 vendorDrillMap (PCB->RouteStyle[i].Hole))
588 {
589 changed++;
590 PCB->RouteStyle[i].Hole =
591 vendorDrillMap (PCB->RouteStyle[i].Hole);
592 Message (_("Adjusted %s routing style via hole size to be "
593 "%6.2f mils\n"),
594 PCB->RouteStyle[i].Name,
595 0.01 * PCB->RouteStyle[i].Hole);
596 if (PCB->RouteStyle[i].Diameter < PCB->RouteStyle[i].Hole)
597 {
598 PCB->RouteStyle[i].Diameter = PCB->RouteStyle[i].Hole;
599 Message (_("Increased %s routing style via diameter to "
600 "%6.2f mils\n"),
601 PCB->RouteStyle[i].Name,
602 0.01 * PCB->RouteStyle[i].Diameter);
603 }
604 }
605 }
606
607 /*
608 * if we've changed anything, indicate that we need to save the
609 * file, redraw things, and make sure we can undo.
610 */
611 if (changed)
612 {
613 SetChangedFlag (true);
614 Redraw ();
615 IncrementUndoSerialNumber ();
616 }
617 }
618
619 /* restore mapping on/off */
620 vendorMapEnable = state;
621 }
622
623 /*!
624 * \brief For a given drill size, find the closest vendor drill size.
625 */
626 int
vendorDrillMap(int in)627 vendorDrillMap (int in)
628 {
629 int i, min, max;
630
631 if (in == cached_drill)
632 return cached_map;
633 cached_drill = in;
634
635 /* skip the mapping if we don't have a vendor drill table */
636 if ((n_vendor_drills == 0) || (vendor_drills == NULL)
637 || (vendorMapEnable == false))
638 {
639 cached_map = in;
640 return in;
641 }
642
643 /* are we smaller than the smallest drill? */
644 if (in <= vendor_drills[0])
645 {
646 cached_map = vendor_drills[0];
647 return vendor_drills[0];
648 }
649
650 /* are we larger than the largest drill? */
651 if (in > vendor_drills[n_vendor_drills - 1])
652 {
653 Message (_("Vendor drill list does not contain a drill >= %6.2f mil\n"
654 "Using %6.2f mil instead.\n"),
655 0.01 * in, 0.01 * vendor_drills[n_vendor_drills - 1]);
656 cached_map = vendor_drills[n_vendor_drills - 1];
657 return vendor_drills[n_vendor_drills - 1];
658 }
659
660 /* figure out which 2 drills are closest in size */
661 min = 0;
662 max = n_vendor_drills - 1;
663 while (max - min > 1)
664 {
665 i = (max+min) / 2;
666 if (in > vendor_drills[i])
667 min = i;
668 else
669 max = i;
670 }
671 i = max;
672
673 /* now round per the rounding mode */
674 if (rounding_method == CLOSEST)
675 {
676 /* find the closest drill size */
677 if ((in - vendor_drills[i - 1]) > (vendor_drills[i] - in))
678 {
679 cached_map = vendor_drills[i];
680 return vendor_drills[i];
681 }
682 else
683 {
684 cached_map = vendor_drills[i - 1];
685 return vendor_drills[i - 1];
686 }
687 }
688 else
689 {
690 /* always round up */
691 cached_map = vendor_drills[i];
692 return vendor_drills[i];
693 }
694
695 }
696
697 /*!
698 * \brief Add a drill size to the vendor drill list.
699 */
700 static void
add_to_drills(char * sval)701 add_to_drills (char *sval)
702 {
703 double tmpd;
704 int val;
705 int k, j;
706
707 /* increment the count and make sure we have memory */
708 n_vendor_drills++;
709 if ((vendor_drills = (int *)realloc (vendor_drills,
710 n_vendor_drills * sizeof (int))) == NULL)
711 {
712 fprintf (stderr, _("realloc() failed to allocate %ld bytes\n"),
713 (unsigned long) n_vendor_drills * sizeof (int));
714 return;
715 }
716
717 /* string to a value with the units scale factor in place */
718 tmpd = atof (sval);
719 val = floor (sf * tmpd + 0.5);
720
721 /*
722 * We keep the array of vendor drills sorted to make it easier to
723 * do the rounding later. The algorithm used here is not so efficient,
724 * but we're not dealing with much in the way of data.
725 */
726
727 /* figure out where to insert the value to keep the array sorted. */
728 k = 0;
729 while ((k < n_vendor_drills - 1) && (vendor_drills[k] < val))
730 k++;
731
732 if (k == n_vendor_drills - 1)
733 {
734 vendor_drills[n_vendor_drills - 1] = val;
735 }
736 else
737 {
738 /* move up the existing drills to make room */
739 for (j = n_vendor_drills - 1; j > k; j--)
740 {
741 vendor_drills[j] = vendor_drills[j - 1];
742 }
743
744 vendor_drills[k] = val;
745 }
746 }
747
748 /*!
749 * \brief Deal with the "skip" subresource.
750 */
751 static void
process_skips(Resource * res)752 process_skips (Resource * res)
753 {
754 int type;
755 int i, k;
756 char *sval;
757 int *cnt;
758 char ***lst = NULL;
759
760 if (res == NULL)
761 return;
762
763 for (i = 0; i < res->c; i++)
764 {
765 type = resource_type (res->v[i]);
766 switch (type)
767 {
768 case 1:
769 /*
770 * an unnamed sub resource. This is something like
771 * {refdes "J3"}
772 */
773 sval = res->v[i].subres->v[0].value;
774 if (sval == NULL)
775 {
776 Message (_("Error: null skip value\n"));
777 }
778 else
779 {
780 if (NSTRCMP (sval, "refdes") == 0)
781 {
782 cnt = &n_refdes;
783 lst = &ignore_refdes;
784 }
785 else if (NSTRCMP (sval, "value") == 0)
786 {
787 cnt = &n_value;
788 lst = &ignore_value;
789 }
790 else if (NSTRCMP (sval, "descr") == 0)
791 {
792 cnt = &n_descr;
793 lst = &ignore_descr;
794 }
795 else
796 {
797 cnt = NULL;
798 }
799
800 /* add the entry to the appropriate list */
801 if (cnt != NULL)
802 {
803 for (k = 1; k < res->v[i].subres->c; k++)
804 {
805 sval = res->v[i].subres->v[k].value;
806 (*cnt)++;
807 if ((*lst =
808 (char **) realloc (*lst,
809 (*cnt) * sizeof (char *))) ==
810 NULL)
811 {
812 fprintf (stderr, _("realloc() failed\n"));
813 exit (-1);
814 }
815 (*lst)[*cnt - 1] = strdup (sval);
816 }
817 }
818 }
819 break;
820
821 default:
822 Message (_("Ignored resource type = %d in skips= section\n"), type);
823 }
824 }
825
826 }
827
828 bool
vendorIsElementMappable(ElementType * element)829 vendorIsElementMappable (ElementType *element)
830 {
831 int i;
832 int noskip;
833
834 if (vendorMapEnable == false)
835 return false;
836
837 noskip = 1;
838 for (i = 0; i < n_refdes; i++)
839 {
840 if ((NSTRCMP (UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]) ==
841 0)
842 || rematch (ignore_refdes[i], UNKNOWN (NAMEONPCB_NAME (element))))
843 {
844 Message (_("Vendor mapping skipped because "
845 "refdes = %s matches %s\n"),
846 UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]);
847 noskip = 0;
848 }
849 }
850 if (noskip)
851 for (i = 0; i < n_value; i++)
852 {
853 if ((NSTRCMP (UNKNOWN (VALUE_NAME (element)), ignore_value[i]) == 0)
854 || rematch (ignore_value[i], UNKNOWN (VALUE_NAME (element))))
855 {
856 Message (_("Vendor mapping skipped because "
857 "value = %s matches %s\n"),
858 UNKNOWN (VALUE_NAME (element)), ignore_value[i]);
859 noskip = 0;
860 }
861 }
862
863 if (noskip)
864 for (i = 0; i < n_descr; i++)
865 {
866 if ((NSTRCMP (UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i])
867 == 0)
868 || rematch (ignore_descr[i],
869 UNKNOWN (DESCRIPTION_NAME (element))))
870 {
871 Message (_("Vendor mapping skipped because "
872 "descr = %s matches %s\n"),
873 UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i]);
874 noskip = 0;
875 }
876 }
877
878 if (noskip && TEST_FLAG (LOCKFLAG, element))
879 {
880 Message (_("Vendor mapping skipped because element %s is locked\n"),
881 UNKNOWN (NAMEONPCB_NAME (element)));
882 noskip = 0;
883 }
884
885 if (noskip)
886 return true;
887 else
888 return false;
889 }
890
891 static bool
rematch(const char * re,const char * s)892 rematch (const char *re, const char *s)
893 {
894 /*
895 * If this system has regular expression capability, then
896 * add support for regular expressions in the skip lists.
897 */
898
899 #if defined(HAVE_REGCOMP)
900
901 int result;
902 regmatch_t match;
903 regex_t compiled;
904
905 /* compile the regular expression */
906 result = regcomp (&compiled, re, REG_EXTENDED | REG_ICASE | REG_NOSUB);
907 if (result)
908 {
909 char errorstring[128];
910
911 regerror (result, &compiled, errorstring, sizeof (errorstring));
912 Message (_("regexp error: %s\n"), errorstring);
913 regfree (&compiled);
914 return (false);
915 }
916
917 result = regexec (&compiled, s, 1, &match, 0);
918 regfree (&compiled);
919
920 if (result == 0)
921 return (true);
922 else
923 return (false);
924
925 #elif defined(HAVE_RE_COMP)
926 int m;
927 char *rslt;
928
929 /* compile the regular expression */
930 if ((rslt = re_comp (re)) != NULL)
931 {
932 Message (_("re_comp error: %s\n"), rslt);
933 return (false);
934 }
935
936 m = re_exec (s);
937
938 switch m
939 {
940 case 1:
941 return (true);
942 break;
943
944 case 0:
945 return (false);
946 break;
947
948 default:
949 Message (_("re_exec error\n"));
950 break;
951 }
952
953 #else
954 return (false);
955 #endif
956
957 }
958
959 HID_Action vendor_action_list[] = {
960 {"ApplyVendor", 0, ActionApplyVendor,
961 apply_vendor_help, apply_vendor_syntax}
962 ,
963 {"ToggleVendor", 0, ActionToggleVendor,
964 toggle_vendor_help, toggle_vendor_syntax}
965 ,
966 {"EnableVendor", 0, ActionEnableVendor,
967 enable_vendor_help, enable_vendor_syntax}
968 ,
969 {"DisableVendor", 0, ActionDisableVendor,
970 disable_vendor_help, disable_vendor_syntax}
971 ,
972 {"UnloadVendor", 0, ActionUnloadVendor,
973 unload_vendor_help, unload_vendor_syntax}
974 ,
975 {"LoadVendorFrom", 0, ActionLoadVendorFrom,
976 load_vendor_help, load_vendor_syntax}
977 };
978
REGISTER_ACTIONS(vendor_action_list)979 REGISTER_ACTIONS (vendor_action_list)
980
981 static int vendor_get_enabled (void *data)
982 {
983 return vendorMapEnable;
984 }
985
986 HID_Flag vendor_flag_list[] = {
987 {"VendorMapOn", vendor_get_enabled, NULL}
988 };
989
990 REGISTER_FLAGS (vendor_flag_list)
991