pcb 4.1.1
An interactive printed circuit board layout editor.

vendor.c

Go to the documentation of this file.
00001 
00029 #ifdef HAVE_CONFIG_H
00030 #include "config.h"
00031 #endif
00032 
00033 #include <ctype.h>
00034 #include <math.h>
00035 #include <stdio.h>
00036 
00037 #ifdef HAVE_STDLIB_H
00038 #include <stdlib.h>
00039 #endif
00040 
00041 #ifdef HAVE_STRING_H
00042 #include <string.h>
00043 #endif
00044 
00045 #ifdef HAVE_SYS_TYPES_H
00046 #include <sys/types.h>
00047 #endif
00048 
00049 #ifdef HAVE_REGEX_H
00050 #include <regex.h>
00051 #else
00052 #ifdef HAVE_UNISTD_H
00053 #include <unistd.h>
00054 #endif
00055 #endif
00056 
00057 #include "change.h"
00058 #include "data.h"
00059 #include "draw.h"
00060 #include "error.h"
00061 #include "global.h"
00062 #include "resource.h"
00063 #include "set.h"
00064 #include "undo.h"
00065 #include "vendor.h"
00066 
00067 #ifdef HAVE_LIBDMALLOC
00068 #include <dmalloc.h>
00069 #endif
00070 
00071 static void add_to_drills (char *);
00072 static void apply_vendor_map (void);
00073 static void process_skips (Resource *);
00074 static bool rematch (const char *, const char *);
00075 
00076 /* list of vendor drills and a count of them */
00077 static int *vendor_drills = NULL;
00078 static int n_vendor_drills = 0;
00079 
00080 static int cached_drill = -1;
00081 static int cached_map = -1;
00082 
00083 /* lists of elements to ignore */
00084 static char **ignore_refdes = NULL;
00085 static int n_refdes = 0;
00086 static char **ignore_value = NULL;
00087 static int n_value = 0;
00088 static char **ignore_descr = NULL;
00089 static int n_descr = 0;
00090 
00094 static char *vendor_name = NULL;
00095 
00099 static double sf;
00100 
00101 
00105 static bool vendorMapEnable = false;
00106 
00107 /* type of drill mapping */
00108 #define CLOSEST 1
00109 #define ROUND_UP 0
00110 static int rounding_method = ROUND_UP;
00111 
00112 #define FREE(x) if((x) != NULL) { free (x) ; (x) = NULL; }
00113 
00114 /* ************************************************************ */
00115 
00116 static const char apply_vendor_syntax[] = N_("ApplyVendor()");
00117 
00118 static const char apply_vendor_help[] =
00119   N_("Applies the currently loaded vendor drill table to the current design.");
00120 
00121 /* %start-doc actions ApplyVendor
00122 @cindex vendor map 
00123 @cindex vendor drill table
00124 @findex ApplyVendor()
00125 
00126 This will modify all of your drill holes to match the list of allowed
00127 sizes for your vendor.
00128 %end-doc */
00129 
00130 int
00131 ActionApplyVendor (int argc, char **argv, Coord x, Coord y)
00132 {
00133   hid_action ("Busy");
00134   apply_vendor_map ();
00135   return 0;
00136 }
00137 
00138 /* ************************************************************ */
00139 
00140 static const char toggle_vendor_syntax[] = N_("ToggleVendor()");
00141 
00142 static const char toggle_vendor_help[] =
00143   N_("Toggles the state of automatic drill size mapping.");
00144 
00145 /* %start-doc actions ToggleVendor
00146 
00147 @cindex vendor map 
00148 @cindex vendor drill table
00149 @findex ToggleVendor()
00150 
00151 When drill mapping is enabled, new instances of pins and vias will
00152 have their drill holes mapped to one of the allowed drill sizes
00153 specified in the currently loaded vendor drill table.  To enable drill
00154 mapping, a vendor resource file containing a drill table must be
00155 loaded first.
00156 
00157 %end-doc */
00158 
00159 int
00160 ActionToggleVendor (int argc, char **argv, Coord x, Coord y)
00161 {
00162   if (vendorMapEnable)
00163     vendorMapEnable = false;
00164   else
00165     vendorMapEnable = true;
00166   return 0;
00167 }
00168 
00169 /* ************************************************************ */
00170 
00171 static const char enable_vendor_syntax[] = N_("EnableVendor()");
00172 
00173 static const char enable_vendor_help[] =
00174   N_("Enables automatic drill size mapping.");
00175 
00176 /* %start-doc actions EnableVendor
00177 
00178 @cindex vendor map 
00179 @cindex vendor drill table
00180 @findex EnableVendor()
00181 
00182 When drill mapping is enabled, new instances of pins and vias will
00183 have their drill holes mapped to one of the allowed drill sizes
00184 specified in the currently loaded vendor drill table.  To enable drill
00185 mapping, a vendor resource file containing a drill table must be
00186 loaded first.
00187 
00188 %end-doc */
00189 
00190 int
00191 ActionEnableVendor (int argc, char **argv, Coord x, Coord y)
00192 {
00193   vendorMapEnable = true;
00194   return 0;
00195 }
00196 
00197 /* ************************************************************ */
00198 
00199 static const char disable_vendor_syntax[] = N_("DisableVendor()");
00200 
00201 static const char disable_vendor_help[] =
00202   N_("Disables automatic drill size mapping.");
00203 
00204 /* %start-doc actions DisableVendor
00205 
00206 @cindex vendor map 
00207 @cindex vendor drill table
00208 @findex DisableVendor()
00209 
00210 When drill mapping is enabled, new instances of pins and vias will
00211 have their drill holes mapped to one of the allowed drill sizes
00212 specified in the currently loaded vendor drill table.
00213 
00214 %end-doc */
00215 
00216 int
00217 ActionDisableVendor (int argc, char **argv, Coord x, Coord y)
00218 {
00219   vendorMapEnable = false;
00220   return 0;
00221 }
00222 
00223 /* ************************************************************ */
00224 
00225 static const char unload_vendor_syntax[] = N_("UnloadVendor()");
00226 
00227 static const char unload_vendor_help[] =
00228   N_("Unloads the current vendor drill mapping table.");
00229 
00230 /* %start-doc actions UnloadVendor
00231 
00232 @cindex vendor map 
00233 @cindex vendor drill table
00234 @findex UnloadVendor()
00235 
00236 %end-doc */
00237 
00238 int
00239 ActionUnloadVendor (int argc, char **argv, Coord x, Coord y)
00240 {
00241   cached_drill = -1;
00242 
00243   /* Unload any vendor table we may have had */
00244   n_vendor_drills = 0;
00245   n_refdes = 0;
00246   n_value = 0;
00247   n_descr = 0;
00248   FREE (vendor_drills);
00249   FREE (ignore_refdes);
00250   FREE (ignore_value);
00251   FREE (ignore_descr);
00252   return 0;
00253 }
00254 
00255 /* ************************************************************ */
00256 
00257 static const char load_vendor_syntax[] = N_("LoadVendorFrom(filename)");
00258 
00259 static const char load_vendor_help[] =
00260   N_("Loads the specified vendor resource file.");
00261 
00262 /* %start-doc actions LoadVendorFrom
00263 
00264 @cindex vendor map 
00265 @cindex vendor drill table
00266 @findex LoadVendorFrom()
00267 
00268 @table @var
00269 @item filename
00270 Name of the vendor resource file.  If not specified, the user will
00271 be prompted to enter one.
00272 @end table
00273 
00274 %end-doc */
00275 
00276 int
00277 ActionLoadVendorFrom (int argc, char **argv, Coord x, Coord y)
00278 {
00279   int i;
00280   char *fname = NULL;
00281   static char *default_file = NULL;
00282   char *sval;
00283   Resource *res, *drcres, *drlres;
00284   int type;
00285   bool free_fname = false;
00286 
00287   cached_drill = -1;
00288 
00289   fname = argc ? argv[0] : 0;
00290 
00291   if (!fname || !*fname)
00292     {
00293       fname = gui->fileselect (_("Load Vendor Resource File..."),
00294                                _("Picks a vendor resource file to load.\n"
00295                                  "This file can contain drc settings for a\n"
00296                                  "particular vendor as well as a list of\n"
00297                                  "predefined drills which are allowed."),
00298                                default_file, ".res", "vendor",
00299                                HID_FILESELECT_READ);
00300       if (fname == NULL)
00301         AFAIL (load_vendor);
00302 
00303       free_fname = true;
00304 
00305       free (default_file);
00306       default_file = NULL;
00307 
00308       if (fname && *fname)
00309         default_file = strdup (fname);
00310     }
00311 
00312   /* Unload any vendor table we may have had */
00313   n_vendor_drills = 0;
00314   n_refdes = 0;
00315   n_value = 0;
00316   n_descr = 0;
00317   FREE (vendor_drills);
00318   FREE (ignore_refdes);
00319   FREE (ignore_value);
00320   FREE (ignore_descr);
00321 
00322 
00323   /* load the resource file */
00324   res = resource_parse (fname, NULL);
00325   if (res == NULL)
00326     {
00327       Message (_("Could not load vendor resource file \"%s\"\n"), fname);
00328       return 1;
00329     }
00330 
00331   /* figure out the vendor name, if specified */
00332   vendor_name = (char *)UNKNOWN (resource_value (res, "vendor"));
00333 
00334   /* figure out the units, if specified */
00335   sval = resource_value (res, "units");
00336   if (sval == NULL)
00337     {
00338       sf = MIL_TO_COORD(1);
00339     }
00340   else if ((NSTRCMP (sval, "mil") == 0) || (NSTRCMP (sval, "mils") == 0))
00341     {
00342       sf = MIL_TO_COORD(1);
00343     }
00344   else if ((NSTRCMP (sval, "inch") == 0) || (NSTRCMP (sval, "inches") == 0))
00345     {
00346       sf = INCH_TO_COORD(1);
00347     }
00348   else if (NSTRCMP (sval, "mm") == 0)
00349     {
00350       sf = MM_TO_COORD(1);
00351     }
00352   else
00353     {
00354       Message (_("\"%s\" is not a supported units.  Defaulting to inch\n"),
00355                sval);
00356       sf = INCH_TO_COORD(1);
00357     }
00358 
00359 
00360   /* default to ROUND_UP */
00361   rounding_method = ROUND_UP;
00362 
00363   /* extract the drillmap resource */
00364   drlres = resource_subres (res, "drillmap");
00365   if (drlres == NULL)
00366     {
00367       Message (_("No drillmap resource found\n"));
00368     }
00369   else
00370     {
00371       sval = resource_value (drlres, "round");
00372       if (sval != NULL)
00373         {
00374           if (NSTRCMP (sval, "up") == 0)
00375             {
00376               rounding_method = ROUND_UP;
00377             }
00378           else if (NSTRCMP (sval, "nearest") == 0)
00379             {
00380               rounding_method = CLOSEST;
00381             }
00382           else
00383             {
00384               Message (_("\"%s\" is not a valid rounding type. "
00385                     "Defaulting to up\n"),
00386                        sval);
00387               rounding_method = ROUND_UP;
00388             }
00389         }
00390 
00391       process_skips (resource_subres (drlres, "skips"));
00392 
00393       for (i = 0; i < drlres->c; i++)
00394         {
00395           type = resource_type (drlres->v[i]);
00396           switch (type)
00397             {
00398             case 10:
00399               /* just a number */
00400               add_to_drills (drlres->v[i].value);
00401               break;
00402 
00403             default:
00404               break;
00405             }
00406         }
00407     }
00408 
00409   /* Extract the DRC resource */
00410   drcres = resource_subres (res, "drc");
00411 
00412   sval = resource_value (drcres, "copper_space");
00413   if (sval != NULL)
00414     {
00415       PCB->Bloat = floor (sf * atof (sval) + 0.5);
00416       Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
00417                0.01 * PCB->Bloat);
00418     }
00419 
00420   sval = resource_value (drcres, "copper_overlap");
00421   if (sval != NULL)
00422     {
00423       PCB->Shrink = floor (sf * atof (sval) + 0.5);
00424       Message (_("Set DRC minimum copper overlap to %.2f mils\n"),
00425                0.01 * PCB->Shrink);
00426     }
00427 
00428   sval = resource_value (drcres, "copper_width");
00429   if (sval != NULL)
00430     {
00431       PCB->minWid = floor (sf * atof (sval) + 0.5);
00432       Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
00433                0.01 * PCB->minWid);
00434     }
00435 
00436   sval = resource_value (drcres, "silk_width");
00437   if (sval != NULL)
00438     {
00439       PCB->minSlk = floor (sf * atof (sval) + 0.5);
00440       Message (_("Set DRC minimum silk width to %.2f mils\n"),
00441                0.01 * PCB->minSlk);
00442     }
00443 
00444   sval = resource_value (drcres, "min_drill");
00445   if (sval != NULL)
00446     {
00447       PCB->minDrill = floor (sf * atof (sval) + 0.5);
00448       Message (_("Set DRC minimum drill diameter to %.2f mils\n"),
00449                0.01 * PCB->minDrill);
00450     }
00451 
00452   sval = resource_value (drcres, "min_ring");
00453   if (sval != NULL)
00454     {
00455       PCB->minRing = floor (sf * atof (sval) + 0.5);
00456       Message (_("Set DRC minimum annular ring to %.2f mils\n"),
00457                0.01 * PCB->minRing);
00458     }
00459 
00460   Message (_("Loaded %d vendor drills from %s\n"), n_vendor_drills, fname);
00461   Message (_("Loaded %d RefDes skips, %d Value skips, %d Descr skips\n"),
00462            n_refdes, n_value, n_descr);
00463 
00464   vendorMapEnable = true;
00465   apply_vendor_map ();
00466   if (free_fname)
00467     free (fname);
00468   return 0;
00469 }
00470 
00471 static void
00472 apply_vendor_map (void)
00473 {
00474   int i;
00475   int changed, tot;
00476   bool state;
00477 
00478   state = vendorMapEnable;
00479 
00480   /* enable mapping */
00481   vendorMapEnable = true;
00482 
00483   /* reset our counts */
00484   changed = 0;
00485   tot = 0;
00486 
00487   /* If we have loaded vendor drills, then apply them to the design */
00488   if (n_vendor_drills > 0)
00489     {
00490 
00491       /* first all the vias */
00492       VIA_LOOP (PCB->Data);
00493       {
00494         tot++;
00495         if (via->DrillingHole != vendorDrillMap (via->DrillingHole))
00496           {
00497             /* only change unlocked vias */
00498             if (!TEST_FLAG (LOCKFLAG, via))
00499               {
00500                 if (ChangeObject2ndSize (VIA_TYPE, via, NULL, NULL,
00501                                          vendorDrillMap (via->DrillingHole),
00502                                          true, false))
00503                   changed++;
00504                 else
00505                   {
00506                     Message (_("Via at %.2f, %.2f not changed. "
00507                           "Possible reasons:\n"
00508                           "\t- pad size too small\n"
00509                           "\t- new size would be too large or too small\n"),
00510                         0.01 * via->X, 0.01 * via->Y);
00511                   }
00512               }
00513             else
00514               {
00515                 Message (_("Locked via at %.2f, %.2f not changed.\n"),
00516                          0.01 * via->X, 0.01 * via->Y);
00517               }
00518           }
00519       }
00520       END_LOOP;
00521 
00522       /* and now the pins */
00523       ELEMENT_LOOP (PCB->Data);
00524       {
00525         /*
00526          * first figure out if this element should be skipped for some
00527          * reason
00528          */
00529         if (vendorIsElementMappable (element))
00530           {
00531             /* the element is ok to modify, so iterate over its pins */
00532             PIN_LOOP (element);
00533             {
00534               tot++;
00535               if (pin->DrillingHole != vendorDrillMap (pin->DrillingHole))
00536                 {
00537                   if (!TEST_FLAG (LOCKFLAG, pin))
00538                     {
00539                       if (ChangeObject2ndSize (PIN_TYPE, element, pin, NULL,
00540                                                vendorDrillMap (pin->
00541                                                                DrillingHole),
00542                                                true, false))
00543                         changed++;
00544                       else
00545                         {
00546                           Message (_("Pin %s (%s) at %.2f, %.2f "
00547                                 "(element %s, %s, %s) not changed.\n"
00548                                 "\tPossible reasons:\n"
00549                                 "\t- pad size too small\n"
00550                                 "\t- new size would be too large or too small\n"),
00551                                    UNKNOWN (pin->Number), UNKNOWN (pin->Name),
00552                                    0.01 * pin->X, 0.01 * pin->Y,
00553                                    UNKNOWN (NAMEONPCB_NAME (element)),
00554                                    UNKNOWN (VALUE_NAME (element)),
00555                                    UNKNOWN (DESCRIPTION_NAME (element)));
00556                         }
00557                     }
00558                   else
00559                     {
00560                       Message (_("Locked pin at %-6.2f, %-6.2f not changed.\n"),
00561                                0.01 * pin->X, 0.01 * pin->Y);
00562                     }
00563                 }
00564             }
00565             END_LOOP;
00566           }
00567       }
00568       END_LOOP;
00569 
00570       Message (_("Updated %d drill sizes out of %d total\n"), changed, tot);
00571 
00572       /* Update the current Via */
00573       if (Settings.ViaDrillingHole !=
00574           vendorDrillMap (Settings.ViaDrillingHole))
00575         {
00576           changed++;
00577           Settings.ViaDrillingHole =
00578             vendorDrillMap (Settings.ViaDrillingHole);
00579           Message (_("Adjusted active via hole size to be %6.2f mils\n"),
00580                    0.01 * Settings.ViaDrillingHole);
00581         }
00582 
00583       /* and update the vias for the various routing styles */
00584       for (i = 0; i < NUM_STYLES; i++)
00585         {
00586           if (PCB->RouteStyle[i].Hole !=
00587               vendorDrillMap (PCB->RouteStyle[i].Hole))
00588             {
00589               changed++;
00590               PCB->RouteStyle[i].Hole =
00591                 vendorDrillMap (PCB->RouteStyle[i].Hole);
00592               Message (_("Adjusted %s routing style via hole size to be "
00593                     "%6.2f mils\n"),
00594                        PCB->RouteStyle[i].Name,
00595                        0.01 * PCB->RouteStyle[i].Hole);
00596               if (PCB->RouteStyle[i].Diameter <
00597                   PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER)
00598                 {
00599                   PCB->RouteStyle[i].Diameter =
00600                     PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER;
00601                   Message (_("Increased %s routing style via diameter to "
00602                         "%6.2f mils\n"),
00603                            PCB->RouteStyle[i].Name,
00604                            0.01 * PCB->RouteStyle[i].Diameter);
00605                 }
00606             }
00607         }
00608 
00609       /* 
00610        * if we've changed anything, indicate that we need to save the
00611        * file, redraw things, and make sure we can undo.
00612        */
00613       if (changed)
00614         {
00615           SetChangedFlag (true);
00616           Redraw ();
00617           IncrementUndoSerialNumber ();
00618         }
00619     }
00620 
00621   /* restore mapping on/off */
00622   vendorMapEnable = state;
00623 }
00624 
00628 int
00629 vendorDrillMap (int in)
00630 {
00631   int i, min, max;
00632 
00633   if (in == cached_drill)
00634     return cached_map;
00635   cached_drill = in;
00636 
00637   /* skip the mapping if we don't have a vendor drill table */
00638   if ((n_vendor_drills == 0) || (vendor_drills == NULL)
00639       || (vendorMapEnable == false))
00640     {
00641       cached_map = in;
00642       return in;
00643     }
00644 
00645   /* are we smaller than the smallest drill? */
00646   if (in <= vendor_drills[0])
00647     {
00648       cached_map = vendor_drills[0];
00649       return vendor_drills[0];
00650     }
00651 
00652   /* are we larger than the largest drill? */
00653   if (in > vendor_drills[n_vendor_drills - 1])
00654     {
00655       Message (_("Vendor drill list does not contain a drill >= %6.2f mil\n"
00656                  "Using %6.2f mil instead.\n"),
00657                0.01 * in, 0.01 * vendor_drills[n_vendor_drills - 1]);
00658       cached_map = vendor_drills[n_vendor_drills - 1];
00659       return vendor_drills[n_vendor_drills - 1];
00660     }
00661 
00662   /* figure out which 2 drills are closest in size */
00663   min = 0;
00664   max = n_vendor_drills - 1;
00665   while (max - min > 1)
00666     {
00667       i = (max+min) / 2;
00668       if (in > vendor_drills[i])
00669         min = i;
00670       else
00671         max = i;
00672     }
00673   i = max;
00674 
00675   /* now round per the rounding mode */
00676   if (rounding_method == CLOSEST)
00677     {
00678       /* find the closest drill size */
00679       if ((in - vendor_drills[i - 1]) > (vendor_drills[i] - in))
00680         {
00681           cached_map = vendor_drills[i];
00682           return vendor_drills[i];
00683         }
00684       else
00685         {
00686           cached_map = vendor_drills[i - 1];
00687           return vendor_drills[i - 1];
00688         }
00689     }
00690   else
00691     {
00692       /* always round up */
00693       cached_map = vendor_drills[i];
00694       return vendor_drills[i];
00695     }
00696 
00697 }
00698 
00702 static void
00703 add_to_drills (char *sval)
00704 {
00705   double tmpd;
00706   int val;
00707   int k, j;
00708 
00709   /* increment the count and make sure we have memory */
00710   n_vendor_drills++;
00711   if ((vendor_drills = (int *)realloc (vendor_drills,
00712                                 n_vendor_drills * sizeof (int))) == NULL)
00713     {
00714       fprintf (stderr, _("realloc() failed to allocate %ld bytes\n"),
00715                (unsigned long) n_vendor_drills * sizeof (int));
00716       return;
00717     }
00718 
00719   /* string to a value with the units scale factor in place */
00720   tmpd = atof (sval);
00721   val = floor (sf * tmpd + 0.5);
00722 
00723   /* 
00724    * We keep the array of vendor drills sorted to make it easier to
00725    * do the rounding later.  The algorithm used here is not so efficient,
00726    * but we're not dealing with much in the way of data.
00727    */
00728 
00729   /* figure out where to insert the value to keep the array sorted.  */
00730   k = 0;
00731   while ((k < n_vendor_drills - 1) && (vendor_drills[k] < val))
00732     k++;
00733 
00734   if (k == n_vendor_drills - 1)
00735     {
00736       vendor_drills[n_vendor_drills - 1] = val;
00737     }
00738   else
00739     {
00740       /* move up the existing drills to make room */
00741       for (j = n_vendor_drills - 1; j > k; j--)
00742         {
00743           vendor_drills[j] = vendor_drills[j - 1];
00744         }
00745 
00746       vendor_drills[k] = val;
00747     }
00748 }
00749 
00753 static void
00754 process_skips (Resource * res)
00755 {
00756   int type;
00757   int i, k;
00758   char *sval;
00759   int *cnt;
00760   char ***lst = NULL;
00761 
00762   if (res == NULL)
00763     return;
00764 
00765   for (i = 0; i < res->c; i++)
00766     {
00767       type = resource_type (res->v[i]);
00768       switch (type)
00769         {
00770         case 1:
00771           /* 
00772            * an unnamed sub resource.  This is something like
00773            * {refdes "J3"}
00774            */
00775           sval = res->v[i].subres->v[0].value;
00776           if (sval == NULL)
00777             {
00778               Message (_("Error:  null skip value\n"));
00779             }
00780           else
00781             {
00782               if (NSTRCMP (sval, "refdes") == 0)
00783                 {
00784                   cnt = &n_refdes;
00785                   lst = &ignore_refdes;
00786                 }
00787               else if (NSTRCMP (sval, "value") == 0)
00788                 {
00789                   cnt = &n_value;
00790                   lst = &ignore_value;
00791                 }
00792               else if (NSTRCMP (sval, "descr") == 0)
00793                 {
00794                   cnt = &n_descr;
00795                   lst = &ignore_descr;
00796                 }
00797               else
00798                 {
00799                   cnt = NULL;
00800                 }
00801 
00802               /* add the entry to the appropriate list */
00803               if (cnt != NULL)
00804                 {
00805                   for (k = 1; k < res->v[i].subres->c; k++)
00806                     {
00807                       sval = res->v[i].subres->v[k].value;
00808                       (*cnt)++;
00809                       if ((*lst =
00810                            (char **) realloc (*lst,
00811                                               (*cnt) * sizeof (char *))) ==
00812                           NULL)
00813                         {
00814                           fprintf (stderr, _("realloc() failed\n"));
00815                           exit (-1);
00816                         }
00817                       (*lst)[*cnt - 1] = strdup (sval);
00818                     }
00819                 }
00820             }
00821           break;
00822 
00823         default:
00824           Message (_("Ignored resource type = %d in skips= section\n"), type);
00825         }
00826     }
00827 
00828 }
00829 
00830 bool
00831 vendorIsElementMappable (ElementType *element)
00832 {
00833   int i;
00834   int noskip;
00835 
00836   if (vendorMapEnable == false)
00837     return false;
00838 
00839   noskip = 1;
00840   for (i = 0; i < n_refdes; i++)
00841     {
00842       if ((NSTRCMP (UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]) ==
00843            0)
00844           || rematch (ignore_refdes[i], UNKNOWN (NAMEONPCB_NAME (element))))
00845         {
00846           Message (_("Vendor mapping skipped because "
00847                 "refdes = %s matches %s\n"),
00848                    UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]);
00849           noskip = 0;
00850         }
00851     }
00852   if (noskip)
00853     for (i = 0; i < n_value; i++)
00854       {
00855         if ((NSTRCMP (UNKNOWN (VALUE_NAME (element)), ignore_value[i]) == 0)
00856             || rematch (ignore_value[i], UNKNOWN (VALUE_NAME (element))))
00857           {
00858             Message (_("Vendor mapping skipped because "
00859                   "value = %s matches %s\n"),
00860                      UNKNOWN (VALUE_NAME (element)), ignore_value[i]);
00861             noskip = 0;
00862           }
00863       }
00864 
00865   if (noskip)
00866     for (i = 0; i < n_descr; i++)
00867       {
00868         if ((NSTRCMP (UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i])
00869              == 0)
00870             || rematch (ignore_descr[i],
00871                         UNKNOWN (DESCRIPTION_NAME (element))))
00872           {
00873             Message (_("Vendor mapping skipped because "
00874                   "descr = %s matches %s\n"),
00875                      UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i]);
00876             noskip = 0;
00877           }
00878       }
00879 
00880   if (noskip && TEST_FLAG (LOCKFLAG, element))
00881     {
00882       Message (_("Vendor mapping skipped because element %s is locked\n"),
00883                UNKNOWN (NAMEONPCB_NAME (element)));
00884       noskip = 0;
00885     }
00886 
00887   if (noskip)
00888     return true;
00889   else
00890     return false;
00891 }
00892 
00893 static bool
00894 rematch (const char *re, const char *s)
00895 {
00896   /*
00897    * If this system has regular expression capability, then
00898    * add support for regular expressions in the skip lists.
00899    */
00900 
00901 #if defined(HAVE_REGCOMP)
00902 
00903   int result;
00904   regmatch_t match;
00905   regex_t compiled;
00906 
00907   /* compile the regular expression */
00908   result = regcomp (&compiled, re, REG_EXTENDED | REG_ICASE | REG_NOSUB);
00909   if (result)
00910     {
00911       char errorstring[128];
00912 
00913       regerror (result, &compiled, errorstring, sizeof (errorstring));
00914       Message (_("regexp error: %s\n"), errorstring);
00915       regfree (&compiled);
00916       return (false);
00917     }
00918 
00919   result = regexec (&compiled, s, 1, &match, 0);
00920   regfree (&compiled);
00921 
00922   if (result == 0)
00923     return (true);
00924   else
00925     return (false);
00926 
00927 #elif defined(HAVE_RE_COMP)
00928   int m;
00929   char *rslt;
00930 
00931   /* compile the regular expression */
00932   if ((rslt = re_comp (re)) != NULL)
00933     {
00934       Message (_("re_comp error: %s\n"), rslt);
00935       return (false);
00936     }
00937 
00938   m = re_exec (s);
00939 
00940   switch m
00941     {
00942     case 1:
00943       return (true);
00944       break;
00945 
00946     case 0:
00947       return (false);
00948       break;
00949 
00950     default:
00951       Message (_("re_exec error\n"));
00952       break;
00953     }
00954 
00955 #else
00956   return (false);
00957 #endif
00958 
00959 }
00960 
00961 HID_Action vendor_action_list[] = {
00962   {"ApplyVendor", 0, ActionApplyVendor,
00963    apply_vendor_help, apply_vendor_syntax}
00964   ,
00965   {"ToggleVendor", 0, ActionToggleVendor,
00966    toggle_vendor_help, toggle_vendor_syntax}
00967   ,
00968   {"EnableVendor", 0, ActionEnableVendor,
00969    enable_vendor_help, enable_vendor_syntax}
00970   ,
00971   {"DisableVendor", 0, ActionDisableVendor,
00972    disable_vendor_help, disable_vendor_syntax}
00973   ,
00974   {"UnloadVendor", 0, ActionUnloadVendor,
00975    unload_vendor_help, unload_vendor_syntax}
00976   ,
00977   {"LoadVendorFrom", 0, ActionLoadVendorFrom,
00978    load_vendor_help, load_vendor_syntax}
00979 };
00980 
00981 REGISTER_ACTIONS (vendor_action_list)
00982 
00983 static int vendor_get_enabled (void *data)
00984 {
00985   return vendorMapEnable;
00986 }
00987 
00988 HID_Flag vendor_flag_list[] = {
00989   {"VendorMapOn", vendor_get_enabled, NULL}
00990 };
00991 
00992 REGISTER_FLAGS (vendor_flag_list)