Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

clean up after brute merge

  • Loading branch information...
commit 726b7897ef6a56ea8361aa686d16e921e0812950 1 parent 50acfd6
@mauke authored
View
10 Makefile
@@ -7,16 +7,16 @@ CFLAGS_DEBUG=
PACKAGE=unibilium
PKG_MAJOR=1
-PKG_MINOR=0
-PKG_REVISION=1
+PKG_MINOR=1
+PKG_REVISION=0
PKG_VERSION=$(PKG_MAJOR).$(PKG_MINOR).$(PKG_REVISION)
# I am implementation $LT_REVISION of binary interface $LT_CURRENT, which is
# a superset of all interfaces back to $LT_CURRENT - $LT_AGE.
-LT_REVISION=1
-LT_CURRENT=1
-LT_AGE=1
+LT_REVISION=0
+LT_CURRENT=2
+LT_AGE=2
PREFIX=/usr/local
LIBDIR=$(PREFIX)/lib
View
35 doc/sparchways.h.pod
@@ -1,35 +0,0 @@
-=pod
-
-=head1 NAME
-
-sparchways.h - terminfo format string interpreter
-
-=head1 SYNOPSIS
-
- #include "sparchways.h"
-
-=head1 DESCRIPTION
-
-This library provides a simple and generic interpreter for terminfo format strings.
-
-=head2 Types
-
-The following types are provided:
-
-=over
-
-=item sparch_var_t
-
-A union with two members, C<int i> and C<char *p>. It represents the values
-used in format string operations.
-
-=back
-
-=head1 SEE ALSO
-
-L<terminfo(5)>,
-L<unibilium.h(3)>,
-L<sparch_format(3)>,
-L<sparch_run(3)>
-
-=cut
View
24 doc/sparch_format.pod → doc/unibi_format.pod
@@ -2,26 +2,28 @@
=head1 NAME
-sparch_format, sparch_run - interpret a terminfo format string
+unibi_format, unibi_run - interpret a terminfo format string
=head1 SYNOPSIS
- void sparch_format(
- sparch_var_t var_dyn[26],
- sparch_var_t var_static[26],
+ #include <unibilium.h>
+
+ void unibi_format(
+ unibi_var_t var_dyn[26],
+ unibi_var_t var_static[26],
const char *fmt,
- sparch_var_t param[9],
+ unibi_var_t param[9],
void (*out)(void *, const char *, size_t),
void *ctx1,
void (*pad)(void *, size_t, int, int),
void *ctx2
);
- size_t sparch_run(const char *fmt, sparch_var_t param[9], char *p, size_t n);
+ size_t unibi_run(const char *fmt, unibi_var_t param[9], char *p, size_t n);
=head1 DESCRIPTION
-C<sparch_format> takes a format string I<fmt> and executes it. All output is
+C<unibi_format> takes a format string I<fmt> and executes it. All output is
done by (possibly repeated) calls to I<out>. In the calls to I<out> the first
argument is always I<ctx1>, the second argument is a pointer to a chunk of
data, and the third argument is a count specifying the size of the chunk in
@@ -41,7 +43,7 @@ The values of I<param> are used for the format codes C<%p1> .. C<%p9>; the
values of I<var_dyn> and I<var_static> are used for the so-called
dynamic/static variables C<%Pa> .. C<%Pz> and C<%PA> .. C<%PZ>, respectively.
-C<sparch_run> is a wrapper around C<sparch_format>. It passes two arrays (each
+C<unibi_run> is a wrapper around C<unibi_format>. It passes two arrays (each
initialized to 26 zeroes) as I<var_dyn> and I<var_static>. I<fmt> and I<param>
are passed on unchanged. It ignores padding and places all normal output in the
buffer pointed to by I<p>. I<n> is the size of the buffer; at most I<n> bytes
@@ -49,12 +51,12 @@ will be written to I<p>.
=head1 RETURN VALUE
-C<sparch_run> returns the number of bytes that would have been written if the
+C<unibi_run> returns the number of bytes that would have been written if the
buffer was big enough. Thus the number of valid bytes in I<p> after a call to
-C<sparch_run> is the minimum of I<n> and the return value of C<sparch_run>.
+C<unibi_run> is the minimum of I<n> and the return value of C<unibi_run>.
=head1 SEE ALSO
-L<sparchways.h(3)>
+L<unibilium.h(3)>
=cut
View
62 doc/unibi_run.pod
@@ -0,0 +1,62 @@
+=pod
+
+=head1 NAME
+
+unibi_format, unibi_run - interpret a terminfo format string
+
+=head1 SYNOPSIS
+
+ #include <unibilium.h>
+
+ void unibi_format(
+ unibi_var_t var_dyn[26],
+ unibi_var_t var_static[26],
+ const char *fmt,
+ unibi_var_t param[9],
+ void (*out)(void *, const char *, size_t),
+ void *ctx1,
+ void (*pad)(void *, size_t, int, int),
+ void *ctx2
+ );
+
+ size_t unibi_run(const char *fmt, unibi_var_t param[9], char *p, size_t n);
+
+=head1 DESCRIPTION
+
+C<unibi_format> takes a format string I<fmt> and executes it. All output is
+done by (possibly repeated) calls to I<out>. In the calls to I<out> the first
+argument is always I<ctx1>, the second argument is a pointer to a chunk of
+data, and the third argument is a count specifying the size of the chunk in
+bytes.
+
+I<pad> is used when the format string contains C<< $<...> >> padding
+instructions. In the calls to I<pad> the first argument is always I<ctx2>, the
+second argument is the delay in tenths of milliseconds, the third argument is a
+boolean flag indicating whether C<*> (proportional delay) was specified in the
+format string, and the fourth argument is a boolean flag indicating whether
+C</> (forced padding) was specified in the format string. Thus a format string
+of C<< $<5/> >> would translate into C<pad(ctx2, 50, 0, 1)>. You may pass a
+null pointer for I<pad>; in that case padding instructions are silently
+skipped.
+
+The values of I<param> are used for the format codes C<%p1> .. C<%p9>; the
+values of I<var_dyn> and I<var_static> are used for the so-called
+dynamic/static variables C<%Pa> .. C<%Pz> and C<%PA> .. C<%PZ>, respectively.
+
+C<unibi_run> is a wrapper around C<unibi_format>. It passes two arrays (each
+initialized to 26 zeroes) as I<var_dyn> and I<var_static>. I<fmt> and I<param>
+are passed on unchanged. It ignores padding and places all normal output in the
+buffer pointed to by I<p>. I<n> is the size of the buffer; at most I<n> bytes
+will be written to I<p>.
+
+=head1 RETURN VALUE
+
+C<unibi_run> returns the number of bytes that would have been written if the
+buffer was big enough. Thus the number of valid bytes in I<p> after a call to
+C<unibi_run> is the minimum of I<n> and the return value of C<unibi_run>.
+
+=head1 SEE ALSO
+
+L<unibilium.h(3)>
+
+=cut
View
9 doc/unibilium.h.pod
@@ -25,6 +25,11 @@ The following types are provided:
The main type. It represents a terminfo entry. Most functions take a pointer to
this structure.
+=item unibi_var_t
+
+A union with two members, C<int i> and C<char *p>. It represents the values
+used in format string operations.
+
=item enum unibi_boolean
An enumeration of boolean capabilities. It has the following elements:
@@ -1109,6 +1114,8 @@ L<unibi_add_ext_num(3)>,
L<unibi_add_ext_str(3)>,
L<unibi_del_ext_bool(3)>,
L<unibi_del_ext_num(3)>,
-L<unibi_del_ext_str(3)>
+L<unibi_del_ext_str(3)>,
+L<unibi_format(3)>,
+L<unibi_run(3)>
=cut
View
390 sparchways.c
@@ -1,390 +0,0 @@
-/* Copyright 2011 Lukas Mai.
- *
- * This library is under the GNU Lesser General Public License;
- * see the file LGPLv3 for details.
- */
-
-#include "sparchways.h"
-
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define UC(F, C) (F((unsigned char)(C)))
-
-#define COUNTOF(A) (sizeof (A) / sizeof *(A))
-
-#define BITTY(A, B, C) (!!(A) << 0 | !!(B)<< 1 | !!(C) << 2)
-
-static void dput(
- char t,
- const char *fmt,
- int w,
- int p,
- sparch_var_t x,
- void (*out)(void *, const char *, size_t),
- void *ctx
-) {
- char buf[512];
- buf[0] = '\0';
- switch (BITTY(t == 's', w != -1, p != -1)) {
- case BITTY(0, 0, 0): snprintf(buf, sizeof buf, fmt, x.i); break;
- case BITTY(0, 0, 1): snprintf(buf, sizeof buf, fmt, p, x.i); break;
- case BITTY(0, 1, 0): snprintf(buf, sizeof buf, fmt, w, x.i); break;
- case BITTY(0, 1, 1): snprintf(buf, sizeof buf, fmt, w, p, x.i); break;
- case BITTY(1, 0, 0): snprintf(buf, sizeof buf, fmt, x.p); break;
- case BITTY(1, 0, 1): snprintf(buf, sizeof buf, fmt, p, x.p); break;
- case BITTY(1, 1, 0): snprintf(buf, sizeof buf, fmt, w, x.p); break;
- case BITTY(1, 1, 1): snprintf(buf, sizeof buf, fmt, w, p, x.p); break;
- }
- out(ctx, buf, strlen(buf));
-}
-
-static long cstrtol(const char *s, const char **pp) {
- long r;
- char *tmp;
- r = strtol(s, &tmp, 10);
- *pp = tmp;
- return r;
-}
-
-void sparch_format(
- sparch_var_t var_dyn[26],
- sparch_var_t var_static[26],
- const char *fmt,
- sparch_var_t param[9],
- void (*out)(void *, const char *, size_t),
- void *ctx1,
- void (*pad)(void *, size_t, int, int),
- void *ctx2
-) {
- const sparch_var_t zero = {0};
- sparch_var_t stack[123] = {{0}};
- size_t sp = 0;
-
-#define POP() (sp ? stack[--sp] : zero)
-#define PUSH(X) do { if (sp < COUNTOF(stack)) { stack[sp++] = (X); } } while (0)
-#define PUSHi(N) do { sparch_var_t tmp_; tmp_.i = (N); PUSH(tmp_); } while (0)
-
- while (*fmt) {
- {
- size_t r = strcspn(fmt, "%$");
- if (r) {
- out(ctx1, fmt, r);
- fmt += r;
- if (!*fmt) {
- break;
- }
- }
- }
-
- if (*fmt == '$') {
- ++fmt;
- if (*fmt == '<' && UC(isdigit, fmt[1])) {
- int scale = 0, force = 0;
- const char *v = fmt + 1;
- size_t n = cstrtol(v, &v);
- n *= 10;
- if (*v == '.') {
- ++v;
- }
- if (UC(isdigit, *v)) {
- n += *v++ - '0';
- }
- if (*v == '/') {
- ++v;
- force = 1;
- if (*v == '*') {
- ++v;
- scale = 1;
- }
- } else if (*v == '*') {
- ++v;
- scale = 1;
- if (*v == '/') {
- ++v;
- force = 1;
- }
- }
- if (*v == '>') {
- fmt = v + 1;
- if (pad) {
- pad(ctx2, n, scale, force);
- }
- } else {
- out(ctx1, fmt - 1, 1);
- }
- } else {
- out(ctx1, fmt - 1, 1);
- }
- continue;
- }
-
- assert(*fmt == '%');
- ++fmt;
-
- if (UC(isdigit, *fmt) || (*fmt && strchr(":# .doxX", *fmt))) {
- enum {
- FlagAlt = 1,
- FlagSpc = 2,
- FlagSgn = 4,
- FlagLft = 8,
- FlagZro = 16
- };
- int flags = 0, width = -1, prec = -1;
- const char *v = fmt;
- if (*v == ':') {
- ++v;
- }
- while (1) {
- switch (*v++) {
- case '#': flags |= FlagAlt; continue;
- case ' ': flags |= FlagSpc; continue;
- case '0': flags |= FlagZro; continue;
- case '+': flags |= FlagSgn; continue;
- case '-': flags |= FlagLft; continue;
- }
- --v;
- break;
- }
- if (UC(isdigit, *v)) {
- width = cstrtol(v, &v);
- }
- if (*v == '.' && UC(isdigit, v[1])) {
- ++v;
- prec = cstrtol(v, &v);
- }
- if (*v && strchr("doxXs", *v)) {
- char gen[sizeof "%# +-0*.*d"], *g = gen;
- *g++ = '%';
- if (flags & FlagAlt) { *g++ = '#'; }
- if (flags & FlagSpc) { *g++ = ' '; }
- if (flags & FlagSgn) { *g++ = '+'; }
- if (flags & FlagLft) { *g++ = '-'; }
- if (flags & FlagZro) { *g++ = '0'; }
- if (width != -1) { *g++ = '*'; }
- if (prec != -1) { *g++ = '.'; *g++ = '*'; }
- *g++ = *v;
- *g = '\0';
- dput(*v, gen, width, prec, POP(), out, ctx1);
- fmt = v;
- } else {
- out(ctx1, fmt - 1, 2);
- }
- ++fmt;
- continue;
- }
-
- switch (*fmt++) {
- default:
- out(ctx1, fmt - 2, 2);
- break;
-
- case '\0':
- --fmt;
- out(ctx1, "%", 1);
- break;
-
- case '%':
- out(ctx1, "%", 1);
- break;
-
- case 'c': {
- unsigned char c;
- c = POP().i;
- out(ctx1, (char *)&c, 1);
- break;
- }
-
- case 's': {
- char *s;
- s = POP().p;
- out(ctx1, s, strlen(s));
- break;
- }
-
- case 'p':
- if (*fmt >= '1' && *fmt <= '9') {
- size_t n = *fmt++ - '1';
- PUSH(param[n]);
- } else {
- out(ctx1, fmt - 2, 2);
- }
- break;
-
- case 'P':
- if (*fmt >= 'a' && *fmt <= 'z') {
- ++fmt;
- var_dyn[*fmt - 'a'] = POP();
- } else if (*fmt >= 'A' && *fmt <= 'Z') {
- ++fmt;
- var_static[*fmt - 'A'] = POP();
- } else {
- out(ctx1, fmt - 2, 2);
- }
- break;
-
- case 'g':
- if (*fmt >= 'a' && *fmt <= 'z') {
- ++fmt;
- PUSH(var_dyn[*fmt - 'a']);
- } else if (*fmt >= 'A' && *fmt <= 'Z') {
- ++fmt;
- PUSH(var_static[*fmt - 'A']);
- } else {
- out(ctx1, fmt - 2, 2);
- }
- break;
-
- case '\'':
- if (*fmt && fmt[1] == '\'') {
- PUSHi((unsigned char)*fmt);
- fmt += 2;
- } else {
- out(ctx1, fmt - 2, 2);
- }
- break;
-
- case '{': {
- size_t r = strspn(fmt, "0123456789");
- if (r && fmt[r] == '}') {
- PUSHi(atoi(fmt));
- fmt += r + 1;
- } else {
- out(ctx1, fmt - 2, 2);
- }
- break;
- }
-
- case 'l':
- PUSHi(strlen(POP().p));
- break;
-
- case 'i':
- ++param[0].i;
- ++param[1].i;
- break;
-
- case '?':
- break;
-
- case 't': {
- int c = POP().i;
- if (!c) {
- size_t nesting = 0;
- for (; *fmt; ++fmt) {
- if (*fmt == '%') {
- ++fmt;
- if (*fmt == '?') {
- ++nesting;
- } else if (*fmt == ';' || *fmt == 'e') {
- if (!nesting) {
- ++fmt;
- break;
- }
- --nesting;
- } else if (!*fmt) {
- break;
- }
- }
- }
- }
- break;
- }
-
- case 'e': {
- size_t nesting = 0;
- for (; *fmt; ++fmt) {
- if (*fmt == '%') {
- ++fmt;
- if (*fmt == '?') {
- ++nesting;
- } else if (*fmt == ';') {
- if (!nesting) {
- ++fmt;
- break;
- }
- --nesting;
- } else if (!*fmt) {
- break;
- }
- }
- }
- break;
- }
-
- case ';':
- break;
-
-#define ARITH2(C, O) \
- case (C): { \
- sparch_var_t x, y; \
- y = POP(); \
- x = POP(); \
- PUSHi(x.i O y.i); \
- } break
-
- ARITH2('+', +);
- ARITH2('-', -);
- ARITH2('*', *);
- ARITH2('/', /);
- ARITH2('m', %);
- ARITH2('&', &);
- ARITH2('|', |);
- ARITH2('^', ^);
- ARITH2('=', ==);
- ARITH2('<', <);
- ARITH2('>', >);
- ARITH2('A', &&);
- ARITH2('O', ||);
-
-#undef ARITH2
-
-#define ARITH1(C, O) \
- case (C): \
- PUSHi(O POP().i); \
- break
-
- ARITH1('!', !);
- ARITH1('~', ~);
-
-#undef ARITH1
- }
- }
-
-#undef PUSHi
-#undef PUSH
-#undef POP
-}
-
-typedef struct {
- char *p;
- size_t n, w;
-} run_ctx_t;
-
-static size_t xmin(size_t a, size_t b) {
- return a < b ? a : b;
-}
-
-static void out(void *vctx, const char *p, size_t n) {
- run_ctx_t *ctx = vctx;
- size_t k = xmin(n, ctx->n);
- ctx->w += n;
- memcpy(ctx->p, p, k);
- ctx->p += k;
- ctx->n -= k;
-}
-
-size_t sparch_run(const char *fmt, sparch_var_t param[9], char *p, size_t n) {
- sparch_var_t vars[26 + 26] = {{0}};
- run_ctx_t ctx;
-
- ctx.p = p;
- ctx.n = n;
- ctx.w = 0;
-
- sparch_format(vars, vars + 26, fmt, param, out, &ctx, NULL, NULL);
- return ctx.w;
-}
View
30 sparchways.h
@@ -1,30 +0,0 @@
-/* Copyright 2011 Lukas Mai.
- *
- * This library is under the GNU Lesser General Public License;
- * see the file LGPLv3 for details.
- */
-
-#ifndef GUARD_SPARCHWAYS_H_
-#define GUARD_SPARCHWAYS_H_
-
-#include <stddef.h>
-
-typedef union {
- int i;
- char *p;
-} sparch_var_t;
-
-void sparch_format(
- sparch_var_t [26],
- sparch_var_t [26],
- const char *,
- sparch_var_t [9],
- void (*)(void *, const char *, size_t),
- void *,
- void (*)(void *, size_t, int, int),
- void *
-);
-
-size_t sparch_run(const char *, sparch_var_t [9], char *, size_t);
-
-#endif /* GUARD_SPARCHWAYS_H_ */
View
9 sparchways.pc.in
@@ -1,9 +0,0 @@
-libdir=@LIBDIR@
-includedir=@INCDIR@
-version=@VERSION@
-
-Name: sparchways
-Description: terminfo format string interpreter
-Version: ${version}
-Libs: -L${libdir} -lsparchways
-Cflags: -I${includedir}
View
5 sparchput.c → tools/unibi-put.c
@@ -5,7 +5,6 @@
*/
#include "unibilium.h"
-#include "sparchways.h"
#include <stdio.h>
#include <stdlib.h>
@@ -65,7 +64,7 @@ int main(int argc, char **argv) {
fputs(fmt, stdout);
return 0;
}
- sparch_var_t vars[9] = {{0}};
+ unibi_var_t vars[9] = {{0}};
switch (i) {
#define REQ(N) do { if (argc - 2 < (N)) { fprintf(stderr, "%s: %s: missing argument\n", argv[0], argv[1]); return 4; } } while (0)
@@ -101,7 +100,7 @@ int main(int argc, char **argv) {
}
}
char buf[1024];
- size_t r = sparch_run(fmt, vars, buf, sizeof buf);
+ size_t r = unibi_run(fmt, vars, buf, sizeof buf);
fwrite(buf, 1, r, stdout);
return 0;
}
View
385 unibilium.c
@@ -1,6 +1,6 @@
/*
-Copyright 2008, 2010, 2012 Lukas Mai.
+Copyright 2008, 2010, 2012, 2013 Lukas Mai.
This file is part of unibilium.
@@ -26,6 +26,8 @@ along with unibilium. If not, see <http://www.gnu.org/licenses/>.
#include <assert.h>
#include <string.h>
#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
#define ASSERT_RETURN(COND, VAL) do { \
assert(COND); \
@@ -921,3 +923,384 @@ void unibi_del_ext_str(unibi_term *t, size_t i) {
}
}
+
+static void dput(
+ char t,
+ const char *fmt,
+ int w,
+ int p,
+ unibi_var_t x,
+ void (*out)(void *, const char *, size_t),
+ void *ctx
+) {
+ char buf[512];
+ buf[0] = '\0';
+
+#define BITTY(A, B, C) (!!(A) << 0 | !!(B) << 1 | !!(C) << 2)
+
+ switch (BITTY(t == 's', w != -1, p != -1)) {
+ case BITTY(0, 0, 0): snprintf(buf, sizeof buf, fmt, x.i); break;
+ case BITTY(0, 0, 1): snprintf(buf, sizeof buf, fmt, p, x.i); break;
+ case BITTY(0, 1, 0): snprintf(buf, sizeof buf, fmt, w, x.i); break;
+ case BITTY(0, 1, 1): snprintf(buf, sizeof buf, fmt, w, p, x.i); break;
+ case BITTY(1, 0, 0): snprintf(buf, sizeof buf, fmt, x.p); break;
+ case BITTY(1, 0, 1): snprintf(buf, sizeof buf, fmt, p, x.p); break;
+ case BITTY(1, 1, 0): snprintf(buf, sizeof buf, fmt, w, x.p); break;
+ case BITTY(1, 1, 1): snprintf(buf, sizeof buf, fmt, w, p, x.p); break;
+ }
+
+#undef BITTY
+
+ out(ctx, buf, strlen(buf));
+}
+
+static long cstrtol(const char *s, const char **pp) {
+ long r;
+ char *tmp;
+ r = strtol(s, &tmp, 10);
+ *pp = tmp;
+ return r;
+}
+
+void unibi_format(
+ unibi_var_t var_dyn[26],
+ unibi_var_t var_static[26],
+ const char *fmt,
+ unibi_var_t param[9],
+ void (*out)(void *, const char *, size_t),
+ void *ctx1,
+ void (*pad)(void *, size_t, int, int),
+ void *ctx2
+) {
+ const unibi_var_t zero = {0};
+ unibi_var_t stack[123] = {{0}};
+ size_t sp = 0;
+
+#define UC(F, C) (F((unsigned char)(C)))
+
+#define POP() (sp ? stack[--sp] : zero)
+#define PUSH(X) do { if (sp < COUNTOF(stack)) { stack[sp++] = (X); } } while (0)
+#define PUSHi(N) do { unibi_var_t tmp_; tmp_.i = (N); PUSH(tmp_); } while (0)
+
+ while (*fmt) {
+ {
+ size_t r = strcspn(fmt, "%$");
+ if (r) {
+ out(ctx1, fmt, r);
+ fmt += r;
+ if (!*fmt) {
+ break;
+ }
+ }
+ }
+
+ if (*fmt == '$') {
+ ++fmt;
+ if (*fmt == '<' && UC(isdigit, fmt[1])) {
+ int scale = 0, force = 0;
+ const char *v = fmt + 1;
+ size_t n = cstrtol(v, &v);
+ n *= 10;
+ if (*v == '.') {
+ ++v;
+ }
+ if (UC(isdigit, *v)) {
+ n += *v++ - '0';
+ }
+ if (*v == '/') {
+ ++v;
+ force = 1;
+ if (*v == '*') {
+ ++v;
+ scale = 1;
+ }
+ } else if (*v == '*') {
+ ++v;
+ scale = 1;
+ if (*v == '/') {
+ ++v;
+ force = 1;
+ }
+ }
+ if (*v == '>') {
+ fmt = v + 1;
+ if (pad) {
+ pad(ctx2, n, scale, force);
+ }
+ } else {
+ out(ctx1, fmt - 1, 1);
+ }
+ } else {
+ out(ctx1, fmt - 1, 1);
+ }
+ continue;
+ }
+
+ assert(*fmt == '%');
+ ++fmt;
+
+ if (UC(isdigit, *fmt) || (*fmt && strchr(":# .doxX", *fmt))) {
+ enum {
+ FlagAlt = 1,
+ FlagSpc = 2,
+ FlagSgn = 4,
+ FlagLft = 8,
+ FlagZro = 16
+ };
+ int flags = 0, width = -1, prec = -1;
+ const char *v = fmt;
+ if (*v == ':') {
+ ++v;
+ }
+ while (1) {
+ switch (*v++) {
+ case '#': flags |= FlagAlt; continue;
+ case ' ': flags |= FlagSpc; continue;
+ case '0': flags |= FlagZro; continue;
+ case '+': flags |= FlagSgn; continue;
+ case '-': flags |= FlagLft; continue;
+ }
+ --v;
+ break;
+ }
+ if (UC(isdigit, *v)) {
+ width = cstrtol(v, &v);
+ }
+ if (*v == '.' && UC(isdigit, v[1])) {
+ ++v;
+ prec = cstrtol(v, &v);
+ }
+ if (*v && strchr("doxXs", *v)) {
+ char gen[sizeof "%# +-0*.*d"], *g = gen;
+ *g++ = '%';
+ if (flags & FlagAlt) { *g++ = '#'; }
+ if (flags & FlagSpc) { *g++ = ' '; }
+ if (flags & FlagSgn) { *g++ = '+'; }
+ if (flags & FlagLft) { *g++ = '-'; }
+ if (flags & FlagZro) { *g++ = '0'; }
+ if (width != -1) { *g++ = '*'; }
+ if (prec != -1) { *g++ = '.'; *g++ = '*'; }
+ *g++ = *v;
+ *g = '\0';
+ dput(*v, gen, width, prec, POP(), out, ctx1);
+ fmt = v;
+ } else {
+ out(ctx1, fmt - 1, 2);
+ }
+ ++fmt;
+ continue;
+ }
+
+ switch (*fmt++) {
+ default:
+ out(ctx1, fmt - 2, 2);
+ break;
+
+ case '\0':
+ --fmt;
+ out(ctx1, "%", 1);
+ break;
+
+ case '%':
+ out(ctx1, "%", 1);
+ break;
+
+ case 'c': {
+ unsigned char c;
+ c = POP().i;
+ out(ctx1, (char *)&c, 1);
+ break;
+ }
+
+ case 's': {
+ char *s;
+ s = POP().p;
+ out(ctx1, s, strlen(s));
+ break;
+ }
+
+ case 'p':
+ if (*fmt >= '1' && *fmt <= '9') {
+ size_t n = *fmt++ - '1';
+ PUSH(param[n]);
+ } else {
+ out(ctx1, fmt - 2, 2);
+ }
+ break;
+
+ case 'P':
+ if (*fmt >= 'a' && *fmt <= 'z') {
+ ++fmt;
+ var_dyn[*fmt - 'a'] = POP();
+ } else if (*fmt >= 'A' && *fmt <= 'Z') {
+ ++fmt;
+ var_static[*fmt - 'A'] = POP();
+ } else {
+ out(ctx1, fmt - 2, 2);
+ }
+ break;
+
+ case 'g':
+ if (*fmt >= 'a' && *fmt <= 'z') {
+ ++fmt;
+ PUSH(var_dyn[*fmt - 'a']);
+ } else if (*fmt >= 'A' && *fmt <= 'Z') {
+ ++fmt;
+ PUSH(var_static[*fmt - 'A']);
+ } else {
+ out(ctx1, fmt - 2, 2);
+ }
+ break;
+
+ case '\'':
+ if (*fmt && fmt[1] == '\'') {
+ PUSHi((unsigned char)*fmt);
+ fmt += 2;
+ } else {
+ out(ctx1, fmt - 2, 2);
+ }
+ break;
+
+ case '{': {
+ size_t r = strspn(fmt, "0123456789");
+ if (r && fmt[r] == '}') {
+ PUSHi(atoi(fmt));
+ fmt += r + 1;
+ } else {
+ out(ctx1, fmt - 2, 2);
+ }
+ break;
+ }
+
+ case 'l':
+ PUSHi(strlen(POP().p));
+ break;
+
+ case 'i':
+ ++param[0].i;
+ ++param[1].i;
+ break;
+
+ case '?':
+ break;
+
+ case 't': {
+ int c = POP().i;
+ if (!c) {
+ size_t nesting = 0;
+ for (; *fmt; ++fmt) {
+ if (*fmt == '%') {
+ ++fmt;
+ if (*fmt == '?') {
+ ++nesting;
+ } else if (*fmt == ';' || *fmt == 'e') {
+ if (!nesting) {
+ ++fmt;
+ break;
+ }
+ --nesting;
+ } else if (!*fmt) {
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ case 'e': {
+ size_t nesting = 0;
+ for (; *fmt; ++fmt) {
+ if (*fmt == '%') {
+ ++fmt;
+ if (*fmt == '?') {
+ ++nesting;
+ } else if (*fmt == ';') {
+ if (!nesting) {
+ ++fmt;
+ break;
+ }
+ --nesting;
+ } else if (!*fmt) {
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case ';':
+ break;
+
+#define ARITH2(C, O) \
+ case (C): { \
+ unibi_var_t x, y; \
+ y = POP(); \
+ x = POP(); \
+ PUSHi(x.i O y.i); \
+ } break
+
+ ARITH2('+', +);
+ ARITH2('-', -);
+ ARITH2('*', *);
+ ARITH2('/', /);
+ ARITH2('m', %);
+ ARITH2('&', &);
+ ARITH2('|', |);
+ ARITH2('^', ^);
+ ARITH2('=', ==);
+ ARITH2('<', <);
+ ARITH2('>', >);
+ ARITH2('A', &&);
+ ARITH2('O', ||);
+
+#undef ARITH2
+
+#define ARITH1(C, O) \
+ case (C): \
+ PUSHi(O POP().i); \
+ break
+
+ ARITH1('!', !);
+ ARITH1('~', ~);
+
+#undef ARITH1
+ }
+ }
+
+#undef PUSHi
+#undef PUSH
+#undef POP
+
+#undef UC
+}
+
+typedef struct {
+ char *p;
+ size_t n, w;
+} run_ctx_t;
+
+static size_t xmin(size_t a, size_t b) {
+ return a < b ? a : b;
+}
+
+static void out(void *vctx, const char *p, size_t n) {
+ run_ctx_t *ctx = vctx;
+ size_t k = xmin(n, ctx->n);
+ ctx->w += n;
+ memcpy(ctx->p, p, k);
+ ctx->p += k;
+ ctx->n -= k;
+}
+
+size_t unibi_run(const char *fmt, unibi_var_t param[9], char *p, size_t n) {
+ unibi_var_t vars[26 + 26] = {{0}};
+ run_ctx_t ctx;
+
+ ctx.p = p;
+ ctx.n = n;
+ ctx.w = 0;
+
+ unibi_format(vars, vars + 26, fmt, param, out, &ctx, NULL, NULL);
+ return ctx.w;
+}
View
21 unibilium.h
@@ -3,7 +3,7 @@
/*
-Copyright 2008, 2010, 2011, 2012 Lukas Mai.
+Copyright 2008, 2010-2013 Lukas Mai.
This file is part of unibilium.
@@ -603,4 +603,23 @@ void unibi_del_ext_bool(unibi_term *, size_t);
void unibi_del_ext_num(unibi_term *, size_t);
void unibi_del_ext_str(unibi_term *, size_t);
+
+typedef union {
+ int i;
+ char *p;
+} unibi_var_t;
+
+void unibi_format(
+ unibi_var_t [26],
+ unibi_var_t [26],
+ const char *,
+ unibi_var_t [9],
+ void (*)(void *, const char *, size_t),
+ void *,
+ void (*)(void *, size_t, int, int),
+ void *
+);
+
+size_t unibi_run(const char *, unibi_var_t [9], char *, size_t);
+
#endif /* GUARD_UNIBILIUM_H_ */
Please sign in to comment.
Something went wrong with that request. Please try again.