1181834Sroberto 2280849Scy/** 3280849Scy * \file load.c 4181834Sroberto * 5181834Sroberto * This file contains the routines that deal with processing text strings 6181834Sroberto * for options, either from a NUL-terminated string passed in or from an 7181834Sroberto * rc/ini file. 8280849Scy * 9280849Scy * @addtogroup autoopts 10280849Scy * @{ 11181834Sroberto */ 12181834Sroberto/* 13280849Scy * This file is part of AutoOpts, a companion to AutoGen. 14280849Scy * AutoOpts is free software. 15285169Scy * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved 16181834Sroberto * 17280849Scy * AutoOpts is available under any one of two licenses. The license 18280849Scy * in use must be one of these two and the choice is under the control 19280849Scy * of the user of the license. 20181834Sroberto * 21280849Scy * The GNU Lesser General Public License, version 3 or later 22280849Scy * See the files "COPYING.lgplv3" and "COPYING.gplv3" 23181834Sroberto * 24280849Scy * The Modified Berkeley Software Distribution License 25280849Scy * See the file "COPYING.mbsd" 26181834Sroberto * 27280849Scy * These files have the following sha256 sums: 28181834Sroberto * 29280849Scy * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 30280849Scy * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 31280849Scy * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd 32181834Sroberto */ 33181834Sroberto 34181834Sroberto/* = = = START-STATIC-FORWARD = = = */ 35280849Scystatic bool 36280849Scyget_realpath(char * buf, size_t b_sz); 37181834Sroberto 38280849Scystatic bool 39280849Scyadd_prog_path(char * buf, int b_sz, char const * fname, char const * prg_path); 40181834Sroberto 41280849Scystatic bool 42280849Scyadd_env_val(char * buf, int buf_sz, char const * name); 43280849Scy 44280849Scystatic char * 45280849Scyassemble_arg_val(char * txt, tOptionLoadMode mode); 46280849Scy 47280849Scystatic char * 48280849Scytrim_quotes(char * arg); 49280849Scy 50280849Scystatic bool 51280849Scydirection_ok(opt_state_mask_t f, int dir); 52181834Sroberto/* = = = END-STATIC-FORWARD = = = */ 53181834Sroberto 54280849Scystatic bool 55280849Scyget_realpath(char * buf, size_t b_sz) 56280849Scy{ 57280849Scy#if defined(HAVE_CANONICALIZE_FILE_NAME) 58280849Scy { 59280849Scy size_t name_len; 60280849Scy 61280849Scy char * pz = canonicalize_file_name(buf); 62280849Scy if (pz == NULL) 63280849Scy return false; 64280849Scy 65280849Scy name_len = strlen(pz); 66280849Scy if (name_len >= (size_t)b_sz) { 67280849Scy free(pz); 68280849Scy return false; 69280849Scy } 70280849Scy 71280849Scy memcpy(buf, pz, name_len + 1); 72280849Scy free(pz); 73280849Scy } 74280849Scy 75280849Scy#elif defined(HAVE_REALPATH) 76280849Scy { 77280849Scy size_t name_len; 78280849Scy char z[PATH_MAX+1]; 79280849Scy 80280849Scy if (realpath(buf, z) == NULL) 81280849Scy return false; 82280849Scy 83280849Scy name_len = strlen(z); 84280849Scy if (name_len >= b_sz) 85280849Scy return false; 86280849Scy 87280849Scy memcpy(buf, z, name_len + 1); 88280849Scy } 89280849Scy#endif 90280849Scy return true; 91280849Scy} 92280849Scy 93181834Sroberto/*=export_func optionMakePath 94181834Sroberto * private: 95181834Sroberto * 96181834Sroberto * what: translate and construct a path 97285169Scy * arg: + char * + p_buf + The result buffer + 98285169Scy * arg: + int + b_sz + The size of this buffer + 99285169Scy * arg: + char const * + fname + The input name + 100285169Scy * arg: + char const * + prg_path + The full path of the current program + 101181834Sroberto * 102280849Scy * ret-type: bool 103280849Scy * ret-desc: true if the name was handled, otherwise false. 104181834Sroberto * If the name does not start with ``$'', then it is handled 105181834Sroberto * simply by copying the input name to the output buffer and 106280849Scy * resolving the name with either 107280849Scy * @code{canonicalize_file_name(3GLIBC)} or @code{realpath(3C)}. 108181834Sroberto * 109181834Sroberto * doc: 110181834Sroberto * 111280849Scy * This routine will copy the @code{pzName} input name into the 112280849Scy * @code{pzBuf} output buffer, not exceeding @code{bufSize} bytes. If the 113181834Sroberto * first character of the input name is a @code{'$'} character, then there 114181834Sroberto * is special handling: 115181834Sroberto * @* 116181834Sroberto * @code{$$} is replaced with the directory name of the @code{pzProgPath}, 117181834Sroberto * searching @code{$PATH} if necessary. 118181834Sroberto * @* 119181834Sroberto * @code{$@} is replaced with the AutoGen package data installation directory 120181834Sroberto * (aka @code{pkgdatadir}). 121181834Sroberto * @* 122181834Sroberto * @code{$NAME} is replaced by the contents of the @code{NAME} environment 123181834Sroberto * variable. If not found, the search fails. 124181834Sroberto * 125181834Sroberto * Please note: both @code{$$} and @code{$NAME} must be at the start of the 126181834Sroberto * @code{pzName} string and must either be the entire string or be followed 127181834Sroberto * by the @code{'/'} (backslash on windows) character. 128181834Sroberto * 129280849Scy * err: @code{false} is returned if: 130181834Sroberto * @* 131181834Sroberto * @bullet{} The input name exceeds @code{bufSize} bytes. 132181834Sroberto * @* 133181834Sroberto * @bullet{} @code{$$}, @code{$@@} or @code{$NAME} is not the full string 134181834Sroberto * and the next character is not '/'. 135181834Sroberto * @* 136181834Sroberto * @bullet{} libopts was built without PKGDATADIR defined and @code{$@@} 137181834Sroberto * was specified. 138181834Sroberto * @* 139181834Sroberto * @bullet{} @code{NAME} is not a known environment variable 140181834Sroberto * @* 141181834Sroberto * @bullet{} @code{canonicalize_file_name} or @code{realpath} return 142181834Sroberto * errors (cannot resolve the resulting path). 143181834Sroberto=*/ 144280849Scybool 145280849ScyoptionMakePath(char * p_buf, int b_sz, char const * fname, char const * prg_path) 146181834Sroberto{ 147280849Scy { 148280849Scy size_t len = strlen(fname); 149181834Sroberto 150280849Scy if (((size_t)b_sz <= len) || (len == 0)) 151280849Scy return false; 152280849Scy } 153181834Sroberto 154181834Sroberto /* 155181834Sroberto * IF not an environment variable, just copy the data 156181834Sroberto */ 157280849Scy if (*fname != '$') { 158280849Scy char const * src = fname; 159280849Scy char * dst = p_buf; 160280849Scy int ct = b_sz; 161181834Sroberto 162181834Sroberto for (;;) { 163280849Scy if ( (*(dst++) = *(src++)) == NUL) 164181834Sroberto break; 165181834Sroberto if (--ct <= 0) 166280849Scy return false; 167181834Sroberto } 168181834Sroberto } 169181834Sroberto 170181834Sroberto /* 171181834Sroberto * IF the name starts with "$$", then it must be "$$" or 172181834Sroberto * it must start with "$$/". In either event, replace the "$$" 173181834Sroberto * with the path to the executable and append a "/" character. 174181834Sroberto */ 175280849Scy else switch (fname[1]) { 176181834Sroberto case NUL: 177280849Scy return false; 178181834Sroberto 179181834Sroberto case '$': 180280849Scy if (! add_prog_path(p_buf, b_sz, fname, prg_path)) 181280849Scy return false; 182181834Sroberto break; 183181834Sroberto 184181834Sroberto case '@': 185280849Scy if (program_pkgdatadir[0] == NUL) 186280849Scy return false; 187181834Sroberto 188280849Scy if (snprintf(p_buf, (size_t)b_sz, "%s%s", 189280849Scy program_pkgdatadir, fname + 2) >= b_sz) 190280849Scy return false; 191181834Sroberto break; 192181834Sroberto 193181834Sroberto default: 194280849Scy if (! add_env_val(p_buf, b_sz, fname)) 195280849Scy return false; 196181834Sroberto } 197181834Sroberto 198280849Scy return get_realpath(p_buf, b_sz); 199181834Sroberto} 200181834Sroberto 201280849Scy/** 202280849Scy * convert a leading "$$" into a path to the executable. 203280849Scy */ 204280849Scystatic bool 205280849Scyadd_prog_path(char * buf, int b_sz, char const * fname, char const * prg_path) 206181834Sroberto{ 207280849Scy char const * path; 208280849Scy char const * pz; 209181834Sroberto int skip = 2; 210181834Sroberto 211280849Scy switch (fname[2]) { 212181834Sroberto case DIRCH: 213181834Sroberto skip = 3; 214181834Sroberto case NUL: 215181834Sroberto break; 216181834Sroberto default: 217280849Scy return false; 218181834Sroberto } 219181834Sroberto 220181834Sroberto /* 221181834Sroberto * See if the path is included in the program name. 222181834Sroberto * If it is, we're done. Otherwise, we have to hunt 223181834Sroberto * for the program using "pathfind". 224181834Sroberto */ 225280849Scy if (strchr(prg_path, DIRCH) != NULL) 226280849Scy path = prg_path; 227181834Sroberto else { 228294554Sdelphij path = pathfind(getenv("PATH"), prg_path, "rx"); 229181834Sroberto 230280849Scy if (path == NULL) 231280849Scy return false; 232181834Sroberto } 233181834Sroberto 234280849Scy pz = strrchr(path, DIRCH); 235181834Sroberto 236181834Sroberto /* 237181834Sroberto * IF we cannot find a directory name separator, 238181834Sroberto * THEN we do not have a path name to our executable file. 239181834Sroberto */ 240181834Sroberto if (pz == NULL) 241280849Scy return false; 242181834Sroberto 243280849Scy fname += skip; 244181834Sroberto 245181834Sroberto /* 246181834Sroberto * Concatenate the file name to the end of the executable path. 247181834Sroberto * The result may be either a file or a directory. 248181834Sroberto */ 249280849Scy if ((unsigned)(pz - path) + 1 + strlen(fname) >= (unsigned)b_sz) 250280849Scy return false; 251181834Sroberto 252280849Scy memcpy(buf, path, (size_t)((pz - path)+1)); 253280849Scy strcpy(buf + (pz - path) + 1, fname); 254181834Sroberto 255181834Sroberto /* 256280849Scy * If the "path" path was gotten from "pathfind()", then it was 257181834Sroberto * allocated and we need to deallocate it. 258181834Sroberto */ 259280849Scy if (path != prg_path) 260280849Scy AGFREE(path); 261280849Scy return true; 262181834Sroberto} 263181834Sroberto 264280849Scy/** 265280849Scy * Add an environment variable value. 266280849Scy */ 267280849Scystatic bool 268280849Scyadd_env_val(char * buf, int buf_sz, char const * name) 269181834Sroberto{ 270280849Scy char * dir_part = buf; 271181834Sroberto 272181834Sroberto for (;;) { 273280849Scy int ch = (int)*++name; 274280849Scy if (! IS_VALUE_NAME_CHAR(ch)) 275181834Sroberto break; 276280849Scy *(dir_part++) = (char)ch; 277181834Sroberto } 278181834Sroberto 279280849Scy if (dir_part == buf) 280280849Scy return false; 281181834Sroberto 282280849Scy *dir_part = NUL; 283181834Sroberto 284280849Scy dir_part = getenv(buf); 285181834Sroberto 286181834Sroberto /* 287181834Sroberto * Environment value not found -- skip the home list entry 288181834Sroberto */ 289280849Scy if (dir_part == NULL) 290280849Scy return false; 291181834Sroberto 292280849Scy if (strlen(dir_part) + 1 + strlen(name) >= (unsigned)buf_sz) 293280849Scy return false; 294181834Sroberto 295280849Scy sprintf(buf, "%s%s", dir_part, name); 296280849Scy return true; 297181834Sroberto} 298181834Sroberto 299280849Scy/** 300280849Scy * Trim leading and trailing white space. 301280849Scy * If we are cooking the text and the text is quoted, then "cook" 302280849Scy * the string. To cook, the string must be quoted. 303280849Scy * 304280849Scy * @param[in,out] txt the input and output string 305280849Scy * @param[in] mode the handling mode (cooking method) 306280849Scy */ 307181834SrobertoLOCAL void 308280849Scymunge_str(char * txt, tOptionLoadMode mode) 309181834Sroberto{ 310280849Scy char * pzE; 311181834Sroberto 312181834Sroberto if (mode == OPTION_LOAD_KEEP) 313181834Sroberto return; 314181834Sroberto 315280849Scy if (IS_WHITESPACE_CHAR(*txt)) { 316280849Scy char * src = SPN_WHITESPACE_CHARS(txt+1); 317280849Scy size_t l = strlen(src) + 1; 318280849Scy memmove(txt, src, l); 319280849Scy pzE = txt + l - 1; 320280849Scy 321181834Sroberto } else 322280849Scy pzE = txt + strlen(txt); 323181834Sroberto 324280849Scy pzE = SPN_WHITESPACE_BACK(txt, pzE); 325181834Sroberto *pzE = NUL; 326181834Sroberto 327181834Sroberto if (mode == OPTION_LOAD_UNCOOKED) 328181834Sroberto return; 329181834Sroberto 330280849Scy switch (*txt) { 331181834Sroberto default: return; 332181834Sroberto case '"': 333181834Sroberto case '\'': break; 334181834Sroberto } 335181834Sroberto 336181834Sroberto switch (pzE[-1]) { 337181834Sroberto default: return; 338181834Sroberto case '"': 339181834Sroberto case '\'': break; 340181834Sroberto } 341181834Sroberto 342280849Scy (void)ao_string_cook(txt, NULL); 343181834Sroberto} 344181834Sroberto 345280849Scystatic char * 346280849Scyassemble_arg_val(char * txt, tOptionLoadMode mode) 347181834Sroberto{ 348280849Scy char * end = strpbrk(txt, ARG_BREAK_STR); 349280849Scy int space_break; 350181834Sroberto 351181834Sroberto /* 352181834Sroberto * Not having an argument to a configurable name is okay. 353181834Sroberto */ 354280849Scy if (end == NULL) 355280849Scy return txt + strlen(txt); 356181834Sroberto 357181834Sroberto /* 358181834Sroberto * If we are keeping all whitespace, then the modevalue starts with the 359181834Sroberto * character that follows the end of the configurable name, regardless 360181834Sroberto * of which character caused it. 361181834Sroberto */ 362181834Sroberto if (mode == OPTION_LOAD_KEEP) { 363280849Scy *(end++) = NUL; 364280849Scy return end; 365181834Sroberto } 366181834Sroberto 367181834Sroberto /* 368181834Sroberto * If the name ended on a white space character, remember that 369181834Sroberto * because we'll have to skip over an immediately following ':' or '=' 370181834Sroberto * (and the white space following *that*). 371181834Sroberto */ 372280849Scy space_break = IS_WHITESPACE_CHAR(*end); 373280849Scy *(end++) = NUL; 374181834Sroberto 375280849Scy end = SPN_WHITESPACE_CHARS(end); 376280849Scy if (space_break && ((*end == ':') || (*end == '='))) 377280849Scy end = SPN_WHITESPACE_CHARS(end+1); 378280849Scy 379280849Scy return end; 380181834Sroberto} 381181834Sroberto 382280849Scystatic char * 383280849Scytrim_quotes(char * arg) 384280849Scy{ 385280849Scy switch (*arg) { 386280849Scy case '"': 387280849Scy case '\'': 388280849Scy ao_string_cook(arg, NULL); 389280849Scy } 390280849Scy return arg; 391280849Scy} 392181834Sroberto 393280849Scy/** 394280849Scy * See if the option is to be processed in the current scan direction 395280849Scy * (-1 or +1). 396181834Sroberto */ 397280849Scystatic bool 398280849Scydirection_ok(opt_state_mask_t f, int dir) 399181834Sroberto{ 400280849Scy if (dir == 0) 401280849Scy return true; 402181834Sroberto 403280849Scy switch (f & (OPTST_IMM|OPTST_DISABLE_IMM)) { 404181834Sroberto case 0: 405181834Sroberto /* 406181834Sroberto * The selected option has no immediate action. 407181834Sroberto * THEREFORE, if the direction is PRESETTING 408181834Sroberto * THEN we skip this option. 409181834Sroberto */ 410280849Scy if (PRESETTING(dir)) 411280849Scy return false; 412181834Sroberto break; 413181834Sroberto 414181834Sroberto case OPTST_IMM: 415280849Scy if (PRESETTING(dir)) { 416181834Sroberto /* 417181834Sroberto * We are in the presetting direction with an option we handle 418181834Sroberto * immediately for enablement, but normally for disablement. 419181834Sroberto * Therefore, skip if disabled. 420181834Sroberto */ 421280849Scy if ((f & OPTST_DISABLED) == 0) 422280849Scy return false; 423181834Sroberto } else { 424181834Sroberto /* 425181834Sroberto * We are in the processing direction with an option we handle 426181834Sroberto * immediately for enablement, but normally for disablement. 427181834Sroberto * Therefore, skip if NOT disabled. 428181834Sroberto */ 429280849Scy if ((f & OPTST_DISABLED) != 0) 430280849Scy return false; 431181834Sroberto } 432181834Sroberto break; 433181834Sroberto 434181834Sroberto case OPTST_DISABLE_IMM: 435280849Scy if (PRESETTING(dir)) { 436181834Sroberto /* 437181834Sroberto * We are in the presetting direction with an option we handle 438181834Sroberto * immediately for disablement, but normally for disablement. 439181834Sroberto * Therefore, skip if NOT disabled. 440181834Sroberto */ 441280849Scy if ((f & OPTST_DISABLED) != 0) 442280849Scy return false; 443181834Sroberto } else { 444181834Sroberto /* 445181834Sroberto * We are in the processing direction with an option we handle 446181834Sroberto * immediately for disablement, but normally for disablement. 447181834Sroberto * Therefore, skip if disabled. 448181834Sroberto */ 449280849Scy if ((f & OPTST_DISABLED) == 0) 450280849Scy return false; 451181834Sroberto } 452181834Sroberto break; 453181834Sroberto 454181834Sroberto case OPTST_IMM|OPTST_DISABLE_IMM: 455181834Sroberto /* 456181834Sroberto * The selected option is always for immediate action. 457181834Sroberto * THEREFORE, if the direction is PROCESSING 458181834Sroberto * THEN we skip this option. 459181834Sroberto */ 460280849Scy if (PROCESSING(dir)) 461280849Scy return false; 462181834Sroberto break; 463181834Sroberto } 464280849Scy return true; 465280849Scy} 466181834Sroberto 467280849Scy/** 468280849Scy * Load an option from a block of text. The text must start with the 469280849Scy * configurable/option name and be followed by its associated value. 470280849Scy * That value may be processed in any of several ways. See "tOptionLoadMode" 471280849Scy * in autoopts.h. 472280849Scy * 473280849Scy * @param[in,out] opts program options descriptor 474280849Scy * @param[in,out] opt_state option processing state 475280849Scy * @param[in,out] line source line with long option name in it 476280849Scy * @param[in] direction current processing direction (preset or not) 477280849Scy * @param[in] load_mode option loading mode (OPTION_LOAD_*) 478280849Scy */ 479280849ScyLOCAL void 480280849Scyload_opt_line(tOptions * opts, tOptState * opt_state, char * line, 481280849Scy tDirection direction, tOptionLoadMode load_mode ) 482280849Scy{ 483181834Sroberto /* 484280849Scy * When parsing a stored line, we only look at the characters after 485280849Scy * a hyphen. Long names must always be at least two characters and 486280849Scy * short options are always exactly one character long. 487280849Scy */ 488280849Scy line = SPN_LOAD_LINE_SKIP_CHARS(line); 489280849Scy 490280849Scy { 491280849Scy char * arg = assemble_arg_val(line, load_mode); 492280849Scy 493280849Scy if (IS_OPTION_NAME_CHAR(line[1])) { 494280849Scy 495280849Scy if (! SUCCESSFUL(opt_find_long(opts, line, opt_state))) 496280849Scy return; 497280849Scy 498280849Scy } else if (! SUCCESSFUL(opt_find_short(opts, *line, opt_state))) 499280849Scy return; 500280849Scy 501280849Scy if ((! CALLED(direction)) && (opt_state->flags & OPTST_NO_INIT)) 502280849Scy return; 503280849Scy 504280849Scy opt_state->pzOptArg = trim_quotes(arg); 505280849Scy } 506280849Scy 507280849Scy if (! direction_ok(opt_state->flags, direction)) 508280849Scy return; 509280849Scy 510280849Scy /* 511181834Sroberto * Fix up the args. 512181834Sroberto */ 513280849Scy if (OPTST_GET_ARGTYPE(opt_state->pOD->fOptState) == OPARG_TYPE_NONE) { 514280849Scy if (*opt_state->pzOptArg != NUL) 515181834Sroberto return; 516280849Scy opt_state->pzOptArg = NULL; 517181834Sroberto 518280849Scy } else if (opt_state->pOD->fOptState & OPTST_ARG_OPTIONAL) { 519280849Scy if (*opt_state->pzOptArg == NUL) 520280849Scy opt_state->pzOptArg = NULL; 521181834Sroberto else { 522280849Scy AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg"); 523280849Scy opt_state->flags |= OPTST_ALLOC_ARG; 524181834Sroberto } 525181834Sroberto 526181834Sroberto } else { 527280849Scy if (*opt_state->pzOptArg == NUL) 528280849Scy opt_state->pzOptArg = zNil; 529181834Sroberto else { 530280849Scy AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg"); 531280849Scy opt_state->flags |= OPTST_ALLOC_ARG; 532181834Sroberto } 533181834Sroberto } 534181834Sroberto 535181834Sroberto { 536181834Sroberto tOptionLoadMode sv = option_load_mode; 537181834Sroberto option_load_mode = load_mode; 538280849Scy handle_opt(opts, opt_state); 539181834Sroberto option_load_mode = sv; 540181834Sroberto } 541181834Sroberto} 542181834Sroberto 543181834Sroberto/*=export_func optionLoadLine 544181834Sroberto * 545181834Sroberto * what: process a string for an option name and value 546181834Sroberto * 547285169Scy * arg: tOptions *, opts, program options descriptor 548285169Scy * arg: char const *, line, NUL-terminated text 549181834Sroberto * 550181834Sroberto * doc: 551181834Sroberto * 552181834Sroberto * This is a client program callable routine for setting options from, for 553181834Sroberto * example, the contents of a file that they read in. Only one option may 554181834Sroberto * appear in the text. It will be treated as a normal (non-preset) option. 555181834Sroberto * 556181834Sroberto * When passed a pointer to the option struct and a string, it will find 557181834Sroberto * the option named by the first token on the string and set the option 558181834Sroberto * argument to the remainder of the string. The caller must NUL terminate 559280849Scy * the string. The caller need not skip over any introductory hyphens. 560280849Scy * Any embedded new lines will be included in the option 561181834Sroberto * argument. If the input looks like one or more quoted strings, then the 562181834Sroberto * input will be "cooked". The "cooking" is identical to the string 563181834Sroberto * formation used in AutoGen definition files (@pxref{basic expression}), 564181834Sroberto * except that you may not use backquotes. 565181834Sroberto * 566181834Sroberto * err: Invalid options are silently ignored. Invalid option arguments 567181834Sroberto * will cause a warning to print, but the function should return. 568181834Sroberto=*/ 569181834Srobertovoid 570280849ScyoptionLoadLine(tOptions * opts, char const * line) 571181834Sroberto{ 572181834Sroberto tOptState st = OPTSTATE_INITIALIZER(SET); 573280849Scy char * pz; 574280849Scy proc_state_mask_t sv_flags = opts->fOptSet; 575280849Scy opts->fOptSet &= ~OPTPROC_ERRSTOP; 576280849Scy AGDUPSTR(pz, line, "opt line"); 577280849Scy load_opt_line(opts, &st, pz, DIRECTION_CALLED, OPTION_LOAD_COOKED); 578280849Scy AGFREE(pz); 579280849Scy opts->fOptSet = sv_flags; 580181834Sroberto} 581280849Scy/** @} 582280849Scy * 583181834Sroberto * Local Variables: 584181834Sroberto * mode: C 585181834Sroberto * c-file-style: "stroustrup" 586181834Sroberto * indent-tabs-mode: nil 587181834Sroberto * End: 588181834Sroberto * end of autoopts/load.c */ 589