summaryrefslogtreecommitdiff
path: root/mimetypes/prloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mimetypes/prloc.c')
-rw-r--r--mimetypes/prloc.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/mimetypes/prloc.c b/mimetypes/prloc.c
new file mode 100644
index 0000000..d53883c
--- /dev/null
+++ b/mimetypes/prloc.c
@@ -0,0 +1,172 @@
+#include <stdlib.h>
+#include <errno.h>
+#include "locus.h"
+
+size_t
+nprlen (unsigned x)
+{
+ size_t len = 1;
+ while (x /= 10)
+ len++;
+ return len;
+}
+
+size_t
+lpprlen (struct locus_point const *lp)
+{
+ size_t len = 0;
+
+ if (lp->file)
+ {
+ len = strlen (lp->file) + 1 + nprlen (lp->line);
+ if (lp->col)
+ len += 1 + nprlen (lp->col);
+ }
+ return len;
+}
+
+size_t
+lrprlen (struct locus_range const *lr)
+{
+ size_t len;
+
+ len = lpprlen (&lr->end);
+ if (len)
+ len++;
+ len += lpprlen (&lr->beg);
+ return len;
+}
+
+enum
+ {
+ PR_NON = 0x00,
+ PR_FIL = 0x01,
+ PR_LIN = 0x02,
+ PR_COL = 0x04,
+ PR_ALL = PR_FIL|PR_LIN|PR_COL
+ };
+
+static ssize_t
+_numprint (char *p, unsigned num)
+{
+ size_t len = 0;
+ char *q;
+ do
+ {
+ p[len++] = (num % 10) + '0';
+ }
+ while (num /= 10);
+ for (q = p + len - 1; q > p; p++, q--)
+ {
+ char t = *p;
+ *p = *q;
+ *q = t;
+ }
+ return len;
+}
+
+ssize_t
+_lpprint (char *buf, struct locus_point const *lp, int pr)
+{
+ size_t n = 0;
+
+ if (!lp->file)
+ pr &= ~PR_FIL;
+ if (!lp->col)
+ pr &= ~PR_COL;
+
+ if (pr & PR_FIL)
+ {
+ n = strlen (lp->file);
+ memcpy (buf, lp->file, n);
+ }
+ if (pr & PR_LIN)
+ {
+ if (pr & PR_FIL)
+ buf[n++] = ':';
+ n += _numprint (buf + n, lp->line);
+ }
+ if (pr & PR_COL)
+ {
+ if (pr & PR_LIN)
+ buf[n++] = '.';
+ n += _numprint (buf + n, lp->col);
+ }
+ return n;
+}
+
+ssize_t
+locus_point_format (char **pbuf, size_t *psize, struct locus_point const *lp)
+{
+ char *buf;
+ size_t size;
+ size_t prlen;
+
+ if (!pbuf || !psize || !lp)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ buf = *pbuf;
+ size = *psize;
+
+ prlen = lpprlen (lp);
+ if (prlen + 1 > size)
+ {
+ size = prlen + 1;
+ buf = realloc (buf, size);
+ if (!buf)
+ return -1;
+ *pbuf = buf;
+ *psize = size;
+ }
+ return _lpprint (buf, lp, PR_ALL);
+}
+
+ssize_t
+locus_range_format (char **pbuf, size_t *psize, struct locus_range const *lr)
+{
+ char *buf;
+ size_t size;
+ size_t prlen;
+ size_t n;
+
+ if (!pbuf || !psize || !lr)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ buf = *pbuf;
+ size = *psize;
+
+ prlen = lrprlen (lr);
+ if (prlen + 1 > size)
+ {
+ size = prlen + 1;
+ buf = realloc (buf, size);
+ if (!buf)
+ return -1;
+ *pbuf = buf;
+ *psize = size;
+ }
+ n = _lpprint (buf, &lr->beg, PR_ALL);
+ buf += n;
+ if (lr->end.file)
+ {
+ int flag = PR_NON;
+
+ if (!locus_point_same_file (&lr->beg, &lr->end))
+ flag = PR_ALL;
+ else if (lr->beg.line != lr->end.line)
+ flag = PR_LIN|PR_COL;
+ else if (lr->beg.col && lr->beg.col != lr->end.col)
+ flag = PR_COL;
+
+ if (flag != PR_NON)
+ {
+ buf[n++] = '-';
+ n += _lpprint (buf + n, &lr->end, flag);
+ }
+ }
+ return n;
+}

Return to:

Send suggestions and report system problems to the System administrator.