pkg-format.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * libdpkg - Debian packaging suite library routines
  3. * pkg-format.c - customizable package formatting
  4. *
  5. * Copyright © 2001 Wichert Akkerman <wakkerma@debian.org>
  6. *
  7. * This is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include <compat.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <dpkg/i18n.h>
  26. #include <dpkg/dpkg.h>
  27. #include <dpkg/dpkg-db.h>
  28. #include <dpkg/parsedump.h>
  29. #include <dpkg/pkg-format.h>
  30. enum pkg_format_type {
  31. invalid,
  32. string,
  33. field,
  34. };
  35. struct pkg_format_node {
  36. struct pkg_format_node *next;
  37. enum pkg_format_type type;
  38. size_t width;
  39. int pad;
  40. char *data;
  41. };
  42. static struct pkg_format_node *
  43. pkg_format_node_new(void)
  44. {
  45. struct pkg_format_node *buf;
  46. buf = m_malloc(sizeof(*buf));
  47. buf->type = invalid;
  48. buf->next = NULL;
  49. buf->data = NULL;
  50. buf->width = 0;
  51. buf->pad = 0;
  52. return buf;
  53. }
  54. static bool
  55. parsefield(struct pkg_format_node *cur, const char *fmt, const char *fmtend)
  56. {
  57. int len;
  58. const char *ws;
  59. len = fmtend - fmt + 1;
  60. ws = memchr(fmt, ';', len);
  61. if (ws) {
  62. char *endptr;
  63. long w;
  64. w = strtol(ws + 1, &endptr, 0);
  65. if (endptr[0] != '}') {
  66. fprintf(stderr,
  67. _("invalid character `%c' in field width\n"),
  68. *endptr);
  69. return false;
  70. }
  71. if (w < 0) {
  72. cur->pad = 1;
  73. cur->width = (size_t)-w;
  74. } else
  75. cur->width = (size_t)w;
  76. len = ws - fmt;
  77. }
  78. cur->type = field;
  79. cur->data = m_malloc(len + 1);
  80. memcpy(cur->data, fmt, len);
  81. cur->data[len] = '\0';
  82. return true;
  83. }
  84. static bool
  85. parsestring(struct pkg_format_node *cur, const char *fmt, const char *fmtend)
  86. {
  87. int len;
  88. char *write;
  89. len = fmtend - fmt + 1;
  90. cur->type = string;
  91. write = cur->data = m_malloc(len + 1);
  92. while (fmt <= fmtend) {
  93. if (*fmt == '\\') {
  94. fmt++;
  95. switch (*fmt) {
  96. case 'n':
  97. *write = '\n';
  98. break;
  99. case 't':
  100. *write = '\t';
  101. break;
  102. case 'r':
  103. *write = '\r';
  104. break;
  105. case '\\':
  106. default:
  107. *write = *fmt;
  108. break;
  109. }
  110. } else
  111. *write = *fmt;
  112. write++;
  113. fmt++;
  114. }
  115. *write = '\0';
  116. return true;
  117. }
  118. void
  119. pkg_format_free(struct pkg_format_node *head)
  120. {
  121. struct pkg_format_node *next;
  122. while (head) {
  123. next = head->next;
  124. free(head->data);
  125. free(head);
  126. head = next;
  127. }
  128. }
  129. struct pkg_format_node *
  130. pkg_format_parse(const char *fmt)
  131. {
  132. struct pkg_format_node *head;
  133. struct pkg_format_node *cur;
  134. const char *fmtend;
  135. head = cur = NULL;
  136. while (*fmt) {
  137. if (cur)
  138. cur = cur->next = pkg_format_node_new();
  139. else
  140. head = cur = pkg_format_node_new();
  141. if (fmt[0] == '$' && fmt[1] == '{') {
  142. fmtend = strchr(fmt, '}');
  143. if (!fmtend) {
  144. fprintf(stderr,
  145. _("Closing brace missing in format\n"));
  146. pkg_format_free(head);
  147. return NULL;
  148. }
  149. if (!parsefield(cur, fmt + 2, fmtend - 1)) {
  150. pkg_format_free(head);
  151. return NULL;
  152. }
  153. fmt = fmtend + 1;
  154. } else {
  155. fmtend = fmt;
  156. do {
  157. fmtend += 1;
  158. fmtend = strchr(fmtend, '$');
  159. } while (fmtend && fmtend[1] != '{');
  160. if (!fmtend)
  161. fmtend = fmt + strlen(fmt);
  162. if (!parsestring(cur, fmt, fmtend - 1)) {
  163. pkg_format_free(head);
  164. return NULL;
  165. }
  166. fmt = fmtend;
  167. }
  168. }
  169. return head;
  170. }
  171. void
  172. pkg_format_show(const struct pkg_format_node *head,
  173. struct pkginfo *pkg, struct pkgbin *pif)
  174. {
  175. struct varbuf vb = VARBUF_INIT, fb = VARBUF_INIT, wb = VARBUF_INIT;
  176. while (head) {
  177. bool ok;
  178. char fmt[16];
  179. ok = false;
  180. if (head->width > 0)
  181. snprintf(fmt, 16, "%%%s%zus",
  182. ((head->pad) ? "-" : ""), head->width);
  183. else
  184. strcpy(fmt, "%s");
  185. if (head->type == string) {
  186. varbuf_printf(&fb, fmt, head->data);
  187. ok = true;
  188. } else if (head->type == field) {
  189. const struct fieldinfo *fip;
  190. for (fip = fieldinfos; fip->name; fip++)
  191. if (strcasecmp(head->data, fip->name) == 0) {
  192. fip->wcall(&wb, pkg, pif, 0, fip);
  193. varbuf_end_str(&wb);
  194. varbuf_printf(&fb, fmt, wb.buf);
  195. varbuf_reset(&wb);
  196. ok = true;
  197. break;
  198. }
  199. if (!fip->name) {
  200. const struct arbitraryfield *afp;
  201. for (afp = pif->arbs; afp; afp = afp->next)
  202. if (strcasecmp(head->data, afp->name) == 0) {
  203. varbuf_printf(&fb, fmt, afp->value);
  204. ok = true;
  205. break;
  206. }
  207. }
  208. }
  209. if (ok) {
  210. size_t len = strlen(fb.buf);
  211. if ((head->width > 0) && (len > head->width))
  212. len = head->width;
  213. varbuf_add_buf(&vb, fb.buf, len);
  214. }
  215. varbuf_reset(&fb);
  216. head = head->next;
  217. }
  218. if (vb.buf) {
  219. varbuf_end_str(&vb);
  220. fputs(vb.buf, stdout);
  221. }
  222. varbuf_destroy(&wb);
  223. varbuf_destroy(&fb);
  224. varbuf_destroy(&vb);
  225. }