mirror of
				https://gitlab.archlinux.org/pacman/pacman.git
				synced 2025-11-04 09:24:45 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			release/7.
			...
			andrew/pfo
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					7dc2266c2f | 
@@ -2913,6 +2913,9 @@ int alpm_capabilities(void);
 | 
			
		||||
/* End of libalpm_api */
 | 
			
		||||
/** @} */
 | 
			
		||||
 | 
			
		||||
size_t alpm_info_print_pkg(const char *format, alpm_pkg_t *pkg);
 | 
			
		||||
size_t alpm_info_print_pkgs(const char *format, alpm_list_t *pkgs);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										226
									
								
								lib/libalpm/info.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								lib/libalpm/info.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,226 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "alpm.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
#include "mfmt.h"
 | 
			
		||||
 | 
			
		||||
typedef enum field_t {
 | 
			
		||||
  FILENAME,
 | 
			
		||||
  NAME,
 | 
			
		||||
  BASE,
 | 
			
		||||
  DESCRIPTION,
 | 
			
		||||
  VERSION,
 | 
			
		||||
  ORIGIN,
 | 
			
		||||
  REASON,
 | 
			
		||||
  LICENSE,
 | 
			
		||||
  GROUP,
 | 
			
		||||
 | 
			
		||||
  DEPENDS,
 | 
			
		||||
  OPTDEPENDS,
 | 
			
		||||
  CONFLICTS,
 | 
			
		||||
  PROVIDES,
 | 
			
		||||
  REPLACES,
 | 
			
		||||
  REQUIREDBY,
 | 
			
		||||
 | 
			
		||||
  DELTAS,
 | 
			
		||||
  FILES,
 | 
			
		||||
  BACKUP,
 | 
			
		||||
  DB,
 | 
			
		||||
  VALIDATION,
 | 
			
		||||
  URL,
 | 
			
		||||
  BUILDDATE,
 | 
			
		||||
  INSTALLDATE,
 | 
			
		||||
  PACKAGER,
 | 
			
		||||
  MD5SUM,
 | 
			
		||||
  SHA256SUM,
 | 
			
		||||
  ARCH,
 | 
			
		||||
  SIZE,
 | 
			
		||||
  ISIZE,
 | 
			
		||||
  BASE64SIG,
 | 
			
		||||
 | 
			
		||||
  UNKNOWN,
 | 
			
		||||
} field_t;
 | 
			
		||||
 | 
			
		||||
static struct field_map_t {
 | 
			
		||||
  const char *input;
 | 
			
		||||
  field_t field;
 | 
			
