diff --git a/misc/tools-source/config_helper.c b/misc/tools-source/config_helper.c index 9c7a7ea09..78a4a9b94 100644 --- a/misc/tools-source/config_helper.c +++ b/misc/tools-source/config_helper.c @@ -46,6 +46,8 @@ struct builtin { #include #include +#define HASH_LEN 4096 + struct package; struct package { int status; @@ -60,9 +62,41 @@ struct package { (for easily searching for flags). */ char *flags; struct package *next; + struct package *next_in_alias_hash; }; struct package *package_list = 0; +struct package *package_alias_hash[HASH_LEN]; + +static unsigned int hash_string(const char *key) +{ + unsigned int c, hash = 0; + const unsigned char *ukey = (const unsigned char *)key; + /* hashing algorithms are fun. this one is from the sdbm package. */ + while (ukey && (c = *ukey++)) hash = c + (hash << 6) + (hash << 16) - hash; + return hash % HASH_LEN; +} + +static void hash_remove(struct package *p) +{ + unsigned int h = hash_string(p->alias); + struct package **pp = &package_alias_hash[h]; + while (*pp) { + if (*pp == p) { + *pp = p->next_in_alias_hash; + break; + } + pp = &(*pp)->next_in_alias_hash; + } + p->next_in_alias_hash = NULL; +} + +static void hash_insert(struct package *p) +{ + unsigned int h = hash_string(p->alias); + p->next_in_alias_hash = package_alias_hash[h]; + package_alias_hash[h] = p; +} int read_pkg_list(const char *file) { FILE *f = fopen(file, "r"); @@ -72,6 +106,7 @@ int read_pkg_list(const char *file) { int i; while (pkg) { + hash_remove(pkg); free(pkg->prio); free(pkg->repository); free(pkg->name); @@ -126,6 +161,8 @@ int read_pkg_list(const char *file) { tok[strlen(tok)-1] = 0; pkg_tmp->flags = strdup(tok); + hash_insert(pkg_tmp); + if ( !package_list ) pkg=package_list=pkg_tmp; else @@ -254,6 +291,7 @@ int pkgswitch(int mode, char **args) if (match) { if ( !mode ) { + hash_remove(pkg); *(last_pkg ? &(last_pkg->next) : &package_list) = pkg->next; free(pkg->prio); free(pkg->repository); @@ -279,7 +317,7 @@ int pkgfork(char *pkgname, char *xpkg, char** opt) struct package *fork, *pkg; int i, k; - for (pkg = package_list; pkg; pkg = pkg->next) + for (pkg = package_alias_hash[hash_string(pkgname)]; pkg; pkg = pkg->next_in_alias_hash) if (!strcmp(pkg->alias, pkgname)) break; if (!pkg) return 1; @@ -357,6 +395,8 @@ int pkgfork(char *pkgname, char *xpkg, char** opt) } } + hash_insert(fork); + return 0; } diff --git a/misc/tools-source/descparser.c b/misc/tools-source/descparser.c index 49dd85ac6..b08dc69b8 100644 --- a/misc/tools-source/descparser.c +++ b/misc/tools-source/descparser.c @@ -70,9 +70,15 @@ int condstack[128]; int condcount = -1; int falselevel = 0; -void parse_file(FILE *f); +char *x_status = NULL; +char *x_priority = NULL; +char *x_stages = NULL; +char *x_version = NULL; +char *x_extraver = NULL; -void parse_file(FILE *f) +void parse_file(FILE *f, int xmode); + +void parse_file(FILE *f, int xmode) { while ( fgets(line, 4096, f) ) { if (line[0] == '#') { @@ -99,20 +105,48 @@ void parse_file(FILE *f) if (strchr(line, '\n')) *strchr(line, '\n') = 0; i = fopen(line+9, "r"); if (i) { - parse_file(i); + parse_file(i, xmode); fclose(i); } else fprintf(stderr, "Can't #include '%s'.\n", line+9); } - } else - if ( !falselevel ) + } else if ( !falselevel ) { + if ( xmode ) { + if (!strncmp(line, "[V]", 3) || !strncmp(line, "[VER]", 5) || !strncmp(line, "[VERSION]", 9)) { + free(x_version); + free(x_extraver); + strtok(line, " \t\n"); + x_version = strdup(strtok(NULL, " \t\n") ?: ""); + x_extraver = strdup(strtok(NULL, " \t\n") ?: ""); + } + if (!strncmp(line, "[P]", 3) || !strncmp(line, "[PRI]", 5) || !strncmp(line, "[PRIORITY]", 10)) { + free(x_status); + free(x_priority); + free(x_stages); + strtok(line, " \t\n"); + x_status = strdup(strtok(NULL, " \t\n") ?: ""); + x_stages = strdup(strtok(NULL, " \t\n") ?: ""); + x_priority = strdup(strtok(NULL, " \t\n") ?: ""); + } + } else fputs(line, stdout); + } } } -int main() +int main(int argc, char **argv) { - parse_file(stdin); + if (argc == 2 && !strcmp(argv[1], "-x")) { + parse_file(stdin, 1); + printf("%s %s %s %s %s\n", x_status, x_priority, x_stages, x_version, + (x_extraver && *x_extraver) ? x_extraver : "0"); + free(x_status); + free(x_priority); + free(x_stages); + free(x_version); + free(x_extraver); + } else + parse_file(stdin, 0); return 0; } diff --git a/package/public/qcake/preconfig.in b/package/public/qcake/preconfig.in index e5b192ff9..de2891580 100644 --- a/package/public/qcake/preconfig.in +++ b/package/public/qcake/preconfig.in @@ -1,4 +1,3 @@ -pkgfork qcake qcake-cat pkgfork qcake qcake-soundcat pkgfork qcake qcake-3dcat pkgfork qcake qcake-splcat diff --git a/scripts/config.func b/scripts/config.func index 006beb74b..c5d7b21d1 100644 --- a/scripts/config.func +++ b/scripts/config.func @@ -186,18 +186,24 @@ else return $ret } pkgfork() { - local pkg=$1 xpkg=$2 extraver ; shift 2 + local pkg=$1 xpkg=$2 status priority stages version extraver; shift 2 bprof pkgfork start - # >50% of the Config time is spent in this line! - parse_desc package/*/$pkg/$pkg.desc P V + local parser="$( type -p descparser )" tag tagdata - extraver=$( echo $desc_V 0 | cut -f2 -d" " ) + [ -z "${parser}" ] && parser="$base/src/descparser" + if [ ! -x "${parser}" ] ; then + mkdir -p $base/src + cc -o $base/src/descparser $base/misc/tools-source/descparser.c + fi + [ ! -x "${parser}" ] && abort "Couldn't find \`descparser'! Please run ./scripts/Build-Tools!" + + read status priority stages version extraver < <( pkg=$pkg xpkg=$xpkg $parser -x < package/*/$pkg/$pkg.desc ) + + cfghlp pkgfork $pkg $xpkg status "$status" priority "$priority" \ + stages "$stages" version "$version" extraversion "$extraver" "$@" - cfghlp pkgfork $pkg $xpkg status ${desc_P%% *} priority ${desc_P##* } \ - stages $( echo $desc_P | cut -f2 -d" ") \ - version ${desc_V%% *} extraversion $extraver $@ bprof pkgfork stop } fi