aboutsummaryrefslogtreecommitdiffstats
path: root/common.h
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2021-04-12 00:07:26 +0200
committerMattias Andrée <maandree@kth.se>2021-04-12 00:07:26 +0200
commit1a21982ebc2747a694558c6e82cea54bd5dbead9 (patch)
tree42a145211772e876d85dfcc65655fa3130016313 /common.h
parentImprove set-contact- utils (diff)
downloadcontacts-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.h160
1 files changed, 160 insertions, 0 deletions
diff --git a/common.h b/common.h
index 6aecf6c..d1345f5 100644
--- a/common.h
+++ b/common.h
@@ -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;\
+ }