pcb 4.1.1
An interactive printed circuit board layout editor.

strflags.c

Go to the documentation of this file.
00001 
00039 #ifdef HAVE_CONFIG_H
00040 #include "config.h"
00041 #endif
00042 
00043 #include <stdio.h>
00044 #include <ctype.h>
00045 #ifdef HAVE_STDLIB_H
00046 #include <stdlib.h>
00047 #endif
00048 #ifdef HAVE_STRING_H
00049 #include <string.h>
00050 #endif
00051 
00052 #include "globalconst.h"
00053 #include "global.h"
00054 #include "compat.h"
00055 #include "hid.h"
00056 #include "strflags.h"
00057 
00058 #ifdef HAVE_LIBDMALLOC
00059 #include <dmalloc.h>
00060 #endif
00061 
00062 /* Because all the macros expect it, that's why.  */
00063 typedef struct
00064 {
00065   FlagType Flags;
00066 } FlagHolder;
00067 
00077 typedef struct
00078 {
00079   int mask; 
00080   char *name; 
00081   int nlen;
00082 #define N(x) x, sizeof(x)-1
00083 
00084   int object_types; 
00086 } FlagBitsType;
00087 
00088 static FlagBitsType object_flagbits[] = {
00089   { PINFLAG, N ("pin"), ALL_TYPES },
00090   { VIAFLAG, N ("via"), ALL_TYPES },
00091   { FOUNDFLAG, N ("found"), ALL_TYPES },
00092   { HOLEFLAG, N ("hole"), PIN_TYPES },
00093   { RATFLAG, N ("rat"), RATLINE_TYPE },
00094   { PININPOLYFLAG, N ("pininpoly"), PIN_TYPES | PAD_TYPE },
00095   { CLEARPOLYFLAG, N ("clearpoly"), POLYGON_TYPE },
00096   { HIDENAMEFLAG, N ("hidename"), ELEMENT_TYPE },
00097   { DISPLAYNAMEFLAG, N ("showname"), ELEMENT_TYPE },
00098   { CLEARLINEFLAG, N ("clearline"), LINE_TYPE | ARC_TYPE | TEXT_TYPE },
00099   { SELECTEDFLAG, N ("selected"), ALL_TYPES },
00100   { ONSOLDERFLAG, N ("onsolder"), ELEMENT_TYPE | PAD_TYPE | TEXT_TYPE | ELEMENTNAME_TYPE },
00101   { AUTOFLAG, N ("auto"), ALL_TYPES },
00102   { SQUAREFLAG, N ("square"), PIN_TYPES | PAD_TYPE },
00103   { RUBBERENDFLAG, N ("rubberend"), LINE_TYPE | ARC_TYPE },
00104   { WARNFLAG, N ("warn"), PIN_TYPES | PAD_TYPE },
00105   { USETHERMALFLAG, N ("usetherm"), PIN_TYPES | LINE_TYPE | ARC_TYPE },
00106   { OCTAGONFLAG, N ("octagon"), PIN_TYPES | PAD_TYPE },
00107   { DRCFLAG, N ("drc"), ALL_TYPES },
00108   { LOCKFLAG, N ("lock"), ALL_TYPES },
00109   { EDGE2FLAG, N ("edge2"), ALL_TYPES },
00110   { FULLPOLYFLAG, N ("fullpoly"), POLYGON_TYPE},
00111   { NOPASTEFLAG, N ("nopaste"), PAD_TYPE },
00112   { CONNECTEDFLAG, N ("connected"), ALL_TYPES }
00113 };
00114 
00115 static FlagBitsType pcb_flagbits[] = {
00116   { SHOWNUMBERFLAG, N ("shownumber"), ALL_TYPES },
00117   { LOCALREFFLAG, N ("localref"), ALL_TYPES },
00118   { CHECKPLANESFLAG, N ("checkplanes"), ALL_TYPES },
00119   { SHOWDRCFLAG, N ("showdrc"), ALL_TYPES },
00120   { RUBBERBANDFLAG, N ("rubberband"), ALL_TYPES },
00121   { DESCRIPTIONFLAG, N ("description"), ALL_TYPES },
00122   { NAMEONPCBFLAG, N ("nameonpcb"), ALL_TYPES },
00123   { AUTODRCFLAG, N ("autodrc"), ALL_TYPES },
00124   { ALLDIRECTIONFLAG, N ("alldirection"), ALL_TYPES },
00125   { SWAPSTARTDIRFLAG, N ("swapstartdir"), ALL_TYPES },
00126   { UNIQUENAMEFLAG, N ("uniquename"), ALL_TYPES },
00127   { CLEARNEWFLAG, N ("clearnew"), ALL_TYPES },
00128   { NEWFULLPOLYFLAG, N ("newfullpoly"), ALL_TYPES },
00129   { SNAPPINFLAG, N ("snappin"), ALL_TYPES },
00130   { SHOWMASKFLAG, N ("showmask"), ALL_TYPES },
00131   { THINDRAWFLAG, N ("thindraw"), ALL_TYPES },
00132   { ORTHOMOVEFLAG, N ("orthomove"), ALL_TYPES },
00133   { LIVEROUTEFLAG, N ("liveroute"), ALL_TYPES },
00134   { THINDRAWPOLYFLAG, N ("thindrawpoly"), ALL_TYPES },
00135   { LOCKNAMESFLAG, N ("locknames"), ALL_TYPES },
00136   { ONLYNAMESFLAG, N ("onlynames"), ALL_TYPES },
00137   { HIDENAMESFLAG, N ("hidenames"), ALL_TYPES },
00138   { AUTOBURIEDVIASFLAG, N ("autoburiedvias"), ALL_TYPES },
00139 };
00140 
00141 #undef N
00142 
00143 /*
00144  * This helper function maintains a small list of buffers which are
00145  * used by flags_to_string().  Each buffer is allocated from the heap,
00146  * but the caller must not free them (they get realloced when they're
00147  * reused, but never completely freed).
00148  */
00149 
00150 static struct
00151 {
00152   char *ptr;
00153   int len;
00154 } buffers[10];
00155 static int bufptr = 0;
00156 static char *
00157 alloc_buf (int len)
00158 {
00159 #define B buffers[bufptr]
00160   len++;
00161   bufptr = (bufptr + 1) % 10;
00162   if (B.len < len)
00163     {
00164       if (B.ptr)
00165         B.ptr = (char *) realloc (B.ptr, len);
00166       else
00167         B.ptr = (char *) malloc (len);
00168       B.len = len;
00169     }
00170   return B.ptr;
00171 #undef B
00172 }
00173 
00174 void
00175 uninit_strflags_buf (void)
00176 {
00177   int n;
00178   for (n = 0; n < 10; n++)
00179     {
00180       if (buffers[n].ptr != NULL)
00181         {
00182           free (buffers[n].ptr);
00183           buffers[n].ptr = NULL;
00184         }
00185     }
00186 }
00187 
00188 static char *layers = 0;
00189 static int max_layers = 0, num_layers = 0;
00190 
00202 static void
00203 grow_layer_list (int num)
00204 {
00205   if (layers == 0)
00206     {
00207       layers = (char *) calloc (num > 0 ? num : 1, 1);
00208       max_layers = num;
00209     }
00210   else if (num > max_layers)
00211     {
00212       max_layers = num;
00213       layers = (char *) realloc (layers, max_layers);
00214     }
00215   if (num > num_layers)
00216     memset (layers + num_layers, 0, num - num_layers - 1);
00217   num_layers = num;
00218   return;
00219 }
00220 
00221 void
00222 uninit_strflags_layerlist (void)
00223 {
00224   if (layers != NULL)
00225     {
00226       free (layers);
00227       layers = NULL;
00228       num_layers = max_layers = 0;
00229     }
00230 }
00231 
00243 static inline void
00244 set_layer_list (int layer, int v)
00245 {
00246   if (layer >= num_layers)
00247     grow_layer_list (layer + 1);
00248   layers[layer] = v;
00249 }
00250 
00269 static const char *
00270 parse_layer_list (const char *bp, int (*error) (const char *))
00271 {
00272   const char *orig_bp = bp;
00273   int l = 0, range = -1;
00274   int value = 1;
00275 
00276   grow_layer_list (0);
00277   while (*bp)
00278     {
00279       if (*bp == '+')
00280         value = 2;
00281       else if (*bp == 'S')
00282         value = 3;
00283       else if (*bp == 'X')
00284         value = 4;
00285       else if (*bp == 't')
00286         value = 5;
00287       else if (*bp == ')' || *bp == ',' || *bp == '-')
00288         {
00289           if (range == -1)
00290             range = l;
00291           while (range <= l)
00292             set_layer_list (range++, value);
00293           if (*bp == '-')
00294             range = l;
00295           else
00296             range = -1;
00297           value = 1;
00298           l = 0;
00299         }
00300 
00301       else if (isdigit ((int) *bp))
00302         l = l * 10 + (*bp - '0');
00303 
00304       else if (error)
00305         {
00306           char *fmt = "Syntax error parsing layer list \"%.*s\" at %c";
00307           char *msg = alloc_buf (strlen (fmt) + strlen (orig_bp));
00308           sprintf (msg, fmt, bp - orig_bp + 5, orig_bp, *bp);
00309           error (msg);
00310           error = NULL;
00311         }
00312 
00313       if (*bp == ')')
00314         return bp + 1;
00315 
00316       bp++;
00317     }
00318   return bp;
00319 }
00320 
00324 static int
00325 printed_int_length (int i, int j)
00326 {
00327   int rv;
00328 
00329   if (i < 10)
00330     return 1 + (j ? 1 : 0);
00331   if (i < 100)
00332     return 2 + (j ? 1 : 0);
00333 
00334   for (rv = 1; i >= 10; rv++)
00335     i /= 10;
00336   return rv + (j ? 1 : 0);
00337 }
00338 
00354 static char *
00355 print_layer_list ()
00356 {
00357   static char *buf = 0;
00358   static int buflen = 0;
00359   int len, i, j;
00360   char *bp;
00361 
00362   len = 2;
00363   for (i = 0; i < num_layers; i++)
00364     if (layers[i])
00365       len += 1 + printed_int_length (i, layers[i]);
00366   if (buflen < len)
00367     {
00368       if (buf)
00369         buf = (char *) realloc (buf, len);
00370       else
00371         buf = (char *) malloc (len);
00372       buflen = len;
00373     }
00374 
00375   bp = buf;
00376   *bp++ = '(';
00377 
00378   for (i = 0; i < num_layers; i++)
00379     if (layers[i])
00380       {
00381         /* 0 0 1 1 1 0 0 */
00382         /*     i     j   */
00383         for (j = i + 1; j < num_layers && layers[j] == 1; j++)
00384           ;
00385         if (j > i + 2)
00386           {
00387             sprintf (bp, "%d-%d,", i, j - 1);
00388             i = j - 1;
00389           }
00390         else
00391           switch (layers[i])
00392           {
00393             case 1:
00394              sprintf (bp, "%d,", i);
00395              break;
00396             case 2:
00397              sprintf (bp, "%d+,", i);
00398              break;
00399             case 3:
00400              sprintf (bp, "%dS,", i);
00401              break;
00402             case 4:
00403              sprintf (bp, "%dX,", i);
00404              break;
00405             case 5:
00406             default:
00407              sprintf (bp, "%dt,", i);
00408              break;
00409            }
00410         bp += strlen (bp);
00411       }
00412   bp[-1] = ')';
00413   *bp = 0;
00414   return buf;
00415 }
00416 
00417 static int
00418 error_ignore (const char *msg)
00419 {                               /* do nothing */
00420   return 0;
00421 }
00422 static FlagType empty_flags;
00423 
00424 static FlagType
00425 common_string_to_flags (const char *flagstring,
00426                         int (*error) (const char *msg),
00427                         FlagBitsType *flagbits,
00428                         int n_flagbits)
00429 {
00430   const char *fp, *ep;
00431   int flen;
00432   FlagHolder rv;
00433   int i;
00434 
00435   rv.Flags = empty_flags;
00436 
00437   if (error == 0)
00438     error = error_ignore;
00439 
00440   if (flagstring == NULL)
00441     return empty_flags;
00442 
00443   fp = ep = flagstring;
00444 
00445   if (*fp == '"')
00446     ep = ++fp;
00447 
00448   while (*ep && *ep != '"')
00449     {
00450       int found = 0;
00451 
00452       for (ep = fp; *ep && *ep != ',' && *ep != '"' && *ep != '('; ep++)
00453         ;
00454       flen = ep - fp;
00455       if (*ep == '(')
00456         ep = parse_layer_list (ep + 1, error);
00457 
00458       if (flen == 7 && memcmp (fp, "thermal", 7) == 0)
00459         {
00460           for (i = 0; i < MAX_LAYER && i < num_layers; i++)
00461             if (layers[i])
00462               ASSIGN_THERM (i, layers[i], &rv);
00463         }
00464       else
00465         {
00466           for (i = 0; i < n_flagbits; i++)
00467             if (flagbits[i].nlen == flen
00468                 && memcmp (flagbits[i].name, fp, flen) == 0)
00469               {
00470                 found = 1;
00471                 SET_FLAG (flagbits[i].mask, &rv);
00472                 break;
00473               }
00474           if (!found)
00475             {
00476               const char *fmt = "Unknown flag: \"%.*s\" ignored";
00477               char *msg = alloc_buf (strlen (fmt) + flen);
00478               sprintf (msg, fmt, flen, fp);
00479               error (msg);
00480             }
00481         }
00482       fp = ep + 1;
00483     }
00484   return rv.Flags;
00485 }
00486 
00496 FlagType
00497 string_to_flags (const char *flagstring,
00498                  int (*error) (const char *msg))
00499 {
00500   return common_string_to_flags (flagstring,
00501                                  error,
00502                                  object_flagbits,
00503                                  ENTRIES (object_flagbits));
00504 }
00505 
00515 FlagType
00516 string_to_pcbflags (const char *flagstring,
00517                     int (*error) (const char *msg))
00518 {
00519   return common_string_to_flags (flagstring,
00520                                  error,
00521                                  pcb_flagbits,
00522                                  ENTRIES (pcb_flagbits));
00523 }
00524 
00540 static char *
00541 common_flags_to_string (FlagType flags,
00542                         int object_type,
00543                         FlagBitsType *flagbits,
00544                         int n_flagbits)
00545 {
00546   int len;
00547   int i;
00548   FlagHolder fh, savef;
00549   char *buf, *bp;
00550 
00551   fh.Flags = flags;
00552 
00553   switch (object_type)
00554     {
00555     case VIA_TYPE:
00556       CLEAR_FLAG (VIAFLAG, &fh);
00557       break;
00558     case RATLINE_TYPE:
00559       CLEAR_FLAG (RATFLAG, &fh);
00560       break;
00561     case PIN_TYPE:
00562       CLEAR_FLAG (PINFLAG, &fh);
00563       break;
00564     }
00565 
00566   savef = fh;
00567 
00568   len = 3;                      /* for "()\0" */
00569   for (i = 0; i < n_flagbits; i++)
00570     if ((flagbits[i].object_types & object_type)
00571         && (TEST_FLAG (flagbits[i].mask, &fh)))
00572       {
00573         len += flagbits[i].nlen + 1;
00574         CLEAR_FLAG (flagbits[i].mask, &fh);
00575       }
00576 
00577   if (TEST_ANY_THERMS (&fh))
00578     {
00579       len += sizeof ("thermal()");
00580       for (i = 0; i < MAX_LAYER; i++)
00581         if (TEST_THERM (i, &fh))
00582           len += printed_int_length (i, GET_THERM (i, &fh)) + 1;
00583     }
00584 
00585   bp = buf = alloc_buf (len + 2);
00586 
00587   *bp++ = '"';
00588 
00589   fh = savef;
00590   for (i = 0; i < n_flagbits; i++)
00591     if (flagbits[i].object_types & object_type
00592         && (TEST_FLAG (flagbits[i].mask, &fh)))
00593       {
00594         if (bp != buf + 1)
00595           *bp++ = ',';
00596         strcpy (bp, flagbits[i].name);
00597         bp += flagbits[i].nlen;
00598         CLEAR_FLAG (flagbits[i].mask, &fh);
00599       }
00600 
00601   if (TEST_ANY_THERMS (&fh))
00602     {
00603       if (bp != buf + 1)
00604         *bp++ = ',';
00605       strcpy (bp, "thermal");
00606       bp += strlen ("thermal");
00607       grow_layer_list (0);
00608       for (i = 0; i < MAX_LAYER; i++)
00609         if (TEST_THERM (i, &fh))
00610           set_layer_list (i, GET_THERM (i, &fh));
00611       strcpy (bp, print_layer_list ());
00612       bp += strlen (bp);
00613     }
00614 
00615   *bp++ = '"';
00616   *bp = 0;
00617   return buf;
00618 }
00619 
00628 char *
00629 flags_to_string (FlagType flags, int object_type)
00630 {
00631   return common_flags_to_string (flags,
00632                                  object_type,
00633                                  object_flagbits,
00634                                  ENTRIES (object_flagbits));
00635 }
00636 
00640 char *
00641 pcbflags_to_string (FlagType flags)
00642 {
00643   return common_flags_to_string (flags,
00644                                  ALL_TYPES,
00645                                  pcb_flagbits,
00646                                  ENTRIES (pcb_flagbits));
00647 }