We actually do not need to maintain two tables. I've merged it with pacman currently and I don't take that approach. I only did it with alpm-dump because it was quicker to just dump out statically initialized tables for testing. Was probably a poor choice for a demonstration. I have a table building function instead, along the lines of: void build_table(char **table, alpm_pkgfrom_t from) { memset(table, 0, sizeof(char *) * LAST_ENTRY); table[ENTRY_REPOSITORY] = _("Repository"); table[ENTRY_NAME] = _("Name"); table[ENTRY_VERSION] = _("Version"); table[ENTRY_DESCRIPTION] = _("Description"); table[ENTRY_ARCHITECTURE] = _("Architecture"); table[ENTRY_URL] = _("URL"); // snip if(from == ALPM_PKG_FROM_SYNCDB || config->op_s_info > 1) { table[ENTRY_REQUIRED] = _("Required By"); table[ENTRY_OPTIONAL_FOR] = _("Optional For"); } // more branches } So rather, the actual effective change, as far as design goes, is this allows us to break dump_pkg_full into two discrete steps rather than all at once; figure out what to print before you start printing. In fact, all this table building stuff can entirely stay inside package.c if we change dump_pkg_full to expect an alpm_list_t * instead of a alpm_pkg_t *. It doesn't need to be exposed to sync.c/query.c (I think, I'm not fully confident I've integrated the new system everywhere).