diff options
author | Mattias Andrée <maandree@kth.se> | 2021-04-12 00:07:26 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2021-04-12 00:07:26 +0200 |
commit | 1a21982ebc2747a694558c6e82cea54bd5dbead9 (patch) | |
tree | 42a145211772e876d85dfcc65655fa3130016313 /common.h | |
parent | Improve set-contact- utils (diff) | |
download | contacts-1a21982ebc2747a694558c6e82cea54bd5dbead9.tar.gz contacts-1a21982ebc2747a694558c6e82cea54bd5dbead9.tar.bz2 contacts-1a21982ebc2747a694558c6e82cea54bd5dbead9.tar.xz |
Deduplicate code and make some minor improvements
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r-- | common.h | 160 |
1 files changed, 160 insertions, 0 deletions
@@ -25,3 +25,163 @@ void print_birthday(struct libcontacts_birthday *bday, const struct tm *now); /* common-address.c */ int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, double *lon, double *lon_min, double *lon_max); + + + +#ifndef LIST_BOOL_PARAMS +# define LIST_BOOL_PARAMS(X) +#endif + +#define X_USAGE_UPPER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + "[-"UPPERS" old-"DISPLAY"] " + +#define X_USAGE_LOWER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + "[-"LOWERS" new-"DISPLAY"] " + +#define X_USAGE_BOOL(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + "[-"UPPERS" | -"LOWERS"] " + +#define X_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)\ + int set_##VAR = -1; + +#define X_ARGPARSE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + case UPPERC:\ + add = 0;\ + if (lookup_##VAR)\ + usage();\ + lookup_##VAR = ARG();\ + break;\ + case LOWERC:\ + edit = 1;\ + if (VAR)\ + usage();\ + VAR = ARG();\ + break; + +#define X_BOOL_ARGPARSE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + case UPPERC:\ + if (set_##VAR >= 0)\ + usage();\ + set_##VAR = 0;\ + break;\ + case LOWERC:\ + if (set_##VAR >= 0)\ + usage();\ + set_##VAR = 1;\ + break; + +#define X_LOWER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + LOWERS + +#define X_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)\ + if (remove && set_##VAR >= 0 && contact.CATEGORY[i]->is_##VAR != set_##VAR)\ + continue; + +#define X_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)\ + if (set_##VAR >= 0)\ + contact.CATEGORY[i]->is_##VAR = set_##VAR; + +#define X_ADD(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\ + contact.CATEGORY[i]->VAR = VAR; + +#define X_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");\ + \ + int\ + main(int argc, char *argv[])\ + {\ + int add = 1, edit = 0, remove = 0;\ + LIST_PARAMS(X_PARAMS)\ + LIST_BOOL_PARAMS(X_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)\ + case 'u':\ + remove = 1;\ + break;\ + default:\ + usage();\ + } ARGEND;\ + \ + if (argc != 1 || !*argv[0] || strchr(argv[0], '/'))\ + usage();\ + \ + if (remove == edit) {\ + if (edit)\ + usage();\ + eprintf("at least one of -"LIST_PARAMS(X_LOWER)"u is required\n");\ + }\ + \ + if (add)\ + edit = 0;\ + \ + errno = 0;\ + user = getpwuid(getuid());\ + if (!user)\ + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist");\ + \ + if (libcontacts_load_contact(argv[0], &contact, user)) {\ + eprintf("libcontacts_load_contact %s: %s\n", argv[0],\ + errno ? strerror(errno) : "contact file is malformatted");\ + }\ + \ + i = 0;\ + if ((edit || remove) && contact.CATEGORY) {\ + for (; contact.CATEGORY[i]; i++) {\ + LIST_PARAMS(X_LOOKUP)\ + LIST_BOOL_PARAMS(X_BOOL_LOOKUP)\ + break;\ + }\ + if (!contact.CATEGORY[i]) {\ + libcontacts_contact_destroy(&contact);\ + return 0;\ + } else if (!edit) {\ + r = &contact.CATEGORY[i];\ + libcontacts_##CAT##_destroy(*r);\ + free(*r);\ + for (w = r++; (*w++ = *r++););\ + } else {\ + LIST_PARAMS(X_CHANGE)\ + LIST_BOOL_PARAMS(X_BOOL_SET)\ + }\ + } else if (!edit && !remove) {\ + if (contact.CATEGORY)\ + for (; contact.CATEGORY[i]; i++);\ + 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)\ + }\ + \ + if (libcontacts_save_contact(&contact, user))\ + eprintf("libcontacts_save_contact %s:", argv[0]);\ + \ + if (!r) {\ + LIST_PARAMS(X_RESTORE)\ + }\ + \ + libcontacts_contact_destroy(&contact);\ + return 0;\ + } |