/*================================================== * open_database -- open database * forceopen: [in] flag to override reader/writer protection * dbpath: [in] database path to open *================================================*/ BOOLEAN open_database (INT alteration, STRING dbpath, INT *lldberr) { LLDATABASE lldb = lldb_alloc(); BOOLEAN rtn = FALSE; char fpath[MAXPATHLEN]; /* tentatively copy paths into gedlib module versions */ strupdate(&readpath_file, lastpathname(dbpath)); llstrncpy(fpath, dbpath, sizeof(fpath), 0); expand_special_fname_chars(fpath, sizeof(fpath), uu8); strupdate(&readpath, fpath); if (f_dbnotify) (*f_dbnotify)(readpath, TRUE); rtn = open_database_impl(lldb, alteration, lldberr); if (!rtn) { /* open failed so clean up, preserve lldberr */ int myerr = *lldberr; lldb_close(&lldb); *lldberr = myerr; } def_lldb = lldb; return rtn; }
/*======================================+ * llrpt_newfile -- Switch output to new file * usage: newfile(STRING, BOOL) -> VOID *=====================================*/ PVALUE llrpt_newfile (PNODE node, SYMTAB stab, BOOLEAN *eflg) { PNODE argvar = builtin_args(node); BOOLEAN aflag=FALSE; STRING name=0; PVALUE val = eval_and_coerce(PSTRING, argvar, stab, eflg); if (*eflg) { prog_var_error(node, stab, argvar, val, nonstrx, "newfile", "1"); delete_pvalue_ptr(&val); return NULL; } name = pvalue_to_string(val); if (!name || !name[0]) { *eflg = TRUE; prog_var_error(node, stab, argvar, val, "1st arg to newfile must be a nonempty string."); delete_pvalue_ptr(&val); return NULL; } strupdate(&outfilename, name); delete_pvalue_ptr(&val); val = eval_and_coerce(PBOOL, argvar=inext(argvar), stab, eflg); if (*eflg) { prog_var_error(node, stab, argvar, val, nonboox, "newfile", "2"); delete_pvalue_ptr(&val); return NULL; } aflag = pvalue_to_bool(val); delete_pvalue_ptr(&val); if (!set_output_file(outfilename, aflag)) { *eflg = TRUE; prog_var_error(node, stab, argvar, NULL, "Failed to open output file: %s", outfilename); } return NULL; }
/*======================================+ * start_output_file -- Start outputing to specified file * (Closes any previously open output file) * Calls msg_error & returns FALSE, if problem *=====================================*/ BOOLEAN start_output_file (STRING outfname) { BOOLEAN append=FALSE; if (set_output_file(outfname, append)) { strupdate(&outfilename, outfname); return TRUE; } else { return FALSE; } }
/*================================================== * update_db_options -- * check database-specific options for updates *================================================*/ static void update_db_options (void) { TABLE opttab = create_table_str(); CNSTRING str=0; get_db_options(opttab); str = valueof_str(opttab, "codeset"); if (!str || !str[0]) { /* no specified database/internal codeset so default to user's default codeset, which should be from locale */ str = get_defcodeset(); } if (!int_codeset) strupdate(&int_codeset, ""); if (!eqstr_ex(int_codeset, str)) { /* database encoding changed */ strupdate(&int_codeset, str); /* Here is where the global uu8 variable is set This is a flag if the internal (database) encoding is UTF-8 */ uu8 = is_codeset_utf8(int_codeset); /* always translate to internal codeset */ set_gettext_codeset(PACKAGE, int_codeset); /* need to reload all predefined codeset conversions */ transl_load_xlats(); if (uu8) { charprops_load_utf8(); } else { charprops_load(int_codeset); } } destroy_table(opttab); }
/*=================================================== * update_useropts -- Set any global variables * dependent on user options *=================================================*/ void update_useropts (VPTR uparm) { uparm = uparm; /* unused */ if (suppress_reload) return; /* deal with db-specific options */ /* includes setting int_codeset */ if (def_lldb) update_db_options(); /* in case user changed any codesets */ init_codesets(); /* in case user changed locale (need int_codeset already set) */ uilocale(); /* in case user changed codesets */ /* TODO: Isn't this superfluous, as it was called in update_db_options above ? */ transl_load_xlats(); strupdate(&illegal_char, getlloptstr("IllegalChar", 0)); nodechk_enable(!!getlloptint("nodecheck", 0)); }
static FILE * ask_for_file_worker (STRING mode, STRING ttl, STRING *pfname, STRING *pfullpath, STRING path, STRING ext, DIRECTION direction) { FILE *fp; char prompt[MAXPATHLEN]; char fname[MAXPATHLEN]; int elen, flen; BOOLEAN rtn; make_fname_prompt(prompt, sizeof(prompt), ext); if (direction==INPUT) rtn = ask_for_input_filename(ttl, path, prompt, fname, sizeof(fname)); else rtn = ask_for_output_filename(ttl, path, prompt, fname, sizeof(fname)); if (pfname) { if (fname && fname[0]) *pfname = strdup(fname); else *pfname = 0; } if (pfullpath) *pfullpath = 0; /* 0 indicates we didn't try to open */ if (!rtn || !fname[0]) return NULL; if (!expand_special_fname_chars(fname, sizeof(fname), uu8)) { msg_error(_(qSfn2long)); return NULL; } ask_for_file_try: /* try name as given */ if (ISNULL(path)) { /* bare filename was given */ if ((fp = fopen(fname, mode)) != NULL) { if (pfname) strupdate(pfname, fname); return fp; } } else { /* fully qualified path was given */ if ((fp = fopenpath(fname, mode, path, ext, uu8, pfullpath)) != NULL) { return fp; } } /* try default extension */ if (ext) { elen = strlen(ext); flen = strlen(fname); if (elen<flen && path_match(fname+flen-elen, ext)) { ext = NULL; /* the file name has the extension already */ } else { /* add extension and go back and retry */ llstrapps(fname, sizeof(fname), uu8, ext); ext = NULL; /* only append extension once! */ goto ask_for_file_try; } } /* failed to open it, give up */ msg_error(_(qSnofopn), fname); return NULL; }
/*================================== * main -- Main routine of LifeLines *================================*/ int main (int argc, char **argv) { extern char *optarg; extern int optind; char * msg; int c; BOOLEAN ok=FALSE; STRING dbrequested=NULL; /* database (path) requested */ STRING dbused=NULL; /* database (path) found */ BOOLEAN forceopen=FALSE, lockchange=FALSE; char lockarg = 0; /* option passed for database lock */ INT alteration=0; LIST exprogs=NULL; TABLE exargs=NULL; STRING progout=NULL; BOOLEAN graphical=TRUE; STRING configfile=0; STRING crashlog=0; int i=0; /* initialize all the low-level library code */ init_stdlib(); #if HAVE_SETLOCALE /* initialize locales */ setlocale(LC_ALL, ""); #endif /* HAVE_SETLOCALE */ /* capture user's default codeset */ ext_codeset = strsave(ll_langinfo()); /* TODO: We can use this info for default conversions */ #if ENABLE_NLS /* setup gettext translation */ ll_bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif save_original_locales(); load_usage(); /* handle conventional arguments --version and --help */ /* needed for help2man to synthesize manual pages */ for (i=1; i<argc; ++i) { if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v")) { print_version("llexec"); return 0; } if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h") || !strcmp(argv[i], "-?")) { print_usage(); return 0; } } /* Parse Command-Line Arguments */ opterr = 0; /* turn off getopt's error message */ while ((c = getopt(argc, argv, "adkrwil:fntc:Fu:x:o:zC:I:vh?")) != -1) { switch (c) { case 'c': /* adjust cache sizes */ while(optarg && *optarg) { if(isasciiletter((uchar)*optarg) && isupper((uchar)*optarg)) *optarg = tolower((uchar)*optarg); if(*optarg == 'i') { INT icsz_indi=0; sscanf(optarg+1, "%ld,%ld", &csz_indi, &icsz_indi); } else if(*optarg == 'f') { INT icsz_fam=0; sscanf(optarg+1, "%ld,%ld", &csz_fam, &icsz_fam); } else if(*optarg == 's') { INT icsz_sour=0; sscanf(optarg+1, "%ld,%ld", &csz_sour, &icsz_sour); } else if(*optarg == 'e') { INT icsz_even=0; sscanf(optarg+1, "%ld,%ld", &csz_even, &icsz_even); } else if((*optarg == 'o') || (*optarg == 'x')) { INT icsz_othr=0; sscanf(optarg+1, "%ld,%ld", &csz_othr, &icsz_othr); } optarg++; while(*optarg && isdigit((uchar)*optarg)) optarg++; if(*optarg == ',') optarg++; while(*optarg && isdigit((uchar)*optarg)) optarg++; } break; #ifdef FINNISH # ifdef FINNISHOPTION case 'F': /* Finnish sorting order [toggle] */ opt_finnish = !opt_finnish; /* TO DO - need to mark Finnish databases, as name records are not interoperable, because of different soundex encoding 2001/02/17, Perry Rapp */ break; # endif #endif case 'a': /* debug allocation */ alloclog = TRUE; break; case 'd': /* debug = no signal catchers */ debugmode = TRUE; break; case 'k': /* don't show key values */ keyflag = FALSE; break; case 'r': /* request for read only access */ readonly = TRUE; break; case 'w': /* request for write access */ writeable = TRUE; break; case 'i': /* immutable access */ immutable = TRUE; readonly = TRUE; break; case 'l': /* locking switch */ lockchange = TRUE; lockarg = *optarg; break; case 'f': /* force database open in all cases */ forceopen = TRUE; break; case 'n': /* use non-traditional family rules */ traditional = FALSE; break; case 't': /* show lots of trace statements for debugging */ prog_trace = TRUE; break; case 'x': /* execute program */ if (!exprogs) { exprogs = create_list2(LISTDOFREE); } push_list(exprogs, strdup(optarg ? optarg : "")); break; case 'I': /* program arguments */ { STRING optname=0, optval=0; parse_arg(optarg, &optname, &optval); if (optname && optval) { if (!exargs) { exargs = create_table_str(); } insert_table_str(exargs, optname, optval); } strfree(&optname); strfree(&optval); } break; case 'o': /* output directory */ progout = optarg; break; case 'z': /* nongraphical box */ graphical = FALSE; break; case 'C': /* specify config file */ configfile = optarg; break; case 'v': /* show version */ showversion = TRUE; goto usage; break; case 'h': /* show usage */ case '?': /* show usage */ showversion = TRUE; showusage = TRUE; goto usage; break; } } prompt_for_db: /* catch any fault, so we can close database */ if (debugmode) stdstring_hardfail(); else set_signals(); platform_init(); set_displaykeys(keyflag); /* initialize options & misc. stuff */ llgettext_set_default_localedir(LOCALEDIR); if (!init_lifelines_global(configfile, &msg, &main_db_notify)) { llwprintf("%s", msg); goto finish; } /* setup crashlog in case init_screen fails (eg, bad menu shortcuts) */ crashlog = getlloptstr("CrashLog_llexec", NULL); if (!crashlog) { crashlog = "Crashlog_llexec.log"; } crash_setcrashlog(crashlog); init_interpreter(); /* give interpreter its turn at initialization */ /* Validate Command-Line Arguments */ if ((readonly || immutable) && writeable) { llwprintf(_(qSnorwandro)); goto finish; } if (forceopen && lockchange) { llwprintf(_(qSnofandl)); goto finish; } if (lockchange && lockarg != 'y' && lockarg != 'n') { llwprintf(_(qSbdlkar)); goto finish; } if (forceopen) alteration = 3; else if (lockchange) { if (lockarg == 'y') alteration = 2; else alteration = 1; } c = argc - optind; if (c > 1) { showusage = TRUE; goto usage; } /* Open database, prompting user if necessary */ if (1) { STRING errmsg=0; if (!alldone && c>0) { dbrequested = strsave(argv[optind]); } else { strupdate(&dbrequested, ""); } if (!select_database(dbrequested, alteration, &errmsg)) { if (errmsg) { llwprintf(errmsg); } alldone = 0; goto finish; } } /* Start Program */ if (!init_lifelines_postdb()) { llwprintf(_(qSbaddb)); goto finish; } /* does not use show module */ /* does not use browse module */ if (exargs) { set_cmd_options(exargs); release_table(exargs); exargs = 0; } if (exprogs) { BOOLEAN picklist = FALSE; BOOLEAN timing = FALSE; interp_main(exprogs, progout, picklist, timing); destroy_list(exprogs); } else { /* TODO: prompt for report filename */ } /* does not use show module */ /* does not use browse module */ ok=TRUE; finish: /* we free this not because we care so much about these tiny amounts of memory, but to ensure we have the memory management right */ /* strfree frees memory & nulls pointer */ if (dbused) strfree(&dbused); strfree(&dbrequested); strfree(&readpath_file); shutdown_interpreter(); close_lifelines(); shutdown_ui(!ok); if (alldone == 2) goto prompt_for_db; /* changing databases */ termlocale(); strfree(&ext_codeset); usage: /* Display Version and/or Command-Line Usage Help */ if (showversion) { print_version("llexec"); } if (showusage) puts(usage_summary); /* Exit */ return !ok; }
/**==========================================================================**\ ** M A IN \**==========================================================================**/ int main ( int argc, char *argv[] ) { param_t param ; npc_t *npc = NULL ; ProgramName = *argv++ ; --argc ; param_default( ¶m ); while( argv[0] && argv[1] && argv[0][0]=='-' ) { switch( argv[0][1] ) { case 'n': param.seedNumber= argv[1]; break; case 'm': param.maxDigits = atoi( argv[1] ); break; case 'b': param.baseNumber= atoi( argv[1] ); break; case 'a': param.savePeriod= atoi( argv[1] ); break; case 'i': strupdate(&(param.loadFile), argv[1] ); break; case 'o': strupdate(&(param.saveFile), argv[1] ); break; case 'v': param.help |= PARAM_VERSION ; param_usage( ¶m ) ; default : fprintf( stderr, "unknown option: '%c'\n" ); param_usage( ¶m ); } param.numParams ++ ; argc -= 2 ; argv += 2 ; } param_verify( ¶m ); if( (npc = npc_new( param.maxDigits )) == NULL ) { fprintf( stderr, "err npc_new\n" ); return( 0 ); } npc->base = param.baseNumber ; if( param.loadFile ) { if( !npc_loadFile( npc, param.loadFile ) ) return( 0 ); } else { if( !npc_string_ingest( npc, param.seedNumber ) ) { fprintf( stderr, "err loading seedNumber\n" ); return( 0 ); } else npc->origSeed = atoi( param.seedNumber ) ; } copywrite() ; npc_loop( npc ) ; printf( "\n" "Progress: %%%6.2f Digits: %7d Its: %8d Secs: %6u\n" , 100. * npc->numDigits / npc->maxDigits , npc->numDigits , npc->iterates , npc->timeMark - npc->timeInit ) ; if( param.saveFile ) npc_saveFile( npc, param.saveFile ) ; return 0; }
/*================================================= * do_import -- Read GEDCOM file to database * ifeed: [IN] output methods * fp: [I/O] GEDCOM file whence to load data *===============================================*/ static BOOLEAN do_import (IMPORT_FEEDBACK ifeed, FILE *fp) { NODE node, conv; XLAT ttm = 0; STRING msg; BOOLEAN emp; INT nindi = 0, nfam = 0, neven = 0; INT nsour = 0, nothr = 0, type, num = 0; INT totkeys = 0, totused = 0; char msgbuf[80]; BOOLEAN succeeded=FALSE; STRING str,unistr=0; ZSTR zerr=0; TABLE metadatatab = create_table_str(); STRING gdcodeset=0; INT warnings=0; /* start by assuming default */ strupdate(&gdcodeset, gedcom_codeset_in); /* rptui_init(); *//* clear ui time counter */ /* Open and validate GEDCOM file */ if ((unistr=check_file_for_unicode(fp)) && !eqstr(unistr, "UTF-8")) { msg_error(_(qSunsupuniv), unistr); goto end_import; } if (eqstr_ex(unistr, "UTF-8")) { strupdate(&gdcodeset, "UTF-8"); } if (!scan_header(fp, metadatatab, &zerr)) { msg_error(zs_str(zerr)); goto end_import; } if ((str = valueof_str(metadatatab, "GEDC.FORM"))!= NULL) { if (!eqstr(str, "LINEAGE-LINKED")) { if (!ask_yes_or_no_msg( _("This is not a lineage linked GEDCOM file.") , _("Proceed anyway?") )) goto end_import; } } if (!unistr && (str = valueof_str(metadatatab, "CHAR"))!= NULL) { /* if no BOM, use file's declared encoding if present */ strupdate(&gdcodeset, str); } /* TODO: Push this codeset question down to after the validation, where we can know if the incoming file happened to really be all ASCII */ if (!int_codeset[0]) { /* TODO: ask if user would like to adopt codeset of incoming file, if we found it */ if (!ask_yes_or_no_msg( _("No current internal codeset, so no codeset conversion can be done") , _("Proceed without codeset conversion?") )) goto end_import; } /* Warn if lossy code conversion likely */ if (gdcodeset[0] && int_codeset[0]) { if (is_lossy_conversion(gdcodeset, int_codeset)) { ZSTR zstr=zs_new(); zs_setf(zstr, _("Lossy codeset conversion (from <%s> to <%s>) likely") , gdcodeset, int_codeset); if (!ask_yes_or_no_msg( zs_str(zstr) , _("Proceed anyway?") )) goto end_import; } } /* validate */ if (ifeed && ifeed->validating_fnc) (*ifeed->validating_fnc)(); if (!validate_gedcom(ifeed, fp)) { if (ifeed && ifeed->error_invalid_fnc) (*ifeed->error_invalid_fnc)(_(qSgdnadd)); goto end_import; } warnings = validate_get_warning_count(); if (warnings) { ZSTR zstr=zs_new(); zs_setf(zstr, _pl("%d warning during import", "%d warnings during import", warnings), warnings); if (!ask_yes_or_no_msg(zs_str(zstr), _(qSproceed))) { goto end_import; } } if (gdcodeset[0] && int_codeset[0]) { retry_input_codeset: ttm = transl_get_xlat(gdcodeset, int_codeset); if (!transl_is_xlat_valid(ttm)) { ZSTR zstr=zs_new(); char csname[64]; BOOLEAN b; transl_release_xlat(ttm); ttm = 0; zs_setf(zstr, _("Cannot convert codeset (from <%s> to <%s>)") , gdcodeset, int_codeset); b = ask_for_string(zs_str(zstr) , _("Enter codeset to assume (* for none)") , csname, sizeof(csname)) && csname[0]; zs_free(&zstr); if (!b) goto end_import; if (!eqstr(csname, "*")) { strupdate(&gdcodeset, csname); goto retry_input_codeset; } } } if((num_indis() > 0) || (num_fams() > 0) || (num_sours() > 0) || (num_evens() > 0) || (num_othrs() > 0)) gd_reuse = FALSE; else if((gd_reuse = check_stdkeys())) { totused = gd_itot + gd_ftot + gd_stot + gd_etot + gd_xtot; totkeys = gd_imax + gd_fmax + gd_smax + gd_emax + gd_xmax; if((totkeys-totused) > 0) { INT delkeys = totkeys-totused; snprintf(msgbuf, sizeof(msgbuf) , _pl("Using original keys, %d deleted record will be in the database." , "Using original keys, %d deleted records will be in the database." , delkeys) , delkeys ); } else strcpy(msgbuf, " "); gd_reuse = ask_yes_or_no_msg(msgbuf, _(qScfoldk)); /* TODO: why were these here ? touchwin(uiw_win(stdout_win)); wrefresh(uiw_win(stdout_win)); */ } /* start loading the file */ rewind(fp); /* test for read-only database here */ if(readonly) { if (ifeed && ifeed->error_readonly_fnc) (*ifeed->error_readonly_fnc)(); goto end_import; } /* tell user we are beginning real part of import */ if (ifeed && ifeed->beginning_import_fnc) { if(gd_reuse) (*ifeed->beginning_import_fnc)(_(qSdboldk)); else (*ifeed->beginning_import_fnc)(_(qSdbnewk)); } /* Add records to database */ node = convert_first_fp_to_node(fp, FALSE, ttm, &msg, &emp); while (node) { if (!(conv = node_to_node(node, &type))) { free_nodes(node); node = next_fp_to_node(fp, FALSE, ttm, &msg, &emp); continue; } switch (type) { case INDI_REC: num = ++nindi; break; case FAM_REC: num = ++nfam; break; case EVEN_REC: num = ++neven; break; case SOUR_REC: num = ++nsour; break; case OTHR_REC: num = ++nothr; break; default: FATAL(); } restore_record(conv, type, num); if (ifeed && ifeed->added_rec_fnc) ifeed->added_rec_fnc(nxref(conv)[1], ntag(conv), num); free_nodes(node); node = next_fp_to_node(fp, FALSE, ttm, &msg, &emp); } if (msg) { msg_error(msg); } if(gd_reuse && ((totkeys - totused) > 0)) { if (ifeed && ifeed->adding_unused_keys_fnc) (*ifeed->adding_unused_keys_fnc)(); addmissingkeys(INDI_REC); addmissingkeys(FAM_REC); addmissingkeys(EVEN_REC); addmissingkeys(SOUR_REC); addmissingkeys(OTHR_REC); } succeeded = TRUE; end_import: validate_end_import(); zs_free(&zerr); destroy_table(metadatatab); strfree(&gdcodeset); return succeeded; }