		||||
} field_map[] = {
 | 
			
		||||
  {"filename", FILENAME},
 | 
			
		||||
  {"name", NAME},
 | 
			
		||||
  {"base", BASE},
 | 
			
		||||
  {"description", DESCRIPTION},
 | 
			
		||||
  {"version", VERSION},
 | 
			
		||||
 | 
			
		||||
  {"license", LICENSE},
 | 
			
		||||
  {"group", GROUP},
 | 
			
		||||
  {"groups", GROUP},
 | 
			
		||||
 | 
			
		||||
  {"depends", DEPENDS},
 | 
			
		||||
  {"optdepends", OPTDEPENDS},
 | 
			
		||||
  {"conflicts", CONFLICTS},
 | 
			
		||||
  {"provides", PROVIDES},
 | 
			
		||||
  {"replaces", REPLACES},
 | 
			
		||||
  {"requiredby", REQUIREDBY},
 | 
			
		||||
 | 
			
		||||
  {"url", URL},
 | 
			
		||||
  {"builddate", BUILDDATE},
 | 
			
		||||
  {"installdate", INSTALLDATE},
 | 
			
		||||
  {"packager", PACKAGER},
 | 
			
		||||
  {"md5sum", MD5SUM},
 | 
			
		||||
  {"sha256sum", SHA256SUM},
 | 
			
		||||
  {"arch", ARCH},
 | 
			
		||||
  {"size", SIZE},
 | 
			
		||||
  {"isize", ISIZE},
 | 
			
		||||
  {"base64sig", BASE64SIG},
 | 
			
		||||
 | 
			
		||||
  {NULL, 0}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static char *_alpm_hr_size(off_t bytes, char *dest)
 | 
			
		||||
{
 | 
			
		||||
  static const char *suff[] = {"B", "K", "M", "G", "T", "P", "E", NULL};
 | 
			
		||||
  float hrsize;
 | 
			
		||||
  int s = 0;
 | 
			
		||||
  while((bytes >= 1000000 || bytes <= -1000000) && suff[s + 1]) {
 | 
			
		||||
    bytes /= 1024;
 | 
			
		||||
    ++s;
 | 
			
		||||
  }
 | 
			
		||||
  hrsize = bytes;
 | 
			
		||||
  if((hrsize >= 1000 || hrsize <= -1000) && suff[s + 1]) {
 | 
			
		||||
    hrsize /= 1024;
 | 
			
		||||
    ++s;
 | 
			
		||||
  }
 | 
			
		||||
  sprintf(dest, "%.2f %s", hrsize, suff[s]);
 | 
			
		||||
  return dest;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static field_t _alpm_info_lookup_field(const char *name) {
 | 
			
		||||
  struct field_map_t *m;
 | 
			
		||||
  for(m = field_map; m->input; m++) {
 | 
			
		||||
    if(strcmp(name, m->input) == 0) { return m->field; }
 | 
			
		||||
  }
 | 
			
		||||
  return UNKNOWN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t _alpm_info_print_str(mfmt_token_callback_t *t, const char *str, FILE *f) {
 | 
			
		||||
  return mfmt_render_str(t, str ? str : "NULL", f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t _alpm_info_print_size(mfmt_token_callback_t *t, const off_t s, FILE *f) {
 | 
			
		||||
  if(s) {
 | 
			
		||||
    char hrsize[50];
 | 
			
		||||
    if(t->conversion == 'd') {
 | 
			
		||||
      snprintf(hrsize, 50, "%lld", (long long)s);
 | 
			
		||||
    } else {
 | 
			
		||||
      _alpm_hr_size(s, hrsize);
 | 
			
		||||
    }
 | 
			
		||||
    return mfmt_render_str(t, hrsize, f);
 | 
			
		||||
  } else {
 | 
			
		||||
    return mfmt_render_str(t, "NULL", f);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t _alpm_info_print_strlist(mfmt_token_callback_t *t, alpm_list_t *l, FILE *f) {
 | 
			
		||||
  if(l) {
 | 
			
		||||
    size_t len = 0;
 | 
			
		||||
    while(l) {
 | 
			
		||||
      len += mfmt_render_str(t, l->data, f) + 1;
 | 
			
		||||
      fputc('\n', f);
 | 
			
		||||
      l = l->next;
 | 
			
		||||
    }
 | 
			
		||||
    return len;
 | 
			
		||||
  } else {
 | 
			
		||||
    return mfmt_render_str(t, "NULL", f);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t _alpm_info_print_deplist(mfmt_token_callback_t *t, alpm_list_t *l, FILE *f) {
 | 
			
		||||
  if(l) {
 | 
			
		||||
    size_t len = 0;
 | 
			
		||||
    while(l) {
 | 
			
		||||
      char *s = alpm_dep_compute_string(l->data);
 | 
			
		||||
      len += mfmt_render_str(t, s, f) + 1;
 | 
			
		||||
      fputc('\n', f);
 | 
			
		||||
      l = l->next;
 | 
			
		||||
      free(s);
 | 
			
		||||
    }
 | 
			
		||||
    return len;
 | 
			
		||||
  } else {
 | 
			
		||||
    return mfmt_render_str(t, "NULL", f);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t _alpm_info_print_timestamp(mfmt_token_callback_t *t, const alpm_time_t s, FILE *f) {
 | 
			
		||||
  if(s) {
 | 
			
		||||
    char datestr[50] = "";
 | 
			
		||||
    if(strftime(datestr, 50, " %c", localtime(&s)) == 0) { return 0; }
 | 
			
		||||
    return mfmt_render_str(t, datestr + 1, f);
 | 
			
		||||
  } else {
 | 
			
		||||
    return mfmt_render_str(t, "NULL", f);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t _alpm_info_process_token(FILE *f, mfmt_token_callback_t *t, void *ctx, void *arg) {
 | 
			
		||||
  alpm_pkg_t *p = arg;
 | 
			
		||||
  (void)ctx;
 | 
			
		||||
  switch(_alpm_info_lookup_field(t->name)) {
 | 
			
		||||
    case NAME:        return _alpm_info_print_str(t, alpm_pkg_get_name(p), f);
 | 
			
		||||
    case DESCRIPTION: return _alpm_info_print_str(t, alpm_pkg_get_desc(p), f);
 | 
			
		||||
    case PACKAGER:    return _alpm_info_print_str(t, alpm_pkg_get_packager(p), f);
 | 
			
		||||
    case MD5SUM:      return _alpm_info_print_str(t, alpm_pkg_get_md5sum(p), f);
 | 
			
		||||
    case FILENAME:    return _alpm_info_print_str(t, alpm_pkg_get_filename(p), f);
 | 
			
		||||
    case BASE:        return _alpm_info_print_str(t, alpm_pkg_get_base(p), f);
 | 
			
		||||
    case VERSION:     return _alpm_info_print_str(t, alpm_pkg_get_version(p), f);
 | 
			
		||||
    case URL:         return _alpm_info_print_str(t, alpm_pkg_get_url(p), f);
 | 
			
		||||
    case SHA256SUM:   return _alpm_info_print_str(t, alpm_pkg_get_sha256sum(p), f);
 | 
			
		||||
    case ARCH:        return _alpm_info_print_str(t, alpm_pkg_get_arch(p), f);
 | 
			
		||||
    case BASE64SIG:   return _alpm_info_print_str(t, alpm_pkg_get_base64_sig(p), f);
 | 
			
		||||
 | 
			
		||||
    case SIZE:  return _alpm_info_print_size(t, alpm_pkg_get_size(p), f);
 | 
			
		||||
    case ISIZE: return _alpm_info_print_size(t, alpm_pkg_get_isize(p), f);
 | 
			
		||||
 | 
			
		||||
    case BUILDDATE:   return _alpm_info_print_timestamp(t, alpm_pkg_get_builddate(p), f);
 | 
			
		||||
    case INSTALLDATE: return _alpm_info_print_timestamp(t, alpm_pkg_get_installdate(p), f);
 | 
			
		||||
 | 
			
		||||
    case DEPENDS:    return _alpm_info_print_deplist(t, alpm_pkg_get_depends(p), f);
 | 
			
		||||
    case OPTDEPENDS: return _alpm_info_print_deplist(t, alpm_pkg_get_optdepends(p), f);
 | 
			
		||||
    case CONFLICTS:  return _alpm_info_print_deplist(t, alpm_pkg_get_conflicts(p), f);
 | 
			
		||||
    case PROVIDES:   return _alpm_info_print_deplist(t, alpm_pkg_get_provides(p), f);
 | 
			
		||||
    case REPLACES:   return _alpm_info_print_deplist(t, alpm_pkg_get_replaces(p), f);
 | 
			
		||||
    case REQUIREDBY: {
 | 
			
		||||
                       alpm_list_t *rb = alpm_pkg_compute_requiredby(p);
 | 
			
		||||
                       size_t len = _alpm_info_print_strlist(t, rb, f);
 | 
			
		||||
                       FREELIST(rb);
 | 
			
		||||
                       return len;
 | 
			
		||||
                     }
 | 
			
		||||
 | 
			
		||||
    default:          errno = EINVAL; return 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t SYMEXPORT alpm_info_print_pkg(const char *format, alpm_pkg_t *pkg) {
 | 
			
		||||
  alpm_list_t l = {
 | 
			
		||||
    .data = pkg,
 | 
			
		||||
    .next = NULL,
 | 
			
		||||
  };
 | 
			
		||||
  l.prev = &l;
 | 
			
		||||
  return alpm_info_print_pkgs(format, &l);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t SYMEXPORT alpm_info_print_pkgs(const char *format, alpm_list_t *pkgs) {
 | 
			
		||||
  mfmt_t *mfmt = mfmt_parse(format, _alpm_info_process_token, NULL);
 | 
			
		||||
  size_t len = 0;
 | 
			
		||||
  if(mfmt == NULL) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  for(alpm_list_t *i = pkgs; i; i = i->next) {
 | 
			
		||||
    size_t plen = mfmt_printf(mfmt, i->data, stdout);
 | 
			
		||||
    if(plen == 0) { return 0; }
 | 
			
		||||
    len += plen;
 | 
			
		||||
  }
 | 
			
		||||
  return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* vim: set ts=2 sw=2 et: */
 | 
			
		||||
@@ -28,5 +28,7 @@ libalpm_sources = files('''
 | 
			
		||||
  sync.h sync.c
 | 
			
		||||
  trans.h trans.c
 | 
			
		||||
  util.h util.c
 | 
			
		||||
  info.c
 | 
			
		||||
  mfmt.c mfmt.h
 | 
			
		||||
  version.c
 | 
			
		||||
'''.split())
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										193
									
								
								lib/libalpm/mfmt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								lib/libalpm/mfmt.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include "mfmt.h"
 | 
			
		||||
 | 
			
		||||
char *_mfmt_find_unescaped_char(char *haystack, char needle) {
 | 
			
		||||
    while(1) {
 | 
			
		||||
        haystack = strchrnul(haystack, needle);
 | 
			
		||||
        if(*haystack && *(haystack + 1) == needle) { haystack += 2; continue; }
 | 
			
		||||
        else { break; }
 | 
			
		||||
    }
 | 
			
		||||
    return haystack;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _mfmt_brace_dedup(char *str) {
 | 
			
		||||
    char *c = str, *end = str + strlen(str);
 | 
			
		||||
    while((c = strchr(c, '{'))) {
 | 
			
		||||
        memmove(c, c + 1, end - c);
 | 
			
		||||
        c++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    c = str;
 | 
			
		||||
    while((c = strchr(c, '}'))) {
 | 
			
		||||
        memmove(c, c + 1, end - c);
 | 
			
		||||
        c++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mfmt_t *mfmt_parse(const char *tmpl, mfmt_callback_t *cb, void *ctx) {
 | 
			
		||||
    mfmt_t *mfmt;
 | 
			
		||||
    char *c;
 | 
			
		||||
 | 
			
		||||
    mfmt = calloc(sizeof(mfmt_t), 1);
 | 
			
		||||
    if(mfmt == NULL) { return NULL; }
 | 
			
		||||
 | 
			
		||||
    mfmt->cb = cb;
 | 
			
		||||
    mfmt->ctx = ctx;
 | 
			
		||||
 | 
			
		||||
    for(c = (char*) tmpl; c && *c; ) {
 | 
			
		||||
        mfmt->token_count++;
 | 
			
		||||
        if(*c == '{' && *(c + 1) != '{') {
 | 
			
		||||
            /* replacement */
 | 
			
		||||
            if(!*(c = _mfmt_find_unescaped_char(c + 1, '}'))) {
 | 
			
		||||
                errno = EINVAL;
 | 
			
		||||
                free(mfmt);
 | 
			
		||||
                return NULL;
 | 
			
		||||
            } else {
 | 
			
		||||
                c++;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            /* literal */
 | 
			
		||||
            c = _mfmt_find_unescaped_char(c, '{');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if((mfmt->tokens = calloc(sizeof(mfmt_token_t), mfmt->token_count)) == NULL) {
 | 
			
		||||
        free(mfmt);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t i;
 | 
			
		||||
    for(c = (char*) tmpl, i = 0; c && *c; i++) {
 | 
			
		||||
        if(*c == '{' && *(c + 1) != '{') {
 | 
			
		||||
            /* replacement */
 | 
			
		||||
            mfmt_token_callback_t *t = &mfmt->tokens[i].callback;
 | 
			
		||||
            char *end = _mfmt_find_unescaped_char(c + 1, '}');
 | 
			
		||||
            t->type = MFMT_TOKEN_CALLBACK;
 | 
			
		||||
            t->name = strndup(c + 1, end - c - 1);
 | 
			
		||||
            c = end + 1;
 | 
			
		||||
        } else {
 | 
			
		||||
            /* literal */
 | 
			
		||||
            char *end = _mfmt_find_unescaped_char(c, '{');
 | 
			
		||||
            mfmt_token_literal_t *t = &mfmt->tokens[i].literal;
 | 
			
		||||
            t->type = MFMT_TOKEN_LITERAL;
 | 
			
		||||
            t->string = strndup(c, end - c);
 | 
			
		||||
            _mfmt_brace_dedup(t->string);
 | 
			
		||||
            c = end;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return mfmt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t mfmt_printf(mfmt_t *mfmt, void *args, FILE *f) {
 | 
			
		||||
    size_t len = 0;
 | 
			
		||||
    size_t i;
 | 
			
		||||
    for(i = 0; i < mfmt->token_count; i++) {
 | 
			
		||||
        mfmt_token_t *t = &mfmt->tokens[i];
 | 
			
		||||
        switch(t->base.type) {
 | 
			
		||||
            case MFMT_TOKEN_LITERAL:
 | 
			
		||||
                len += fputs(t->literal.string, f);
 | 
			
		||||
                break;
 | 
			
		||||
            case MFMT_TOKEN_CALLBACK:
 | 
			
		||||
                len += mfmt->cb(f, &t->callback, mfmt->ctx, args);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                errno = EINVAL;
 | 
			
		||||
                return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t _mfmt_printf_close(mfmt_t *mfmt, void *args, FILE *f) {
 | 
			
		||||
    if(f) {
 | 
			
		||||
        size_t len = mfmt_printf(mfmt, args, f);
 | 
			
		||||
        fclose(f);
 | 
			
		||||
        return len;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t mfmt_printd(mfmt_t *mfmt, void *args, int fd) {
 | 
			
		||||
    return _mfmt_printf_close(mfmt, args, fdopen(fd, "w"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t mfmt_printb(mfmt_t *mfmt, void *args, char *buf, size_t buflen) {
 | 
			
		||||
    return _mfmt_printf_close(mfmt, args, fmemopen(buf, buflen, "w"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t mfmt_prints(mfmt_t *mfmt, void *args, char **buf, size_t *buflen) {
 | 
			
		||||
    return _mfmt_printf_close(mfmt, args, open_memstream(buf, buflen));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t mfmt_fmt(const char *tmpl, mfmt_val_t *args, FILE *f) {
 | 
			
		||||
    mfmt_t *mfmt = mfmt_parse(tmpl, NULL, NULL);
 | 
			
		||||
    size_t len;
 | 
			
		||||
    for(size_t i = 0; i < mfmt->token_count; i++) {
 | 
			
		||||
        mfmt_token_t *t = &mfmt->tokens[i];
 | 
			
		||||
        switch(t->base.type) {
 | 
			
		||||
            case MFMT_TOKEN_LITERAL:
 | 
			
		||||
                len += fputs(t->literal.string, f);
 | 
			
		||||
                break;
 | 
			
		||||
            case MFMT_TOKEN_CALLBACK:
 | 
			
		||||
                /* fprintf(stderr, "token: %s\n", t->callback.name); */
 | 
			
		||||
                if(t->callback.name[0]) {
 | 
			
		||||
                    for(mfmt_val_t *v = args; v; v++) {
 | 
			
		||||
                        /* fprintf(stderr, "val: %s\n", v->name); */
 | 
			
		||||
                        if(strcmp(v->name, t->callback.name) == 0) {
 | 
			
		||||
                            len += fputs(v->string, f);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    len += fputs(args->string, f);
 | 
			
		||||
                    args++;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t mfmt_mfmt(mfmt_t *mfmt, mfmt_val_t *args, FILE *f) {
 | 
			
		||||
    size_t len;
 | 
			
		||||
    for(size_t i = 0; i < mfmt->token_count; i++) {
 | 
			
		||||
        mfmt_token_t *t = &mfmt->tokens[i];
 | 
			
		||||
        switch(t->base.type) {
 | 
			
		||||
            case MFMT_TOKEN_LITERAL:
 | 
			
		||||
                len += fputs(t->literal.string, f);
 | 
			
		||||
                break;
 | 
			
		||||
            case MFMT_TOKEN_CALLBACK:
 | 
			
		||||
                /* fprintf(stderr, "token: %s\n", t->callback.name); */
 | 
			
		||||
                if(t->callback.name[0]) {
 | 
			
		||||
                    for(mfmt_val_t *v = args; v; v++) {
 | 
			
		||||
                        /* fprintf(stderr, "val: %s\n", v->name); */
 | 
			
		||||
                        if(strcmp(v->name, t->callback.name) == 0) {
 | 
			
		||||
                            len += fputs(v->string, f);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    len += fputs(args->string, f);
 | 
			
		||||
                    args++;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t mfmt_render_int(mfmt_token_callback_t *t, const intmax_t i, FILE *f) {
 | 
			
		||||
    (void)t;
 | 
			
		||||
    return fprintf(f, "%jd", i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t mfmt_render_str(mfmt_token_callback_t *t, const char *str, FILE *f) {
 | 
			
		||||
    (void)t;
 | 
			
		||||
    return fputs(str, f);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								lib/libalpm/mfmt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								lib/libalpm/mfmt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
typedef enum mfmt_token_type_t {
 | 
			
		||||
    MFMT_TOKEN_LITERAL,
 | 
			
		||||
    MFMT_TOKEN_CALLBACK,
 | 
			
		||||
} mfmt_token_type_t;
 | 
			
		||||
 | 
			
		||||
typedef struct mfmt_token_literal_t {
 | 
			
		||||
    mfmt_token_type_t type;
 | 
			
		||||
    char *string;
 | 
			
		||||
} mfmt_token_literal_t;
 | 
			
		||||
 | 
			
		||||
typedef struct mfmt_token_base_t {
 | 
			
		||||
    mfmt_token_type_t type;
 | 
			
		||||
} mfmt_token_base_t;
 | 
			
		||||
 | 
			
		||||
typedef struct mfmt_token_callback_t {
 | 
			
		||||
    mfmt_token_type_t type;
 | 
			
		||||
 | 
			
		||||
    size_t position;
 | 
			
		||||
    char *name;
 | 
			
		||||
    size_t width;
 | 
			
		||||
    size_t precision;
 | 
			
		||||
    char align;
 | 
			
		||||
    char fill;
 | 
			
		||||
    char conversion;
 | 
			
		||||
    int sign;
 | 
			
		||||
} mfmt_token_callback_t;
 | 
			
		||||
 | 
			
		||||
typedef union mfmt_token_t {
 | 
			
		||||
    mfmt_token_base_t base;
 | 
			
		||||
    mfmt_token_literal_t literal;
 | 
			
		||||
    mfmt_token_callback_t callback;
 | 
			
		||||
} mfmt_token_t;
 | 
			
		||||
 | 
			
		||||
typedef size_t (mfmt_callback_t)(FILE *f, mfmt_token_callback_t *token, void *ctx, void *args);
 | 
			
		||||
 | 
			
		||||
typedef struct mfmt_t {
 | 
			
		||||
    mfmt_callback_t *cb;
 | 
			
		||||
    void *ctx;
 | 
			
		||||
    size_t token_count;
 | 
			
		||||
    mfmt_token_t *tokens;
 | 
			
		||||
} mfmt_t;
 | 
			
		||||
 | 
			
		||||
typedef struct mfmt_val_t {
 | 
			
		||||
    const char *name;
 | 
			
		||||
    const char *string;
 | 
			
		||||
} mfmt_val_t;
 | 
			
		||||
 | 
			
		||||
mfmt_t *mfmt_parse(const char *tmpl, mfmt_callback_t *cb, void *ctx);
 | 
			
		||||
size_t mfmt_printf(mfmt_t *mfmt, void *args, FILE *f);
 | 
			
		||||
size_t mfmt_printd(mfmt_t *mfmt, void *args, int fd);
 | 
			
		||||
size_t mfmt_printb(mfmt_t *mfmt, void *args, char *buf, size_t buflen);
 | 
			
		||||
size_t mfmt_prints(mfmt_t *mfmt, void *args, char **buf, size_t *buflen);
 | 
			
		||||
void mfmt_free(mfmt_t *mfmt);
 | 
			
		||||
 | 
			
		||||
size_t mfmt_render_int(mfmt_token_callback_t *token, intmax_t i, FILE *f);
 | 
			
		||||
size_t mfmt_render_uint(mfmt_token_callback_t *token, uintmax_t i, FILE *f);
 | 
			
		||||
size_t mfmt_render_str(mfmt_token_callback_t *token, const char *str, FILE *f);
 | 
			
		||||
 | 
			
		||||
size_t mfmt_formatf(const char *tmpl, mfmt_callback_t *cb, void *ctx, FILE *f);
 | 
			
		||||
size_t mfmt_formatd(const char *tmpl, mfmt_callback_t *cb, void *ctx, int fd);
 | 
			
		||||
size_t mfmt_formatb(const char *tmpl, mfmt_callback_t *cb, void *ctx, char *buf, size_t buflen);
 | 
			
		||||
size_t mfmt_formats(const char *tmpl, mfmt_callback_t *cb, void *ctx, char **buf);
 | 
			
		||||
@@ -58,6 +58,7 @@ typedef struct __config_t {
 | 
			
		||||
	unsigned short color;
 | 
			
		||||
	unsigned short disable_dl_timeout;
 | 
			
		||||
	char *print_format;
 | 
			
		||||
	char *pformat;
 | 
			
		||||
	/* unfortunately, we have to keep track of paths both here and in the library
 | 
			
		||||
	 * because they can come from both the command line or config file, and we
 | 
			
		||||
	 * need to ensure we get the order of preference right. */
 | 
			
		||||
@@ -172,6 +173,7 @@ enum {
 | 
			
		||||
	OP_ASEXPLICIT,
 | 
			
		||||
	OP_ARCH,
 | 
			
		||||
	OP_PRINTFORMAT,
 | 
			
		||||
	OP_PFORMAT,
 | 
			
		||||
	OP_GPGDIR,
 | 
			
		||||
	OP_DBONLY,
 | 
			
		||||
	OP_FORCE,
 | 
			
		||||
 
 | 
			
		||||
@@ -651,6 +651,9 @@ static int parsearg_trans(int opt)
 | 
			
		||||
			free(config->print_format);
 | 
			
		||||
			config->print_format = strdup(optarg);
 | 
			
		||||
			break;
 | 
			
		||||
		case OP_PFORMAT:
 | 
			
		||||
			config->pformat = strdup(optarg);
 | 
			
		||||
			break;
 | 
			
		||||
		case OP_ASSUMEINSTALLED:
 | 
			
		||||
			parsearg_util_addlist(&(config->assumeinstalled));
 | 
			
		||||
			break;
 | 
			
		||||
@@ -944,6 +947,7 @@ static int parseargs(int argc, char *argv[])
 | 
			
		||||
		{"asexplicit",     no_argument,   0, OP_ASEXPLICIT},
 | 
			
		||||
		{"arch",       required_argument, 0, OP_ARCH},
 | 
			
		||||
		{"print-format", required_argument, 0, OP_PRINTFORMAT},
 | 
			
		||||
		{"pformat"     , required_argument, 0, OP_PFORMAT},
 | 
			
		||||
		{"gpgdir",     required_argument, 0, OP_GPGDIR},
 | 
			
		||||
		{"dbonly",     no_argument,       0, OP_DBONLY},
 | 
			
		||||
		{"color",      required_argument, 0, OP_COLOR},
 | 
			
		||||
 
 | 
			
		||||
@@ -1168,6 +1168,10 @@ double humanize_size(off_t bytes, const char target_unit, int precision,
 | 
			
		||||
void print_packages(const alpm_list_t *packages)
 | 
			
		||||
{
 | 
			
		||||
	const alpm_list_t *i;
 | 
			
		||||
	if(config->pformat) {
 | 
			
		||||
		alpm_info_print_pkgs(config->pformat, (alpm_list_t*) packages);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if(!config->print_format) {
 | 
			
		||||
		config->print_format = strdup("%l");
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user