unroff/src/subst.c

99 lines
2.6 KiB
C

/* $Revision: 1.9 $
*/
/* The implementation of the Scheme primitive `substitute'
*/
#include "unroff.h"
Object p_substitute(int ac, Object *av) {
Object str = *av;
static Buffer *fp;
char *p, *ep, *s, *t, *endp;
int len;
long a;
char buf[30];
char *fmt;
time_t now;
extern char *macros, *format, *directory;
Check_Type(str, T_String);
if (!fp)
fp = buffer_new(0);
buffer_clear(fp);
for (p = STRING(str)->data, ep = p + STRING(str)->size; p < ep; p++) {
if (*p == '%') {
for (s = ++p; p < ep && *p != '%'; p++)
;
if (p == ep)
Primitive_Error("missing `%' delimiter");
len = p-s;
t = safe_malloc(len+1); /* Make copy to add \0. C sucks... */
memcpy(t, s, len);
t[len] = 0;
fmt = 0;
if (len == 0)
s = "%";
else if (strcmp(t, "macros") == 0)
s = macros;
else if (strcmp(t, "format") == 0)
s = format;
else if (strcmp(t, "directory") == 0)
s = directory;
else if (strcmp(t, "progname") == 0)
s = get_progname();
else if (strcmp(t, "filepos") == 0) { /* ` file:lno' */
if (istream_is_open()) {
buffer_putc(fp, ' ');
buffer_puts(fp, curr_istream_target(),
strlen(curr_istream_target()));
sprintf(buf, ":%lu:", curr_istream_lno());
s = buf;
} else s = "";
} else if (strcmp(t, "tmpname") == 0) {
s = tmpnam(0);
} else if (strcmp(t, "version") == 0) {
sprintf(buf, "%s", get_version_string());
s = buf;
} else if (strcmp(t, "weekday") == 0) {
fmt = "%a";
} else if (strcmp(t, "weekday+") == 0) {
fmt = "%A";
} else if (strcmp(t, "weekdaynum")== 0) {
fmt = "%w";
} else if (strcmp(t, "monthname") == 0) {
fmt = "%b";
} else if (strcmp(t, "monthname+") == 0) {
fmt = "%B";
} else if (strcmp(t, "day") == 0) {
fmt = "%d";
} else if (strcmp(t, "month") == 0) {
fmt = "%m";
} else if (strcmp(t, "year") == 0) {
fmt = "%Y";
} else if (strcmp(t, "date") == 0) {
fmt = "%x";
} else if (strcmp(t, "time") == 0) {
fmt = "%X";
} else if ((a = strtol(t, &endp, 10)), endp == t+len) {
if (a < 1 || a > ac-1)
Primitive_Error("no argument for %-specifier");
Check_Type(av[a], T_String);
buffer_puts(fp, STRING(av[a])->data, STRING(av[a])->size);
s = "";
} else if ((s = getenv(t)) == 0)
s = "";
if (fmt) {
now = time(0);
if (strftime(buf, sizeof buf, fmt, localtime(&now)) == 0)
s = "";
else s = buf;
}
free(t);
buffer_puts(fp, s, strlen(s));
} else
buffer_putc(fp, *p);
}
return Make_String(fp->data, fp->size);
}