static char *mkidx_pathname(char *dest, size_t size, const char *pathname, const char *suffix) { char *ext, *bn = NULL; int suffix_len; suffix_len = strlen(suffix); if (strlen(pathname) + suffix_len + 1 > size) return NULL; bn = n_basenam(pathname); if ((ext = strrchr(bn, '.')) == NULL || strcmp(ext, ".dir") == 0) { snprintf(dest, size, "%s%s", pathname, suffix); } else { int len = ext - pathname + 1; n_assert(len + suffix_len + strlen(ext) + 1 < size); n_strncpy(dest, pathname, len); strcat(dest, suffix); if (strstr(suffix, ext) == NULL) strcat(dest, ext); dest[size - 1] = '\0'; } return dest; }
static char *command_options_generator(const char *text, int state) { static tn_array *opts_table = NULL; if (state == 0) { struct poclidek_cmd *command = NULL; char *p, *e = NULL, line[64]; int i, len; p = rl_line_buffer; if ((e = strchr(p, ' ')) == NULL) return NULL; n_assert(e - p + 1 <= 64); n_strncpy(line, p, e - p + 1); for (i = 0; i < n_array_size(sh_ctx.cctx->commands); i++) { struct poclidek_cmd *cmd = n_array_nth(sh_ctx.cctx->commands, i); if (n_str_eq(cmd->name, line)) { if (cmd->aliasto) { struct poclidek_cmd tmpcmd; tmpcmd.name = cmd->aliasto; command = n_array_bsearch(sh_ctx.cctx->commands, &tmpcmd); } else { command = cmd; } break; } } if (command == NULL) return NULL; opts_table = n_array_new(4, NULL, (tn_fn_cmp)strcmp); len = strlen(&text[2]); for (i = 0; !option_is_end(&command->argp_opts[i]); i++) { const struct argp_option *argp_opt = &command->argp_opts[i]; /* skip hidden options */ if (argp_opt->flags & OPTION_HIDDEN) continue; if (argp_opt->name && strncmp(argp_opt->name, &text[2], len) == 0) { n_array_push(opts_table, (void *) argp_opt->name); } } n_array_sort(opts_table); } if (state >= n_array_size(opts_table)) { n_array_cfree(&opts_table); return NULL; } return n_str_concat("--", n_array_nth(opts_table, state), NULL); }
static zword smart_tokeniser(zword dictionarytable, const char *text, unsigned length, BOOL is_begin) { zword word_num = 0; unsigned tlength = (length < 12) ? length : 12; char tbuffer[13]; /* Letter replacements are tried in this order - */ const char fixmeletters[] = "abcdefghijklmnopqrstuvwxyz"; /* char fixmeletters[] = "etaonrishdlfcmugpywbvkxjqz"; */ word_num = find_word(dictionarytable, text, length); /* Some game files don't contain abbreviations for common commands */ if(!word_num && do_expand && length == 1 && is_begin) { const char * const abbrevs[26] = { "a", "b", "close", "down", "east", "f", "again", "h", "inventory", "j", "attack", "look", "m", "north", "oops", "open", "quit", "drop", "south", "take", "up", "v", "west", "examine", "yes", "wait" }; if('a' <= text[0] && text[0] <= 'z') { strcpy(tbuffer, abbrevs[text[0] - 'a']); tlength = strlen(tbuffer); word_num = find_word(dictionarytable, tbuffer, tlength); } } /* Check for various typing errors */ /* Don't attempt typo correction in very short words */ if(do_spell_correct && length >= 3) { if(!word_num) { /* Check for transposes */ /* To fix, try all possible transposes */ unsigned position; for(position = 1; position < tlength; position++) { unsigned s; for(s = 0; s < tlength; s++) tbuffer[s] = text[s]; tbuffer[position - 1] = text[position]; tbuffer[position] = text[position - 1]; word_num = find_word(dictionarytable, tbuffer, tlength); if(word_num) break; } } if(!word_num) { /* Check for deletions */ /* To fix, try all possible insertions */ unsigned position; for(position = 0; position <= tlength; position++) { unsigned s; for(s = 0; s < position; s++) /* letters before the insertion */ tbuffer[s] = text[s]; for(s = position; s < tlength; s++) /* after the insertion */ tbuffer[s + 1] = text[s]; /* try each letter */ for(s = 0; s < sizeof(fixmeletters); s++) { tbuffer[position] = fixmeletters[s]; word_num = find_word(dictionarytable, tbuffer, tlength + 1); if(word_num) break; } if(word_num) { tlength++; break; } } } if(!word_num) { /* Check for insertions */ /* To fix, try all possible deletions */ unsigned position; for(position = 0; position < tlength; position++) { unsigned s; for(s = 0; s < position; s++) /* letters before the deletion */ tbuffer[s] = text[s]; for(s = position + 1; s < tlength; s++) /* after the deletion */ tbuffer[s - 1] = text[s]; word_num = find_word(dictionarytable, tbuffer, tlength - 1); if(word_num) { tlength--; break; } } } if(!word_num) { /* Check for substitutions */ /* To fix, try all possible substitutions */ unsigned position; for(position = 0; position < tlength; position++) { unsigned s; for(s = 0; s < tlength; s++) tbuffer[s] = text[s]; /* try each letter */ for(s = 0; s < sizeof(fixmeletters); s++) { tbuffer[position] = fixmeletters[s]; word_num = find_word(dictionarytable, tbuffer, tlength); if(word_num) break; } if(word_num) break; } } } /* Report any corrections made */ if(word_num) { struct Typocorrection *p; char original[13], changedto[13]; n_strncpy(original, text, 13); n_strncpy(changedto, tbuffer, 13); if(length < 13) original[length] = 0; if(tlength < 13) changedto[tlength] = 0; LEsearch(recent_corrections, p, ((n_strncmp(p->original, original, 13) == 0) && (n_strncmp(p->changedto, changedto, 13) == 0))); /* Only print a correction if it hasn't yet been reported this turn */ if(!p) { struct Typocorrection newcorrection; n_strncpy(newcorrection.original, original, 13); n_strncpy(newcorrection.changedto, changedto, 13); LEadd(recent_corrections, newcorrection); set_glk_stream_current(); if(allow_output) { glk_put_char('['); w_glk_put_buffer(text, length); w_glk_put_string(" -> "); w_glk_put_buffer(tbuffer, tlength); glk_put_char(']'); glk_put_char(10); } } } return word_num; }
static int pdir_difftoc_vacuum(const char *idxpath, const char *diffpath, const char *suffix) { tn_array *lines; char line[2048], *dn, *bn, tmp[PATH_MAX]; char difftoc_path[PATH_MAX], difftoc_path_bak[PATH_MAX]; struct stat st_idx, st; struct vfile *vf; int lineno, i, len; off_t diffs_size; if (poldek__is_in_testing_mode()) return 1; if (stat(idxpath, &st_idx) != 0) { logn(LOGERR, "vaccum diff: stat %s: %m", idxpath); return 0; } if (!mkidx_pathname(difftoc_path, sizeof(difftoc_path), diffpath, suffix)) return 0; n_strncpy(tmp, difftoc_path, sizeof(tmp)); n_basedirnam(tmp, &dn, &bn); if ((vf = vfile_open(difftoc_path, VFT_TRURLIO, VFM_RO)) == NULL) return 0; lines = n_array_new(128, NULL, NULL); while ((len = n_stream_gets(vf->vf_tnstream, line, sizeof(line))) > 0) { char *l; l = alloca(len + 1); memcpy(l, line, len + 1); n_array_push(lines, l); DBGF("l = [%s]\n", l); } if (n_array_size(lines)) { snprintf(difftoc_path_bak, sizeof(difftoc_path_bak), "%s-", difftoc_path); rename(difftoc_path, difftoc_path_bak); } vfile_close(vf); if ((vf = vfile_open(difftoc_path, VFT_TRURLIO, VFM_RW)) == NULL) { rename(difftoc_path_bak, difftoc_path); n_array_free(lines); return 0; } lineno = 0; diffs_size = 0; for (i = n_array_size(lines) - 1; i >= 0; i--) { char *p, *l, path[PATH_MAX]; l = n_array_nth(lines, i); if ((p = strchr(l, ' ')) == NULL) { logn(LOGERR, _("%s: format error"), path); *l = '\0'; continue; } *p = '\0'; /* "- 1" to save space for ".mdd" (to unlink mdd too) */ snprintf(path, sizeof(path) - 1, "%s/%s", dn, l); *p = ' '; if (stat(path, &st) != 0) { if (errno != ENOENT) logn(LOGERR, "vaccum diff: stat %s: %m", l); *l = '\0'; continue; } DBGF("path = (%s) %ld, %ld, %ld\n", path, st.st_size, diffs_size, st_idx.st_size); if (lineno) { if (vf_valid_path(path)) { char *p; msgn(1, _("Removing outdated diff %s"), n_basenam(path)); unlink(path); if ((p = strrchr(path, '.')) && strcmp(p, ".gz") == 0) { strcpy(p, ".mdd"); //msgn(1, _("Removing outdated MDD %s"), n_basenam(path)); unlink(path); } } } else { if (diffs_size + st.st_size > (st_idx.st_size * 0.9)) lineno = i; else diffs_size += st.st_size; } } for (i = lineno; i < n_array_size(lines); i++) { char *l; l = n_array_nth(lines, i); if (*l) n_stream_printf(vf->vf_tnstream, "%s", l); } vfile_close(vf); n_array_free(lines); return 1; }