summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Reisner <d@falconindy.com>2010-12-10 22:38:24 -0500
committerDave Reisner <d@falconindy.com>2010-12-10 22:48:19 -0500
commite835af7775599a5c942f3813907dfa72d1227553 (patch)
tree7a1de0dcf775b274ce1d621d94677ac08cce092f
parentc2d67feae0688c1ba601722edfd3024bc364ce51 (diff)
downloadexpac-e835af7775599a5c942f3813907dfa72d1227553.tar.xz
allow real printf formatters for simple strings
It's kind of silly to verify this kind of formatting, so I'm just letting it explode (which happens not too horribly) when the user inevitably does something stupid.
-rw-r--r--README.pod6
-rw-r--r--expac.c68
2 files changed, 28 insertions, 46 deletions
diff --git a/README.pod b/README.pod
index b675f20..cd29252 100644
--- a/README.pod
+++ b/README.pod
@@ -119,7 +119,11 @@ The format argument allows the following interpreted sequences:
%% literal %
-Standard backslash escape sequences are supported. See printf(1).
+Note that for any lowercase tokens aside from %m and %k, full printf support is
+allowed, e.g. %-20n. This does not apply to any list based, date, or numerical
+output.
+
+Standard backslash escape sequences are supported, as per printf(1).
=head1 AUTHOR
diff --git a/expac.c b/expac.c
index 63c2562..503af54 100644
--- a/expac.c
+++ b/expac.c
@@ -42,6 +42,9 @@
#define FORMAT_TOKENS_SYNC "f"
#define ESCAPE_TOKENS "\"\\abefnrtv"
+static char const digits[] = "0123456789";
+static char const printf_flags[] = "'-+ #0I";
+
pmdb_t *db_local = NULL;
alpm_list_t *dblist = NULL;
alpm_list_t *targets = NULL;
@@ -344,45 +347,52 @@ static int print_time(time_t timestamp) {
static int print_pkg(pmpkg_t *pkg, const char *format) {
const char *f;
- int out = 0;
+ char fmt[32];
+ int len, out = 0;
for (f = format; *f != '\0'; f++) {
bool shortdeps = false;
+ len = 0;
if (*f == '%') {
- switch (*++f) {
+ len = strspn(f + 1 + len, printf_flags);
+ len += strspn(f + 1 + len, digits);
+ snprintf(fmt, len + 3, "%ss", f);
+ fmt[len + 1] = 's';
+ f += len + 1;
+ switch (*f) {
/* simple attributes */
case 'f': /* filename */
- out += printf("%s", alpm_pkg_get_filename(pkg));
+ out += printf(fmt, alpm_pkg_get_filename(pkg));
break;
case 'n': /* package name */
- out += printf("%s", alpm_pkg_get_name(pkg));
+ out += printf(fmt, alpm_pkg_get_name(pkg));
break;
case 'v': /* version */
- out += printf("%s", alpm_pkg_get_version(pkg));
+ out += printf(fmt, alpm_pkg_get_version(pkg));
break;
case 'd': /* description */
- out += printf("%s", alpm_pkg_get_desc(pkg));
+ out += printf(fmt, alpm_pkg_get_desc(pkg));
break;
case 'u': /* project url */
- out += printf("%s", alpm_pkg_get_url(pkg));
+ out += printf(fmt, alpm_pkg_get_url(pkg));
break;
case 'p': /* packager name */
- out += printf("%s", alpm_pkg_get_packager(pkg));
+ out += printf(fmt, alpm_pkg_get_packager(pkg));
break;
case 's': /* md5sum */
- out += printf("%s", alpm_pkg_get_md5sum(pkg));
+ out += printf(fmt, alpm_pkg_get_md5sum(pkg));
break;
case 'a': /* architecutre */
- out += printf("%s", alpm_pkg_get_arch(pkg));
+ out += printf(fmt, alpm_pkg_get_arch(pkg));
break;
case 'i': /* has install scriptlet? */
- out += printf("%s", alpm_pkg_has_scriptlet(pkg) ? "yes" : "no");
+ out += printf(fmt, alpm_pkg_has_scriptlet(pkg) ? "yes" : "no");
break;
case 'r': /* repo */
- out += printf("%s", alpm_db_get_name(alpm_pkg_get_db(pkg)));
+ out += printf(fmt, alpm_db_get_name(alpm_pkg_get_db(pkg)));
break;
case 'w': /* install reason */
- out += printf("%s", alpm_pkg_get_reason(pkg) ? "dependency" : "explicit");
+ out += printf(fmt, alpm_pkg_get_reason(pkg) ? "dependency" : "explicit");
break;
/* times */
@@ -462,34 +472,6 @@ static int print_pkg(pmpkg_t *pkg, const char *format) {
return(0);
}
-int verify_format_string(const char *format) {
- const char *p;
-
- for (p = format; *p != '\0'; p++) {
- if (*p == '%') {
- ++p;
- if (!strchr(FORMAT_TOKENS FORMAT_TOKENS_LOCAL FORMAT_TOKENS_SYNC, *p)) {
- fprintf(stderr, "error: bad token in format string: %%%c\n", *p);
- return(1);
- }
-
- /* check for querytype dependent tokens */
- if (!local && strchr(FORMAT_TOKENS_LOCAL, *p)) {
- fprintf(stderr, "error: token not available with local queries: %%%c\n", *p);
- return(1);
- } else if (local && strchr(FORMAT_TOKENS_SYNC, *p)) {
- fprintf(stderr, "error: token not available with sync queries: %%%c\n", *p);
- return(1);
- }
- } else if (*p == '\\' && !strchr(ESCAPE_TOKENS, *++p)) {
- fprintf(stderr, "error: bad token in format string: \\%c\n", *p);
- return(1);
- }
- }
-
- return(0);
-}
-
alpm_list_t *resolve_pkg(alpm_list_t *targets) {
char *pkgname, *reponame;
alpm_list_t *t, *r, *ret = NULL;
@@ -569,10 +551,6 @@ int main(int argc, char *argv[]) {
listdelim = listdelim ? listdelim : DEFAULT_LISTDELIM;
timefmt = timefmt ? timefmt : DEFAULT_TIMEFMT;
- if (verify_format_string(format) != 0) {
- return(1);
- }
-
results = resolve_pkg(targets);
if (!results) {
ret = 1;