// reset all hash tables // void pool_freeidhashes(Pool *pool) { stringpool_freehash(&pool->ss); pool->relhashtbl = sat_free(pool->relhashtbl); pool->relhashmask = 0; }
void queue_free(Queue *q) { if (q->alloc) sat_free(q->alloc); q->alloc = q->elements = 0; q->count = q->left = 0; }
int main(int argc, char *argv[]) { int c; sat_t *sat; uint32_t sa_repeat = 100; uint32_t sa_best = 0; uint32_t sa_sum = 0; bool run_bruteforce = 0; bool sa_run = true; srand(time(0)); while ((c = getopt(argc, argv, "bc:l:r:sSP")) != -1) { switch (c) { case 'b': run_bruteforce = true; break; case 'c': switch (atoi(optarg)) { case 1: cost = &cost1; break; case 2: cost = &cost2; break; case 3: cost = &cost3; break; default: assert(0); break; } break; case 'l': g_limit = atoi(optarg); break; case 'r': sa_repeat = (uint32_t) atoi(optarg); break; case 's': g_just_solved = true; break; case 'S': sa_run = false; break; case 'P': g_print_progress = true; break; case '?': fprintf(stderr, "unknown opt\n"); return (EXIT_FAILURE); break; default: abort(); break; } } sat = sat_load(); //sat_print(sat); // sat_simulated_evolution(sat, 100); if (run_bruteforce) { sat_bruteforce(sat); } if (sa_run) { assert(cost != NULL); double sa_time = omp_get_wtime(); for (uint32_t i = 0; i < sa_repeat; i++) { uint32_t res = simulated_annealing(sat, 0.01, 10000); // fprintf(stderr, "[%u]", i); // fflush(stdout); sa_sum += res; if (sa_best < res) { sa_best = res; } } sa_time = (omp_get_wtime() - sa_time) / (double) sa_repeat; // fprintf(stderr, "\n"); if (g_just_solved) { if (sa_best > 0) { fprintf(stderr, "1"); } else { fprintf(stderr, "0"); } } else { fprintf(stderr, "saavg= %u sabest= %u satime= %lf \n", (uint32_t) ((double) sa_sum / (double) sa_repeat), sa_best, sa_time); } } sat_free(sat); return (EXIT_SUCCESS); }
/* http://people.sc.fsu.edu/~jburkardt/data/cnf/cnf.html */ static sat_t *sat_load() { sat_t *sat = NULL; sat = calloc(1, sizeof(sat_t)); assert(sat != NULL); if (scanf("p cnf %" SCNu32 " %" SCNu32, &sat->vars_cnt, &sat->clauses_cnt) != 2) { fprintf(stderr, "scanf p cnf %%d %%d has failed\n"); goto error; } sat->clauses_cnt = min(sat->clauses_cnt, g_limit); sat->weights = malloc(sizeof(uint32_t) * sat->vars_cnt); #ifdef SAT_READ_WEIGHTS char c; if (scanf("%c", &c) != 1) { fprintf(stderr, "reading w failed\n"); goto error; } if ((c = getchar()) != 'w') { fprintf(stderr, "reading w failed its -%c-\n", c); goto error; } #else srand(0); #endif sat->weight_sum = 0; sat->weight_max = 0; for (uint32_t i = 0; i < sat->vars_cnt; i++) { #ifdef SAT_READ_WEIGHTS int res; if ((res = scanf("%" SCNu32, &sat->weights[i])) != 1) { fprintf(stderr, "reading weight %d has failed, scanf=%d\n", i, res); goto error; } #else sat->weights[i] = (rand() % 5) + 1; #endif sat->weight_sum += sat->weights[i]; sat->weight_max = max(sat->weight_max, sat->weights[i]); } #ifndef SAT_READ_WEIGHTS srand(time(0)); #endif sat->clauses = malloc(sizeof(int8_t *) * sat->clauses_cnt); assert(sat->clauses); for (uint32_t i = 0; i < sat->clauses_cnt; i++) { sat->clauses[i] = malloc(sizeof(int8_t *) * (sat->clauses_cnt + 1)); assert(sat->clauses[i]); for (uint32_t j = 0; j < 3; j++) { if (scanf("%" SCNd32, &sat->clauses[i][j]) != 1) { fprintf(stderr, "reading clause [%d][%d] has failed\n", i, j); goto error; } } if (scanf("%" SCNd32, &sat->clauses[i][sat->vars_cnt]) != 1) { fprintf(stderr, "reading terminating clause [%d][] has failed\n", i); goto error; } if (sat->clauses[i][sat->vars_cnt] != 0) { fprintf(stderr, "terminating clause [%d][] is not 0 but %d\n", i, sat->clauses[i][sat->vars_cnt]); goto error; } } return (sat); error: // sat_free(sat); return (NULL); }
void repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags) { Pool *pool = repo->pool; struct parsedata pd; char buf[BUFF_SIZE]; int i, l; struct stateswitch *sw; Repodata *data; unsigned int now; now = sat_timems(0); data = repo_add_repodata(repo, flags); memset(&pd, 0, sizeof(pd)); for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) { if (!pd.swtab[sw->from]) pd.swtab[sw->from] = sw; pd.sbtab[sw->to] = sw->from; } pd.common.pool = pool; pd.common.repo = repo; pd.data = data; pd.content = sat_malloc(256); pd.acontent = 256; pd.lcontent = 0; pd.common.tmp = 0; pd.common.tmpl = 0; pd.kind = 0; pd.language = language; /* initialize the string pool where we will store the package checksums we know about, to get an Id we can use in a cache */ stringpool_init_empty(&pd.cspool); if ((flags & REPO_EXTEND_SOLVABLES) != 0) { /* setup join data */ Dataiterator di; dataiterator_init(&di, pool, repo, 0, SOLVABLE_CHECKSUM, 0, 0); while (dataiterator_step(&di)) { const char *str; int index; if (!sat_chksum_len(di.key->type)) continue; str = repodata_chk2str(di.data, di.key->type, (const unsigned char *)di.kv.str); index = stringpool_str2id(&pd.cspool, str, 1); if (index >= pd.ncscache) { pd.cscache = sat_zextend(pd.cscache, pd.ncscache, index + 1 - pd.ncscache, sizeof(Id), 255); pd.ncscache = index + 1; } pd.cscache[index] = di.solvid; } dataiterator_free(&di); } XML_Parser parser = XML_ParserCreate(NULL); XML_SetUserData(parser, &pd); pd.parser = &parser; XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, characterData); for (;;) { l = fread(buf, 1, sizeof(buf), fp); if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR) { pool_debug(pool, SAT_FATAL, "repo_rpmmd: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser)); exit(1); } if (l == 0) break; } XML_ParserFree(parser); sat_free(pd.content); sat_free(pd.lastdirstr); join_freemem(); stringpool_free(&pd.cspool); sat_free(pd.cscache); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); POOL_DEBUG(SAT_DEBUG_STATS, "repo_add_rpmmd took %d ms\n", sat_timems(now)); POOL_DEBUG(SAT_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables); POOL_DEBUG(SAT_DEBUG_STATS, "repo memory used: %d K incore, %d K idarray\n", data->incoredatalen/1024, repo->idarraysize / (int)(1024/sizeof(Id))); }
int main(int argc, char **argv) { int c, flags = 0; const char *attrname = 0; const char *basefile = 0; const char *dir = 0; const char *locale = 0; Pool *pool = pool_create(); Repo *repo = repo_create(pool, "<stdin>"); while ((c = getopt (argc, argv, "hkn:b:d:l:")) >= 0) { switch(c) { case 'h': usage(0); break; case 'k': flags |= RPMMD_KINDS_SEPARATELY; /* do not use! */ break; case 'n': attrname = optarg; break; case 'b': basefile = optarg; break; case 'd': dir = optarg; break; case 'l': locale = optarg; break; default: usage(1); break; } } if (dir) { FILE *fp; int l; char *fnp; l = strlen(dir) + 128; fnp = sat_malloc(l+1); snprintf(fnp, l, "%s/primary.xml.gz", dir); if (!(fp = myfopen(fnp))) { perror(fnp); exit(1); } repo_add_rpmmd(repo, fp, 0, flags); fclose(fp); snprintf(fnp, l, "%s/diskusagedata.xml.gz", dir); if ((fp = myfopen(fnp))) { repo_add_rpmmd(repo, fp, 0, flags); fclose(fp); } if (locale) { if (snprintf(fnp, l, "%s/translation-%s.xml.gz", dir, locale) >= l) { fprintf(stderr, "-l parameter too long\n"); exit(1); } while (!(fp = myfopen(fnp))) { fprintf(stderr, "not opened %s\n", fnp); if (strlen(locale) > 2) { if (snprintf(fnp, l, "%s/translation-%.2s.xml.gz", dir, locale) >= l) { fprintf(stderr, "-l parameter too long\n"); exit(1); } if ((fp = myfopen(fnp))) break; } perror(fnp); exit(1); } fprintf(stderr, "opened %s\n", fnp); repo_add_rpmmd(repo, fp, 0, flags); fclose(fp); } sat_free(fnp); } else repo_add_rpmmd(repo, stdin, 0, flags); tool_write(repo, basefile, attrname); pool_free(pool); exit(0); }
Id pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create) { Hashval h; unsigned int hh; Hashmask hashmask; int i; Id id; Hashtable hashtbl; Reldep *ran; hashmask = pool->relhashmask; hashtbl = pool->relhashtbl; ran = pool->rels; /* extend hashtable if needed */ if (pool->nrels * 2 > hashmask) { sat_free(pool->relhashtbl); pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK); pool->relhashtbl = hashtbl = sat_calloc(hashmask + 1, sizeof(Id)); // rehash all rels into new hashtable for (i = 1; i < pool->nrels; i++) { h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask; hh = HASHCHAIN_START; while (hashtbl[h]) h = HASHCHAIN_NEXT(h, hh, hashmask); hashtbl[h] = i; } } /* compute hash and check for match */ h = relhash(name, evr, flags) & hashmask; hh = HASHCHAIN_START; while ((id = hashtbl[h]) != 0) { if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags) break; h = HASHCHAIN_NEXT(h, hh, hashmask); } if (id) return MAKERELDEP(id); if (!create) return ID_NULL; id = pool->nrels++; /* extend rel space if needed */ pool->rels = sat_extend(pool->rels, id, 1, sizeof(Reldep), REL_BLOCK); hashtbl[h] = id; ran = pool->rels + id; ran->name = name; ran->evr = evr; ran->flags = flags; /* extend whatprovides_rel if needed */ if (pool->whatprovides_rel && (id & WHATPROVIDES_BLOCK) == 0) { pool->whatprovides_rel = sat_realloc2(pool->whatprovides_rel, id + (WHATPROVIDES_BLOCK + 1), sizeof(Offset)); memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset)); } return MAKERELDEP(id); }
void repo_add_content(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; char *line, *linep; int aline; Solvable *s; struct parsedata pd; Repodata *data; Id handle = 0; int contentstyle = 0; char *descrdir = 0; char *datadir = 0; char *defvendor = 0; int i = 0; /* architectures we use the first architecture in BASEARCHS or noarch for the product. At the end we create (clone) the product for each one of the remaining architectures we allow max 4 archs */ unsigned int numotherarchs = 0; Id *otherarchs = 0; memset(&pd, 0, sizeof(pd)); line = sat_malloc(1024); aline = 1024; pd.repo = repo; linep = line; s = 0; data = repo_add_repodata(repo, flags); for (;;) { char *key, *value; /* read line into big-enough buffer */ if (linep - line + 16 > aline) { aline = linep - line; line = sat_realloc(line, aline + 512); linep = line + aline; aline += 512; } if (!fgets(linep, aline - (linep - line), fp)) break; linep += strlen(linep); if (linep == line || linep[-1] != '\n') continue; while ( --linep > line && ( linep[-1] == ' ' || linep[-1] == '\t' ) ) ; /* skip trailing ws */ *linep = 0; linep = line; /* expect "key value" lines */ value = line; key = splitword(&value); if (key) { #if 0 fprintf (stderr, "key %s, value %s\n", key, value); #endif #define istag(x) (!strcmp (key, x)) #define code10 (contentstyle == 10) #define code11 (contentstyle == 11) if (istag ("CONTENTSTYLE")) { if (contentstyle) pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n"); contentstyle = atoi(value); continue; } if (!contentstyle) contentstyle = 10; /* repository tags */ /* we also replicate some of them into the product solvables * to be backward compatible */ if (istag ("REPOID")) { repodata_add_poolstr_array(data, SOLVID_META, REPOSITORY_REPOID, value); continue; } if (istag ("DESCRDIR")) { if (descrdir) free(descrdir); else repo_set_str(repo, SOLVID_META, SUSETAGS_DESCRDIR, value); if (s) repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, value); descrdir = strdup(value); continue; } if (istag ("DATADIR")) { if (datadir) free(datadir); else repo_set_str(repo, SOLVID_META, SUSETAGS_DATADIR, value); if (s) repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value); datadir = strdup(value); continue; } if (istag ("VENDOR")) { if (defvendor) free(defvendor); else repo_set_poolstr(repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value); if (s) s->vendor = str2id(pool, value, 1); defvendor = strdup(value); continue; } if (istag ("META") || istag ("HASH") || istag ("KEY")) { char *checksumtype, *checksum; Id fh, type; int l; if ((checksumtype = splitword(&value)) == 0) continue; if ((checksum = splitword(&value)) == 0) continue; if (!*value) continue; if (!strcasecmp(checksumtype, "sha") || !strcasecmp(checksumtype, "sha1")) l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1; else if (!strcasecmp(checksumtype, "sha256")) l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256; else if (!strcasecmp(checksumtype, "md5")) l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5; else { fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype); exit(1); } if (strlen(checksum) != l) { fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum); exit(1); } fh = repodata_new_handle(data); repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key); repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value); repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum); repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh); continue; } /* product tags */ if ((code10 && istag ("PRODUCT")) || (code11 && istag ("NAME"))) { if (s && !s->name) { /* this solvable was created without seeing a PRODUCT entry, just set the name and continue */ s->name = str2id(pool, join(&pd, "product", ":", value), 1); continue; } if (s) { /* finish old solvable */ if (!s->arch) s->arch = ARCH_NOARCH; if (!s->evr) s->evr = ID_EMPTY; if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); if (code10) s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0); } /* create new solvable */ s = pool_id2solvable(pool, repo_add_solvable(repo)); repodata_extend(data, s - pool->solvables); handle = s - pool->solvables; s->name = str2id(pool, join(&pd, "product", ":", value), 1); if (datadir) repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, datadir); if (descrdir) repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir); if (defvendor) s->vendor = str2id(pool, defvendor, 1); continue; } /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable from here on. */ if (!s) { s = pool_id2solvable(pool, repo_add_solvable(repo)); repodata_extend(data, s - pool->solvables); handle = s - pool->solvables; } if (istag ("VERSION")) pd.tmpvers = strdup(value); else if (istag ("RELEASE")) pd.tmprel = strdup(value); else if (code11 && istag ("DISTRIBUTION")) repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value); else if (istag ("UPDATEURLS")) add_multiple_urls(data, handle, value, str2id(pool, "update", 1)); else if (istag ("EXTRAURLS")) add_multiple_urls(data, handle, value, str2id(pool, "extra", 1)); else if (istag ("OPTIONALURLS")) add_multiple_urls(data, handle, value, str2id(pool, "optional", 1)); else if (istag ("RELNOTESURL")) add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1)); else if (istag ("SHORTLABEL")) repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value); else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */ repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value); else if (!strncmp (key, "LABEL.", 6)) repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value); else if (istag ("FLAGS")) add_multiple_strings(data, handle, PRODUCT_FLAGS, value); else if (istag ("VENDOR")) /* actually already handled above */ s->vendor = str2id(pool, value, 1); else if (istag ("BASEARCHS")) { char *arch; if ((arch = splitword(&value)) != 0) { s->arch = str2id(pool, arch, 1); while ((arch = splitword(&value)) != 0) { otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7); otherarchs[numotherarchs++] = str2id(pool, arch, 1); } } } /* * Every tag below is Code10 only * */ if (code10 && istag ("DISTPRODUCT")) /* DISTPRODUCT is for registration and Yast, not for the solver. */ repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value); else if (code10 && istag ("DISTVERSION")) /* DISTVERSION is for registration and Yast, not for the solver. */ repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value); else if (code10 && istag ("ARCH")) /* Theoretically we want to have the best arch of the given modifiers which still is compatible with the system arch. We don't know the latter here, though. */ s->arch = ARCH_NOARCH; else if (code10 && istag ("PREREQUIRES")) s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER); else if (code10 && istag ("REQUIRES")) s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER); else if (code10 && istag ("PROVIDES")) s->provides = adddep(pool, &pd, s->provides, value, 0); else if (code10 && istag ("CONFLICTS")) s->conflicts = adddep(pool, &pd, s->conflicts, value, 0); else if (code10 && istag ("OBSOLETES")) s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0); else if (code10 && istag ("RECOMMENDS")) s->recommends = adddep(pool, &pd, s->recommends, value, 0); else if (code10 && istag ("SUGGESTS")) s->suggests = adddep(pool, &pd, s->suggests, value, 0); else if (code10 && istag ("SUPPLEMENTS")) s->supplements = adddep(pool, &pd, s->supplements, value, 0); else if (code10 && istag ("ENHANCES")) s->enhances = adddep(pool, &pd, s->enhances, value, 0); /* FRESHENS doesn't seem to exist. */ else if (code10 && istag ("TYPE")) repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value); /* XXX do something about LINGUAS and ARCH? * <ma>: Don't think so. zypp does not use or propagate them. */ #undef istag } else pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line); } if (datadir) free(datadir); if (descrdir) free(descrdir); if (defvendor) free(defvendor); if (s) { if (!s->name) { pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n"); exit(1); } if (pd.tmprel) s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel)); else s->evr = makeevr(pool, pd.tmpvers); pd.tmpvers = sat_free((void *)pd.tmpvers); pd.tmprel = sat_free((void *)pd.tmprel); if (!s->arch) s->arch = ARCH_NOARCH; if (!s->evr) s->evr = ID_EMPTY; if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); if (code10) s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0); /* now for every other arch, clone the product except the architecture */ for (i = 0; i < numotherarchs; ++i) { Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo)); repodata_extend(data, p - pool->solvables); p->name = s->name; p->evr = s->evr; p->vendor = s->vendor; p->arch = otherarchs[i]; /* self provides */ if (s->name && p->arch != ARCH_SRC && p->arch != ARCH_NOSRC) p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0); /* now merge the attributes */ repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables); } } if (pd.tmp) sat_free(pd.tmp); sat_free(line); sat_free(otherarchs); join_freemem(); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); }
void repo_add_code11_products(Repo *repo, const char *dirpath, int flags) { Repodata *data; struct parsedata pd; struct stateswitch *sw; DIR *dir; int i; data = repo_add_repodata(repo, flags); memset(&pd, 0, sizeof(pd)); pd.repo = repo; pd.pool = repo->pool; pd.data = data; pd.content = sat_malloc(256); pd.acontent = 256; for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) { if (!pd.swtab[sw->from]) pd.swtab[sw->from] = sw; pd.sbtab[sw->to] = sw->from; } dir = opendir(dirpath); if (dir) { struct dirent *entry; struct stat st; char *fullpath; /* check for <productsdir>/baseproduct on code11 and remember its target inode */ if (stat(join2(dirpath, "/", "baseproduct"), &st) == 0) /* follow symlink */ pd.baseproduct = st.st_ino; else pd.baseproduct = 0; while ((entry = readdir(dir))) { int len = strlen(entry->d_name); if (len <= 5 || strcmp(entry->d_name + len - 5, ".prod") != 0) continue; fullpath = join2(dirpath, "/", entry->d_name); FILE *fp = fopen(fullpath, "r"); if (!fp) { perror(fullpath); continue; } pd.filename = fullpath; pd.basename = entry->d_name; add_code11_product(&pd, fp); fclose(fp); } closedir(dir); } sat_free((void *)pd.tmplang); sat_free(pd.content); join_freemem(); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); }
static void XMLCALL endElement(void *userData, const char *name) { struct parsedata *pd = userData; Solvable *s = pd->solvable; #if 0 fprintf(stderr, "end: [%d]%s\n", pd->state, name); #endif if (pd->depth != pd->statedepth) { pd->depth--; #if 0 fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); #endif return; } pd->depth--; pd->statedepth--; switch (pd->state) { case STATE_PRODUCT: /* product done, finish solvable */ if (pd->ctime) repodata_set_num(pd->data, pd->handle, SOLVABLE_INSTALLTIME, pd->ctime); if (pd->basename) repodata_set_str(pd->data, pd->handle, PRODUCT_REFERENCEFILE, pd->basename); /* this is where <productsdir>/baseproduct points to */ if (pd->currentproduct == pd->baseproduct) repodata_set_str(pd->data, pd->handle, PRODUCT_TYPE, "base"); if (pd->tmprel) { if (pd->tmpvers) s->evr = makeevr(pd->pool, join2(pd->tmpvers, "-", pd->tmprel)); else { fprintf(stderr, "Seen <release> but no <version>\n"); } } else if (pd->tmpvers) s->evr = makeevr(pd->pool, pd->tmpvers); /* just version, no release */ pd->tmpvers = sat_free((void *)pd->tmpvers); pd->tmprel = sat_free((void *)pd->tmprel); if (!s->arch) s->arch = ARCH_NOARCH; if (!s->evr) s->evr = ID_EMPTY; if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(pd->repo, s->provides, rel2id(pd->pool, s->name, s->evr, REL_EQ, 1), 0); pd->solvable = 0; break; case STATE_VENDOR: s->vendor = str2id(pd->pool, pd->content, 1); break; case STATE_NAME: s->name = str2id(pd->pool, join2("product", ":", pd->content), 1); break; case STATE_VERSION: pd->tmpvers = strdup(pd->content); break; case STATE_RELEASE: pd->tmprel = strdup(pd->content); break; case STATE_ARCH: s->arch = str2id(pd->pool, pd->content, 1); break; case STATE_PRODUCTLINE: repodata_set_str(pd->data, pd->handle, PRODUCT_PRODUCTLINE, pd->content); break; case STATE_UPDATEREPOKEY: /** obsolete **/ break; case STATE_SUMMARY: repodata_set_str(pd->data, pd->handle, langtag(pd, SOLVABLE_SUMMARY, pd->tmplang), pd->content); pd->tmplang = sat_free((void *)pd->tmplang); break; case STATE_SHORTSUMMARY: repodata_set_str(pd->data, pd->handle, PRODUCT_SHORTLABEL, pd->content); break; case STATE_DESCRIPTION: repodata_set_str(pd->data, pd->handle, langtag(pd, SOLVABLE_DESCRIPTION, pd->tmplang), pd->content ); pd->tmplang = sat_free((void *)pd->tmplang); break; case STATE_URL: if (pd->tmpurltype) { repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, str2id(pd->pool, pd->tmpurltype, 1)); } pd->tmpurltype = sat_free((void *)pd->tmpurltype); break; case STATE_TARGET: repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_TARGET, pd->content); break; case STATE_REGRELEASE: repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_RELEASE, pd->content); break; case STATE_CPEID: if (pd->content) repodata_set_str(pd->data, pd->handle, SOLVABLE_CPEID, pd->content); default: break; } pd->state = pd->sbtab[pd->state]; pd->docontent = 0; #if 0 fprintf(stderr, "end: [%s] -> %d\n", name, pd->state); #endif }