pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00035 #ifdef HAVE_CONFIG_H 00036 #include "config.h" 00037 #endif 00038 00039 #include <stdio.h> 00040 #include <stdlib.h> 00041 #include <string.h> 00042 00043 #ifdef HAVE_DLFCN_H 00044 #include <dlfcn.h> 00045 #endif 00046 00047 #include <dirent.h> 00048 #include <sys/types.h> 00049 #include <sys/stat.h> 00050 #include <unistd.h> 00051 00052 #if defined(WIN32) && defined(HAVE_WINDOWS_H) 00053 #define WIN32_LEAN_AND_MEAN 00054 #include <windows.h> 00055 #endif 00056 00057 #include "global.h" 00058 #include "hid.h" 00059 #include "hidnogui.h" 00060 #include "../hidint.h" 00061 00062 /* for dlopen() and friends on windows */ 00063 #include "compat.h" 00064 00065 #include "error.h" 00066 #include "global.h" 00067 #include "misc.h" 00068 #include "pcb-printf.h" 00069 00070 #ifdef HAVE_LIBDMALLOC 00071 #include <dmalloc.h> 00072 #endif 00073 00074 #define HID_DEF(x) extern void hid_ ## x ## _init(void); 00075 #include "hid/common/hidlist.h" 00076 #undef HID_DEF 00077 00078 HID **hid_list = 0; 00079 int hid_num_hids = 0; 00080 00081 HID *gui = NULL; 00082 HID *exporter = NULL; 00083 00084 int pixel_slop = 1; 00085 00097 static void 00098 hid_load_dir (char *dirname) 00099 { 00100 DIR *dir; 00101 struct dirent *de; 00102 00103 dir = opendir (dirname); 00104 if (!dir) 00105 { 00106 free (dirname); 00107 return; 00108 } 00109 while ((de = readdir (dir)) != NULL) 00110 { 00111 void *sym; 00112 void (*symv)(); 00113 void *so; 00114 char *basename, *path, *symname; 00115 struct stat st; 00116 00117 basename = strdup (de->d_name); 00118 if (strlen (basename) > 3 00119 && strcasecmp (basename+strlen(basename)-3, ".so") == 0) 00120 basename[strlen(basename)-3] = 0; 00121 else if (strlen (basename) > 4 00122 && strcasecmp (basename+strlen(basename)-4, ".dll") == 0) 00123 basename[strlen(basename)-4] = 0; 00124 path = Concat (dirname, PCB_DIR_SEPARATOR_S, de->d_name, NULL); 00125 00126 if (stat (path, &st) == 0 00127 && ( 00128 /* mingw and win32 do not support S_IXGRP or S_IXOTH */ 00129 #if defined(S_IXGRP) 00130 (st.st_mode & S_IXGRP) || 00131 #endif 00132 #if defined(S_IXOTH) 00133 (st.st_mode & S_IXOTH) || 00134 #endif 00135 (st.st_mode & S_IXUSR) ) 00136 && S_ISREG (st.st_mode)) 00137 { 00138 if ((so = dlopen (path, RTLD_NOW | RTLD_GLOBAL)) == NULL) 00139 { 00140 fprintf(stderr, "dl_error: %s\n", dlerror ()); 00141 } 00142 else 00143 { 00144 symname = Concat ("hid_", basename, "_init", NULL); 00145 if ((sym = dlsym (so, symname)) != NULL) 00146 { 00147 symv = (void (*)()) sym; 00148 symv(); 00149 } 00150 else if ((sym = dlsym (so, "pcb_plugin_init")) != NULL) 00151 { 00152 symv = (void (*)()) sym; 00153 symv(); 00154 } 00155 free (symname); 00156 } 00157 } 00158 free (basename); 00159 free (path); 00160 } 00161 free (dirname); 00162 closedir (dir); 00163 } 00164 00172 void 00173 hid_init () 00174 { 00175 /* Setup a "nogui" default HID */ 00176 gui = hid_nogui_get_hid (); 00177 00178 /* Call all of the hid initialization functions */ 00179 #define HID_DEF(x) hid_ ## x ## _init(); 00180 #include "hid/common/hidlist.h" 00181 #undef HID_DEF 00182 00183 /* Search the exec_prefix for plugins and load them */ 00184 hid_load_dir (Concat (exec_prefix, PCB_DIR_SEPARATOR_S, "lib", 00185 PCB_DIR_SEPARATOR_S, "pcb", 00186 PCB_DIR_SEPARATOR_S, "plugins", 00187 PCB_DIR_SEPARATOR_S, HOST, NULL)); 00188 hid_load_dir (Concat (exec_prefix, PCB_DIR_SEPARATOR_S, "lib", 00189 PCB_DIR_SEPARATOR_S, "pcb", 00190 PCB_DIR_SEPARATOR_S, "plugins", NULL)); 00191 00192 /* Search homedir for plugins and load them. homedir is set by the core 00193 * immediately on startup */ 00194 if (homedir != NULL) 00195 { 00196 hid_load_dir (Concat (homedir, PCB_DIR_SEPARATOR_S, ".pcb", 00197 PCB_DIR_SEPARATOR_S, "plugins", 00198 PCB_DIR_SEPARATOR_S, HOST, NULL)); 00199 hid_load_dir (Concat (homedir, PCB_DIR_SEPARATOR_S, ".pcb", 00200 PCB_DIR_SEPARATOR_S, "plugins", NULL)); 00201 } 00202 hid_load_dir (Concat ("plugins", PCB_DIR_SEPARATOR_S, HOST, NULL)); 00203 hid_load_dir (Concat ("plugins", NULL)); 00204 } 00205 00206 void 00207 hid_uninit (void) 00208 { 00209 00210 } 00211 00215 void 00216 hid_register_hid (HID * hid) 00217 { 00218 int i; 00219 int sz = (hid_num_hids + 2) * sizeof (HID *); 00220 00221 if (hid->struct_size != sizeof (HID)) 00222 { 00223 fprintf (stderr, "Warning: hid \"%s\" has an incompatible ABI.\n", 00224 hid->name); 00225 return; 00226 } 00227 00228 for (i=0; i<hid_num_hids; i++) 00229 if (hid == hid_list[i]) 00230 return; 00231 00232 hid_num_hids++; 00233 if (hid_list) 00234 hid_list = (HID **) realloc (hid_list, sz); 00235 else 00236 hid_list = (HID **) malloc (sz); 00237 00238 hid_list[hid_num_hids - 1] = hid; 00239 hid_list[hid_num_hids] = 0; 00240 } 00241 00242 00243 HID * 00244 hid_find_gui () 00245 { 00246 int i; 00247 00248 for (i = 0; i < hid_num_hids; i++) 00249 if (!hid_list[i]->printer && !hid_list[i]->exporter) 00250 return hid_list[i]; 00251 00252 fprintf (stderr, "Error: No GUI available.\n"); 00253 exit (1); 00254 } 00255 00256 HID * 00257 hid_find_printer () 00258 { 00259 int i; 00260 00261 for (i = 0; i < hid_num_hids; i++) 00262 if (hid_list[i]->printer) 00263 return hid_list[i]; 00264 00265 return 0; 00266 } 00267 00268 HID * 00269 hid_find_exporter (const char *which) 00270 { 00271 int i; 00272 00273 for (i = 0; i < hid_num_hids; i++) 00274 if (hid_list[i]->exporter && strcmp (which, hid_list[i]->name) == 0) 00275 return hid_list[i]; 00276 00277 fprintf (stderr, "Invalid exporter %s, available ones:", which); 00278 for (i = 0; i < hid_num_hids; i++) 00279 if (hid_list[i]->exporter) 00280 fprintf (stderr, " %s", hid_list[i]->name); 00281 fprintf (stderr, "\n"); 00282 00283 return 0; 00284 } 00285 00286 HID ** 00287 hid_enumerate () 00288 { 00289 return hid_list; 00290 } 00291 00292 HID_AttrNode *hid_attr_nodes = 0; 00293 00294 void 00295 hid_register_attributes (HID_Attribute * a, int n) 00296 { 00297 HID_AttrNode *ha; 00298 00299 /* printf("%d attributes registered\n", n); */ 00300 ha = (HID_AttrNode *) malloc (sizeof (HID_AttrNode)); 00301 ha->next = hid_attr_nodes; 00302 hid_attr_nodes = ha; 00303 ha->attributes = a; 00304 ha->n = n; 00305 } 00306 00307 void 00308 hid_parse_command_line (int *argc, char ***argv) 00309 { 00310 HID_AttrNode *ha; 00311 int i, e, ok; 00312 00313 (*argc)--; 00314 (*argv)++; 00315 00316 for (ha = hid_attr_nodes; ha; ha = ha->next) 00317 for (i = 0; i < ha->n; i++) 00318 { 00319 HID_Attribute *a = ha->attributes + i; 00320 switch (a->type) 00321 { 00322 case HID_Label: 00323 break; 00324 case HID_Integer: 00325 if (a->value) 00326 *(int *) a->value = a->default_val.int_value; 00327 break; 00328 case HID_Coord: 00329 if (a->value) 00330 *(Coord *) a->value = a->default_val.coord_value; 00331 break; 00332 case HID_Boolean: 00333 if (a->value) 00334 *(char *) a->value = a->default_val.int_value; 00335 break; 00336 case HID_Real: 00337 if (a->value) 00338 *(double *) a->value = a->default_val.real_value; 00339 break; 00340 case HID_String: 00341 if (a->value) 00342 *(const char **) a->value = a->default_val.str_value; 00343 break; 00344 case HID_Enum: 00345 if (a->value) 00346 *(int *) a->value = a->default_val.int_value; 00347 break; 00348 case HID_Mixed: 00349 if (a->value) { 00350 *(HID_Attr_Val *) a->value = a->default_val; 00351 case HID_Unit: 00352 if (a->value) 00353 *(int *) a->value = a->default_val.int_value; 00354 break; 00355 } 00356 break; 00357 default: 00358 abort (); 00359 } 00360 } 00361 00362 while (*argc && (*argv)[0][0] == '-' && (*argv)[0][1] == '-') 00363 { 00364 int bool_val; 00365 int arg_ofs; 00366 00367 bool_val = 1; 00368 arg_ofs = 2; 00369 try_no_arg: 00370 for (ha = hid_attr_nodes; ha; ha = ha->next) 00371 for (i = 0; i < ha->n; i++) 00372 if (strcmp ((*argv)[0] + arg_ofs, ha->attributes[i].name) == 0) 00373 { 00374 HID_Attribute *a = ha->attributes + i; 00375 char *ep; 00376 const Unit *unit; 00377 switch (ha->attributes[i].type) 00378 { 00379 case HID_Label: 00380 break; 00381 case HID_Integer: 00382 if (a->value) 00383 *(int *) a->value = strtol ((*argv)[1], 0, 0); 00384 else 00385 a->default_val.int_value = strtol ((*argv)[1], 0, 0); 00386 (*argc)--; 00387 (*argv)++; 00388 break; 00389 case HID_Coord: 00390 if (a->value) 00391 *(Coord *) a->value = GetValue ((*argv)[1], NULL, NULL); 00392 else 00393 a->default_val.coord_value = GetValue ((*argv)[1], NULL, NULL); 00394 (*argc)--; 00395 (*argv)++; 00396 break; 00397 case HID_Real: 00398 if (a->value) 00399 *(double *) a->value = strtod ((*argv)[1], 0); 00400 else 00401 a->default_val.real_value = strtod ((*argv)[1], 0); 00402 (*argc)--; 00403 (*argv)++; 00404 break; 00405 case HID_String: 00406 if (a->value) 00407 *(char **) a->value = (*argv)[1]; 00408 else 00409 a->default_val.str_value = (*argv)[1]; 00410 (*argc)--; 00411 (*argv)++; 00412 break; 00413 case HID_Boolean: 00414 if (a->value) 00415 *(char *) a->value = bool_val; 00416 else 00417 a->default_val.int_value = bool_val; 00418 break; 00419 case HID_Mixed: 00420 a->default_val.real_value = strtod ((*argv)[1], &ep); 00421 goto do_enum; 00422 case HID_Enum: 00423 ep = (*argv)[1]; 00424 do_enum: 00425 ok = 0; 00426 for (e = 0; a->enumerations[e]; e++) 00427 if (strcmp (a->enumerations[e], ep) == 0) 00428 { 00429 ok = 1; 00430 a->default_val.int_value = e; 00431 a->default_val.str_value = ep; 00432 break; 00433 } 00434 if (!ok) 00435 { 00436 fprintf (stderr, 00437 "ERROR: \"%s\" is an unknown value for the --%s option\n", 00438 (*argv)[1], a->name); 00439 exit (1); 00440 } 00441 (*argc)--; 00442 (*argv)++; 00443 break; 00444 case HID_Path: 00445 abort (); 00446 a->default_val.str_value = (*argv)[1]; 00447 (*argc)--; 00448 (*argv)++; 00449 break; 00450 case HID_Unit: 00451 unit = get_unit_struct ((*argv)[1]); 00452 if (unit == NULL) 00453 { 00454 fprintf (stderr, 00455 "ERROR: unit \"%s\" is unknown to pcb (option --%s)\n", 00456 (*argv)[1], a->name); 00457 exit (1); 00458 } 00459 a->default_val.int_value = unit->index; 00460 a->default_val.str_value = unit->suffix; 00461 (*argc)--; 00462 (*argv)++; 00463 break; 00464 } 00465 (*argc)--; 00466 (*argv)++; 00467 ha = 0; 00468 goto got_match; 00469 } 00470 if (bool_val == 1 && strncmp ((*argv)[0], "--no-", 5) == 0) 00471 { 00472 bool_val = 0; 00473 arg_ofs = 5; 00474 goto try_no_arg; 00475 } 00476 fprintf (stderr, "unrecognized option: %s\n", (*argv)[0]); 00477 exit (1); 00478 got_match:; 00479 } 00480 00481 (*argc)++; 00482 (*argv)--; 00483 } 00484 00485 static int 00486 attr_hash (HID_Attribute *a) 00487 { 00488 unsigned char *cp = (unsigned char *)a; 00489 int i, rv=0; 00490 for (i=0; i<(int)((char *)&(a->hash) - (char *)a); i++) 00491 rv = (rv * 13) ^ (rv >> 16) ^ cp[i]; 00492 return rv; 00493 } 00494 00495 void 00496 hid_save_settings (int locally) 00497 { 00498 char *fname; 00499 struct stat st; 00500 FILE *f; 00501 HID_AttrNode *ha; 00502 int i; 00503 00504 if (locally) 00505 { 00506 fname = Concat ("pcb.settings", NULL); 00507 } 00508 else 00509 { 00510 if (homedir == NULL) 00511 return; 00512 fname = Concat (homedir, PCB_DIR_SEPARATOR_S, ".pcb", NULL); 00513 00514 if (stat (fname, &st)) 00515 if (MKDIR (fname, 0777)) 00516 { 00517 free (fname); 00518 return; 00519 } 00520 free (fname); 00521 00522 fname = Concat (homedir, PCB_DIR_SEPARATOR_S, ".pcb", 00523 PCB_DIR_SEPARATOR_S, "settings", NULL); 00524 } 00525 00526 f = fopen (fname, "w"); 00527 if (!f) 00528 { 00529 Message ("Can't open %s", fname); 00530 free (fname); 00531 return; 00532 } 00533 00534 for (ha = hid_attr_nodes; ha; ha = ha->next) 00535 { 00536 for (i = 0; i < ha->n; i++) 00537 { 00538 const char *str; 00539 HID_Attribute *a = ha->attributes + i; 00540 00541 if (a->hash == attr_hash (a)) 00542 fprintf (f, "# "); 00543 switch (a->type) 00544 { 00545 case HID_Label: 00546 break; 00547 case HID_Integer: 00548 fprintf (f, "%s = %d\n", 00549 a->name, 00550 a->value ? *(int *)a->value : a->default_val.int_value); 00551 break; 00552 case HID_Coord: 00553 pcb_fprintf (f, "%s = %$mS\n", 00554 a->name, 00555 a->value ? *(Coord *)a->value : a->default_val.coord_value); 00556 break; 00557 case HID_Boolean: 00558 fprintf (f, "%s = %d\n", 00559 a->name, 00560 a->value ? *(char *)a->value : a->default_val.int_value); 00561 break; 00562 case HID_Real: 00563 fprintf (f, "%s = %f\n", 00564 a->name, 00565 a->value ? *(double *)a->value : a->default_val.real_value); 00566 break; 00567 case HID_String: 00568 case HID_Path: 00569 str = a->value ? *(char **)a->value : a->default_val.str_value; 00570 fprintf (f, "%s = %s\n", a->name, str ? str : ""); 00571 break; 00572 case HID_Enum: 00573 fprintf (f, "%s = %s\n", 00574 a->name, 00575 a->enumerations[a->value ? *(int *)a->value : a->default_val.int_value]); 00576 break; 00577 case HID_Mixed: 00578 { 00579 HID_Attr_Val *value = 00580 a->value ? (HID_Attr_Val*) a->value : &(a->default_val); 00581 fprintf (f, "%s = %g%s\n", 00582 a->name, 00583 value->real_value, 00584 a->enumerations[value->int_value]); 00585 } 00586 break; 00587 case HID_Unit: 00588 fprintf (f, "%s = %s\n", 00589 a->name, 00590 get_unit_list()[a->value ? *(int *)a->value : a->default_val.int_value].suffix); 00591 break; 00592 } 00593 } 00594 fprintf (f, "\n"); 00595 } 00596 fclose (f); 00597 free (fname); 00598 } 00599 00600 static void 00601 hid_set_attribute (char *name, char *value) 00602 { 00603 const Unit *unit; 00604 HID_AttrNode *ha; 00605 int i, e, ok; 00606 00607 for (ha = hid_attr_nodes; ha; ha = ha->next) 00608 for (i = 0; i < ha->n; i++) 00609 if (strcmp (name, ha->attributes[i].name) == 0) 00610 { 00611 HID_Attribute *a = ha->attributes + i; 00612 switch (ha->attributes[i].type) 00613 { 00614 case HID_Label: 00615 break; 00616 case HID_Integer: 00617 a->default_val.int_value = strtol (value, 0, 0); 00618 break; 00619 case HID_Coord: 00620 a->default_val.coord_value = GetValue (value, NULL, NULL); 00621 break; 00622 case HID_Real: 00623 a->default_val.real_value = strtod (value, 0); 00624 break; 00625 case HID_String: 00626 a->default_val.str_value = strdup (value); 00627 break; 00628 case HID_Boolean: 00629 a->default_val.int_value = 1; 00630 break; 00631 case HID_Mixed: 00632 a->default_val.real_value = strtod (value, &value); 00633 /* fall through */ 00634 case HID_Enum: 00635 ok = 0; 00636 for (e = 0; a->enumerations[e]; e++) 00637 if (strcmp (a->enumerations[e], value) == 0) 00638 { 00639 ok = 1; 00640 a->default_val.int_value = e; 00641 a->default_val.str_value = value; 00642 break; 00643 } 00644 if (!ok) 00645 { 00646 fprintf (stderr, 00647 "ERROR: \"%s\" is an unknown value for the %s option\n", 00648 value, a->name); 00649 exit (1); 00650 } 00651 break; 00652 case HID_Path: 00653 a->default_val.str_value = value; 00654 break; 00655 case HID_Unit: 00656 unit = get_unit_struct (value); 00657 if (unit == NULL) 00658 { 00659 fprintf (stderr, 00660 "ERROR: unit \"%s\" is unknown to pcb (option --%s)\n", 00661 value, a->name); 00662 exit (1); 00663 } 00664 a->default_val.int_value = unit->index; 00665 a->default_val.str_value = unit->suffix; 00666 break; 00667 } 00668 } 00669 } 00670 00671 static void 00672 hid_load_settings_1 (char *fname) 00673 { 00674 char line[1024], *namep, *valp, *cp; 00675 FILE *f; 00676 00677 f = fopen (fname, "r"); 00678 if (!f) 00679 { 00680 free (fname); 00681 return; 00682 } 00683 00684 free (fname); 00685 while (fgets (line, sizeof(line), f) != NULL) 00686 { 00687 for (namep=line; *namep && isspace ((int) *namep); namep++) 00688 ; 00689 if (*namep == '#') 00690 continue; 00691 for (valp=namep; *valp && !isspace((int) *valp); valp++) 00692 ; 00693 if (! *valp) 00694 continue; 00695 *valp++ = 0; 00696 while (*valp && (isspace ((int) *valp) || *valp == '=')) 00697 valp ++; 00698 if (! *valp) 00699 continue; 00700 cp = valp + strlen(valp) - 1; 00701 while (cp >= valp && isspace ((int) *cp)) 00702 *cp-- = 0; 00703 hid_set_attribute (namep, valp); 00704 } 00705 00706 fclose (f); 00707 } 00708 00709 void 00710 hid_load_settings () 00711 { 00712 HID_AttrNode *ha; 00713 int i; 00714 00715 for (ha = hid_attr_nodes; ha; ha = ha->next) 00716 for (i = 0; i < ha->n; i++) 00717 ha->attributes[i].hash = attr_hash (ha->attributes+i); 00718 00719 hid_load_settings_1 (Concat (pcblibdir, PCB_DIR_SEPARATOR_S, "settings", NULL)); 00720 if (homedir != NULL) 00721 hid_load_settings_1 (Concat (homedir, PCB_DIR_SEPARATOR_S, ".pcb", 00722 PCB_DIR_SEPARATOR_S, "settings", NULL)); 00723 hid_load_settings_1 (Concat ("pcb.settings", NULL)); 00724 } 00725 00726 #define HASH_SIZE 31 00727 00728 typedef struct ecache 00729 { 00730 struct ecache *next; 00731 const char *name; 00732 hidval val; 00733 } ecache; 00734 00735 typedef struct ccache 00736 { 00737 ecache *colors[HASH_SIZE]; 00738 ecache *lru; 00739 } ccache; 00740 00741 static void 00742 copy_color (int set, hidval * cval, hidval * aval) 00743 { 00744 if (set) 00745 memcpy (cval, aval, sizeof (hidval)); 00746 else 00747 memcpy (aval, cval, sizeof (hidval)); 00748 } 00749 00750 int 00751 hid_cache_color (int set, const char *name, hidval * val, void **vcache) 00752 { 00753 unsigned long hash; 00754 const char *cp; 00755 ccache *cache; 00756 ecache *e; 00757 00758 cache = (ccache *) * vcache; 00759 if (cache == 0) { 00760 cache = (ccache *) calloc (sizeof (ccache), 1); 00761 *vcache = cache; 00762 } 00763 if (cache->lru && strcmp (cache->lru->name, name) == 0) 00764 { 00765 copy_color (set, &(cache->lru->val), val); 00766 return 1; 00767 } 00768 00769 /* djb2: this algorithm (k=33) was first reported by dan bernstein many 00770 * years ago in comp.lang.c. another version of this algorithm (now favored 00771 * by bernstein) uses xor: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic 00772 * of number 33 (why it works better than many other constants, prime or 00773 * not) has never been adequately explained. 00774 */ 00775 hash = 5381; 00776 for (cp = name, hash = 0; *cp; cp++) 00777 hash = ((hash << 5) + hash) + (*cp & 0xff); /* hash * 33 + c */ 00778 hash %= HASH_SIZE; 00779 00780 for (e = cache->colors[hash]; e; e = e->next) 00781 if (strcmp (e->name, name) == 0) 00782 { 00783 copy_color (set, &(e->val), val); 00784 cache->lru = e; 00785 return 1; 00786 } 00787 if (!set) 00788 return 0; 00789 00790 e = (ecache *) malloc (sizeof (ecache)); 00791 e->next = cache->colors[hash]; 00792 cache->colors[hash] = e; 00793 e->name = strdup (name); 00794 memcpy (&(e->val), val, sizeof (hidval)); 00795 cache->lru = e; 00796 00797 return 1; 00798 } 00799 00800 /* otherwise homeless function, refactored out of the five export HIDs */ 00801 void 00802 derive_default_filename(const char *pcbfile, HID_Attribute *filename_attrib, const char *suffix, char **memory) 00803 { 00804 char *buf; 00805 char *pf; 00806 00807 if (pcbfile == NULL) 00808 pf = strdup ("unknown.pcb"); 00809 else 00810 pf = strdup (pcbfile); 00811 00812 if (!pf || (memory && filename_attrib->default_val.str_value != *memory)) return; 00813 00814 buf = (char *)malloc (strlen (pf) + strlen(suffix) + 1); 00815 if (memory) *memory = buf; 00816 if (buf) { 00817 size_t bl; 00818 strcpy (buf, pf); 00819 bl = strlen(buf); 00820 if (bl > 4 && strcmp (buf + bl - 4, ".pcb") == 0) 00821 buf[bl - 4] = 0; 00822 strcat(buf, suffix); 00823 if (filename_attrib->default_val.str_value) 00824 free ((void *) filename_attrib->default_val.str_value); 00825 filename_attrib->default_val.str_value = buf; 00826 } 00827 00828 free (pf); 00829 }