/* * Copyright 2005-2019 Gentoo Foundation * Distributed under the terms of the GNU General Public License v2 * * Copyright 2005-2008 Ned Ludd - <solar@gentoo.org> * Copyright 2005-2014 Mike Frysinger - <vapier@gentoo.org> */ #include "main.h" #include <stdlib.h> #include <stdbool.h> #include "atom.h" #include "applets.h" #define QATOM_FORMAT "%{CATEGORY} %{PN} %{PV} %[PR] %[SLOT] %[pfx] %[sfx]" #define QATOM_FLAGS "F:c" COMMON_FLAGS static struct option const qatom_long_opts[] = { {"format", a_argument, NULL, 'F'}, {"compare", no_argument, NULL, 'c'}, COMMON_LONG_OPTS }; static const char * const qatom_opts_help[] = { "Custom output format (default: " QATOM_FORMAT ")", "Compare two atoms", COMMON_OPTS_HELP }; #define qatom_usage(ret) usage(ret, QATOM_FLAGS, qatom_long_opts, qatom_opts_help, NULL, lookup_applet_idx("qatom")) /* Run printf on an atom! The format field takes the form: * %{keyword}: Always display the field that matches "keyword" * %[keyword]: Only display the field when it's valid (or pverbose) * The possible "keywords" are: * CATEGORY P PN PV PVR PF PR SLOT * - these are all the standard portage variables (so see ebuild(5)) * pfx - the version qualifier if set (e.g. > < = !) * sfx - the version qualifier if set (e.g. *) */ static void qatom_printf(const char *format, const depend_atom *atom, int pverbose) { char bracket; const char *fmt, *p; if (!atom) { printf("(NULL:atom)"); return; } p = format; while (*p != '\0') { fmt = strchr(p, '%'); if (fmt == NULL) { printf("%s", p); return; } else if (fmt != p) printf("%.*s", (int)(fmt - p), p); bracket = fmt[1]; if (bracket == '{' || bracket == '[') { fmt += 2; p = strchr(fmt, bracket == '{' ? '}' : ']'); if (p) { size_t len = p - fmt; bool showit = (bracket == '{') || pverbose; #define HN(X) (X ? X : "<unset>") if (!strncmp("CATEGORY", fmt, len)) { if (showit || atom->CATEGORY) printf("%s", HN(atom->CATEGORY)); } else if (!strncmp("P", fmt, len)) { if (showit || atom->P) printf("%s", HN(atom->P)); } else if (!strncmp("PN", fmt, len)) { if (showit || atom->PN) printf("%s", HN(atom->PN)); } else if (!strncmp("PV", fmt, len)) { if (showit || atom->PV) printf("%s", HN(atom->PV)); } else if (!strncmp("PVR", fmt, len)) { if (showit || atom->PVR) printf("%s", HN(atom->PVR)); } else if (!strncmp("PF", fmt, len)) { printf("%s", atom->PN); if (atom->PV) printf("-%s", atom->PV); if (atom->PR_int) printf("-r%i", atom->PR_int); } else if (!strncmp("PR", fmt, len)) { if (showit || atom->PR_int) printf("r%i", atom->PR_int); } else if (!strncmp("SLOT", fmt, len)) { if (showit || atom->SLOT) printf(":%s", atom->SLOT ? atom->SLOT : "-"); } else if (!strncmp("REPO", fmt, len)) { if (showit || atom->REPO) printf("::%s", HN(atom->REPO)); } else if (!strncmp("pfx", fmt, len)) { if (showit || atom->pfx_op != ATOM_OP_NONE) fputs(atom->pfx_op == ATOM_OP_NONE ? "-" : atom_op_str[atom->pfx_op], stdout); } else if (!strncmp("sfx", fmt, len)) { if (showit || atom->sfx_op != ATOM_OP_NONE) fputs(atom->sfx_op == ATOM_OP_NONE ? "-" : atom_op_str[atom->sfx_op], stdout); } else printf("<BAD:%.*s>", (int)len, fmt); ++p; #undef HN } else p = fmt + 1; } else ++p; } } int qatom_main(int argc, char **argv) { enum qatom_atom { _EXPLODE=0, _COMPARE } action = _EXPLODE; const char *format = QATOM_FORMAT; depend_atom *atom; int i; while ((i = GETOPT_LONG(QATOM, qatom, "")) != -1) { switch (i) { case 'F': format = optarg; break; case 'c': action = _COMPARE; break; COMMON_GETOPTS_CASES(qatom) } } if (argc == optind) qatom_usage(EXIT_FAILURE); if (action == _COMPARE && (argc - optind) % 2) err("compare needs even number of arguments"); for (i = optind; i < argc; ++i) { switch (action) { case _COMPARE: printf("%s %s %s\n", argv[i], booga[atom_compare_str(argv[i], argv[i+1])], argv[i+1]); ++i; break; case _EXPLODE: atom = atom_explode(argv[i]); qatom_printf(format, atom, verbose); putchar('\n'); atom_implode(atom); break; } } return EXIT_SUCCESS; }