diff options
author | Mattias Andrée <maandree@kth.se> | 2021-04-12 13:37:59 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2021-04-12 13:37:59 +0200 |
commit | fa88a28e46b7ac2d3dcd1938e5e4708157d08b22 (patch) | |
tree | c3ca4f98374328f37d71d1079f9e1f7406ed84d8 /common.h | |
parent | Minor fix to set-contact-photos (diff) | |
download | contacts-fa88a28e46b7ac2d3dcd1938e5e4708157d08b22.tar.gz contacts-fa88a28e46b7ac2d3dcd1938e5e4708157d08b22.tar.bz2 contacts-fa88a28e46b7ac2d3dcd1938e5e4708157d08b22.tar.xz |
Deduplicate code and make some small improvements
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'common.h')
-rw-r--r-- | common.h | 246 |
1 files changed, 219 insertions, 27 deletions
@@ -32,22 +32,23 @@ int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, do # define LIST_BOOL_PARAMS(X) #endif -#define X_USAGE_UPPER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + +#define X_SET_USAGE_UPPER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ "[-"UPPERS" old-"DISPLAY"] " -#define X_USAGE_LOWER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_USAGE_LOWER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ "[-"LOWERS" new-"DISPLAY"] " -#define X_USAGE_BOOL(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_USAGE_BOOL(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ "[-"UPPERS" | -"LOWERS"] " -#define X_PARAMS(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_PARAMS(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ char *VAR = NULL, *lookup_##VAR = NULL, *old_##VAR = NULL; -#define X_BOOL_PARAMS(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_BOOL_PARAMS(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ int set_##VAR = -1; -#define X_ARGPARSE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_ARGPARSE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ case UPPERC:\ add = 0;\ if (lookup_##VAR)\ @@ -61,7 +62,7 @@ int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, do VAR = ARG();\ break; -#define X_BOOL_ARGPARSE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_BOOL_ARGPARSE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ case UPPERC:\ if (set_##VAR >= 0)\ usage();\ @@ -73,50 +74,50 @@ int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, do set_##VAR = 1;\ break; -#define X_LOWER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_LOWER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ LOWERS -#define X_LOOKUP(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_LOOKUP(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ if (lookup_##VAR && strcmpnul(contact.CATEGORY[i]->VAR, lookup_##VAR))\ continue; -#define X_BOOL_LOOKUP(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_BOOL_LOOKUP(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ if (remove && set_##VAR >= 0 && contact.CATEGORY[i]->is_##VAR != set_##VAR)\ continue; -#define X_CHANGE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_CHANGE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ if (VAR) {\ old_##VAR = contact.CATEGORY[i]->VAR;\ contact.CATEGORY[i]->VAR = VAR;\ } -#define X_BOOL_SET(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_BOOL_SET(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ if (set_##VAR >= 0)\ contact.CATEGORY[i]->is_##VAR = set_##VAR; -#define X_ADD(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_ADD(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ contact.CATEGORY[i]->VAR = VAR; -#define X_RESTORE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ +#define X_SET_RESTORE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ contact.CATEGORY[i]->VAR = old_##VAR; #define IMPLEMENT_SET_ON_LIST(CAT)\ - USAGE(LIST_PARAMS(X_USAGE_UPPER)LIST_BOOL_PARAMS(X_USAGE_BOOL)"("LIST_PARAMS(X_USAGE_LOWER)"| -u) contact-id");\ + USAGE(LIST_PARAMS(X_SET_USAGE_UPPER)LIST_BOOL_PARAMS(X_SET_USAGE_BOOL)"("LIST_PARAMS(X_SET_USAGE_LOWER)"| -u) contact-id");\ \ int\ main(int argc, char *argv[])\ {\ int add = 1, edit = 0, remove = 0;\ - LIST_PARAMS(X_PARAMS)\ - LIST_BOOL_PARAMS(X_BOOL_PARAMS)\ + LIST_PARAMS(X_SET_PARAMS)\ + LIST_BOOL_PARAMS(X_SET_BOOL_PARAMS)\ struct passwd *user;\ struct libcontacts_contact contact;\ struct libcontacts_##CAT **r = NULL, **w;\ size_t i;\ \ ARGBEGIN {\ - LIST_PARAMS(X_ARGPARSE)\ - LIST_BOOL_PARAMS(X_BOOL_ARGPARSE)\ + LIST_PARAMS(X_SET_ARGPARSE)\ + LIST_BOOL_PARAMS(X_SET_BOOL_ARGPARSE)\ case 'u':\ remove = 1;\ break;\ @@ -130,7 +131,7 @@ int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, do if (remove == edit) {\ if (edit)\ usage();\ - eprintf("at least one of -"LIST_PARAMS(X_LOWER)"u is required\n");\ + eprintf("at least one of -"LIST_PARAMS(X_SET_LOWER)"u is required\n");\ }\ \ if (add)\ @@ -149,8 +150,8 @@ int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, do i = 0;\ if ((edit || remove) && contact.CATEGORY) {\ for (; contact.CATEGORY[i]; i++) {\ - LIST_PARAMS(X_LOOKUP)\ - LIST_BOOL_PARAMS(X_BOOL_LOOKUP)\ + LIST_PARAMS(X_SET_LOOKUP)\ + LIST_BOOL_PARAMS(X_SET_BOOL_LOOKUP)\ break;\ }\ if (!contact.CATEGORY[i]) {\ @@ -162,8 +163,8 @@ int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, do free(*r);\ for (w = r++; (*w++ = *r++););\ } else {\ - LIST_PARAMS(X_CHANGE)\ - LIST_BOOL_PARAMS(X_BOOL_SET)\ + LIST_PARAMS(X_SET_CHANGE)\ + LIST_BOOL_PARAMS(X_SET_BOOL_SET)\ }\ } else if (!edit && !remove) {\ if (contact.CATEGORY)\ @@ -171,17 +172,208 @@ int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, do contact.CATEGORY = erealloc(contact.CATEGORY, (i + 2) * sizeof(*contact.CATEGORY));\ contact.CATEGORY[i + 1] = NULL;\ contact.CATEGORY[i] = ecalloc(1, sizeof(**contact.CATEGORY));\ - LIST_PARAMS(X_ADD)\ - LIST_BOOL_PARAMS(X_BOOL_SET)\ + LIST_PARAMS(X_SET_ADD)\ + LIST_BOOL_PARAMS(X_SET_BOOL_SET)\ }\ \ if (libcontacts_save_contact(&contact, user))\ eprintf("libcontacts_save_contact %s:", argv[0]);\ \ if (!r) {\ - LIST_PARAMS(X_RESTORE)\ + LIST_PARAMS(X_SET_RESTORE)\ }\ \ libcontacts_contact_destroy(&contact);\ return 0;\ } + + +#define X_GET_USAGE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + "[-"LOWERS" "DISPLAY"] " + +#define X_GET_UPPER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + UPPERS + +#define X_GET_PARAMS(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + int display_##VAR = 0;\ + const char *lookup_##VAR = NULL; + +#define X_GET_ARGPARSE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + case LOWERC:\ + if (lookup_##VAR)\ + usage();\ + lookup_##VAR = ARG();\ + break;\ + case UPPERC:\ + fields += !display_##VAR;\ + display_##VAR = 1;\ + break; + +#define X_GET_AUTO_DISPLAY(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + fields += display_##VAR = !lookup_##VAR; + +#define X_GET_LOOKUP(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + if (lookup_##VAR && strcmpnul(elem->VAR, lookup_##VAR))\ + continue; + +#define X_GET_FULL_LOOKUP(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + lookup_##VAR && + +#define X_GET_DISPLAY(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + if (display_##VAR) {\ + fields_ -= 1;\ + printf("%s%s", elem->VAR, fields_ ? ": " : "\n");\ + } + +#define IMPLEMENT_GET_ON_LIST(CAT)\ + USAGE(LIST_PARAMS(X_GET_USAGE)"[-"LIST_PARAMS(X_GET_UPPER)"] contact-id ..."); \ + \ + int\ + main(int argc, char *argv[])\ + {\ + LIST_PARAMS(X_GET_PARAMS)\ + struct passwd *user;\ + struct libcontacts_contact contact;\ + struct libcontacts_##CAT **elems, *elem;\ + int ret = 0, fields = 0, fields_;\ + size_t i; \ + \ + ARGBEGIN {\ + LIST_PARAMS(X_GET_ARGPARSE)\ + default:\ + usage();\ + } ARGEND;\ + \ + if (!argc)\ + usage();\ + \ + if (!fields) {\ + LIST_PARAMS(X_GET_AUTO_DISPLAY)\ + }\ + \ + for (i = 0; argv[i]; i++)\ + if (!*argv[i] || strchr(argv[i], '/'))\ + usage();\ + \ + errno = 0;\ + user = getpwuid(getuid());\ + if (!user)\ + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist");\ + \ + for (; *argv; argv++) {\ + if (libcontacts_load_contact(*argv, &contact, user)) {\ + weprintf("libcontacts_load_contact %s: %s\n", *argv,\ + errno ? strerror(errno) : "contact file is malformatted");\ + ret = 1;\ + continue;\ + }\ + if ((elems = contact.CATEGORY)) {\ + for (; (elem = *elems); elems++) {\ + LIST_PARAMS(X_GET_LOOKUP)\ + if (LIST_PARAMS(X_GET_FULL_LOOKUP) !fields) {\ + printf("%s\n", *argv);\ + continue;\ + }\ + if (argc > 1)\ + printf("%s: ", *argv);\ + fields_ = fields;\ + LIST_PARAMS(X_GET_DISPLAY)\ + }\ + }\ + libcontacts_contact_destroy(&contact);\ + }\ + \ + if (fflush(stdout) || ferror(stdout) || fclose(stdout))\ + eprintf("printf:");\ + return ret;\ + } + + +#define X_FIND_USAGE(LOWERC, LOWERS, VAR, DISPLAY)\ + "[-"LOWERS" "DISPLAY"] " + +#define X_FIND_PARAMS(LOWERC, LOWERS, VAR, DISPLAY)\ + const char *VAR = NULL; + +#define X_FIND_ARGPARSE(LOWERC, LOWERS, VAR, DISPLAY)\ + case LOWERC:\ + if (VAR)\ + usage();\ + VAR = ARG();\ + break; + +#define X_FIND_LOOKUP(LOWERC, LOWERS, VAR, DISPLAY)\ + if (VAR && strcmpnul(elem->VAR, VAR))\ + continue; + +#ifdef SUBCATEGORY +# define PRINT_PREFIX_LIST(DATUM)\ + if (elem->SUBCATEGORY && !SUBCATEGORY)\ + printf("%s (%s: %s)\n", contacts[i]->id, elem->SUBCATEGORY, elem->DATUM);\ + else +# define PRINT_PREFIX_LOOKUP(DATUM)\ + if (elem->SUBCATEGORY && !SUBCATEGORY)\ + printf("%s (%s)\n", contacts[i]->id, elem->SUBCATEGORY);\ + else +#else +# define PRINT_PREFIX_LIST(DATUM) +# define PRINT_PREFIX_LOOKUP(DATUM) +#endif + +#define IMPLEMENT_FIND_ON_LIST(CAT, DATUM, DISPLAY)\ + USAGE(LIST_PARAMS(X_FIND_USAGE)"(-L | "DISPLAY")");\ + \ + int\ + main(int argc, char *argv[])\ + {\ + int list = 0;\ + LIST_PARAMS(X_FIND_PARAMS)\ + struct passwd *user;\ + struct libcontacts_contact **contacts;\ + struct libcontacts_##CAT **elems, *elem;\ + size_t i;\ + \ + ARGBEGIN {\ + LIST_PARAMS(X_FIND_ARGPARSE)\ + case 'L':\ + list = 1;\ + break;\ + default:\ + usage();\ + } ARGEND;\ + \ + if (argc != 1 - list)\ + usage();\ + \ + errno = 0;\ + user = getpwuid(getuid());\ + if (!user)\ + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist");\ + \ + if (libcontacts_load_contacts(&contacts, user, 1))\ + eprintf("libcontacts_load_contacts:");\ + for (i = 0; contacts[i]; i++) {\ + if ((elems = contacts[i]->CATEGORY)) {\ + for (; (elem = *elems); elems++) {\ + if (!elem->DATUM)\ + continue;\ + LIST_PARAMS(X_FIND_LOOKUP)\ + if (list) {\ + PRINT_PREFIX_LIST(DATUM)\ + printf("%s (%s)\n", contacts[i]->id, elem->DATUM);\ + } else if (!strcmp(elem->DATUM, argv[0])) {\ + PRINT_PREFIX_LOOKUP(DATUM)\ + printf("%s\n", contacts[i]->id);\ + }\ + }\ + }\ + libcontacts_contact_destroy(contacts[i]);\ + free(contacts[i]);\ + }\ + free(contacts);\ + \ + if (fflush(stdout) || ferror(stdout) || fclose(stdout))\ + eprintf("printf:");\ + \ + return 0;\ + } |