pointtools

Simple point utilities to hold text presentations.
git clone git://r-36.net/pointtools
Log | Files | Refs | README | LICENSE

md2point.c (3365B)


      1 /*
      2  * See LICENSE for license details.
      3  */
      4 #include <err.h>
      5 #include <limits.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <unistd.h>
     10 
     11 #ifdef NEED_STRLCPY /* OpenBSD implementation */
     12 size_t
     13 strlcpy(char *dst, const char *src, size_t dsize) {
     14 	const char *osrc = src;
     15 	size_t nleft = dsize;
     16 
     17 	if (nleft != 0) {
     18 		while (--nleft != 0) {
     19 			if ((*dst++= *src++) == '\0')
     20 				break;
     21 		}
     22 	}
     23 
     24 	if (nleft == 0) {
     25 		if (dsize != 0)
     26 			*dst = '\0';
     27 		while (*src++)
     28 			;
     29 	}
     30 
     31 	return(src - osrc - 1);
     32 }
     33 #endif /* NEED_STRLCPY */
     34 
     35 /* from git://bitreich.org/utf8expr */
     36 size_t
     37 utf8strlen(const char *s)
     38 {
     39 	size_t i;
     40 
     41 	for (i = 0; *s; s++) {
     42 		if ((*s & 0xc0) != 0x80)
     43 			i++;
     44 	}
     45 
     46 	return i;
     47 }
     48 
     49 void
     50 fprintunderline(FILE *fp, const char *str)
     51 {
     52 	size_t i, len;
     53 
     54 	fprintf(fp, "\n  %s\n  ", str);
     55 	len = utf8strlen(str);
     56 	for (i = 0; i <= len; ++i)
     57 		fputs("=", fp);
     58 	fputs("\n\n", fp);
     59 }
     60 
     61 void
     62 escapechars(char *s)
     63 {
     64 	for (; *s; s++) {
     65 		if (*s == '\n') {
     66 			*s = '\0';
     67 			return;
     68 		}
     69 
     70 		/*
     71 		 * Only allow ASCII printable a-zA-Z0-9 for simplicity.
     72 		 */
     73 		if ((*s >= 'a' && *s <= 'z')
     74 				|| (*s >= 'A' && *s <= 'Z')
     75 				|| (*s >= '0' && *s <= '9')) {
     76 			continue;
     77 		}
     78 		*s = '_';
     79 	}
     80 }
     81 
     82 void
     83 fprintesc(FILE *fp, const char *s)
     84 {
     85 	int intext = 0;
     86 
     87 	fputs("  ", fp);
     88 	for (; *s; s++) {
     89 		switch (*s) {
     90 		case ' ':
     91 			fputc(' ', fp);
     92 			break;
     93 		case '\t':
     94 			fprintf(fp, "        ");
     95 			break;
     96 		case '*':
     97 			if (intext) {
     98 				fputc(*s, fp);
     99 			} else {
    100 				fputc('o', fp);
    101 				intext = 1;
    102 			}
    103 			break;
    104 		default:
    105 			intext = 1;
    106 			fputc(*s, fp);
    107 			break;
    108 		}
    109 	}
    110 	fputs("\n", fp);
    111 }
    112 
    113 void
    114 mkfilename(char *fname, char *str, size_t bufsiz, int i)
    115 {
    116 	char buf[PATH_MAX];
    117 
    118 	strlcpy(buf, str, sizeof(buf));
    119 	escapechars(buf);
    120 	snprintf(fname, bufsiz, "%.4d-%s.txt", i, buf);
    121 }
    122 
    123 void
    124 copyfile(char *dst, char *src)
    125 {
    126 	int c;
    127 	FILE *fsrc, *fdst;
    128 
    129 	if (src[0] == '\0' || dst[0] == '\0' ||
    130 		!(fsrc = fopen(src, "r")) || !(fdst = fopen(dst, "w")))
    131 		err(1, "copyfile: %s -> %s", src, dst);
    132 
    133 	while ((c = fgetc(fsrc)) != EOF)
    134 		fputc(c, fdst);
    135 
    136 	fclose(fsrc);
    137 	fclose(fdst);
    138 }
    139 
    140 int
    141 main(void)
    142 {
    143 	size_t i = 0;
    144 	char *line = NULL;
    145 	size_t linesize = 0;
    146 	ssize_t linelen;
    147 	char title[PATH_MAX] = "", fname[PATH_MAX] = "", fname_old[PATH_MAX] = "";
    148 	FILE *fp = NULL;
    149 
    150 	while ((linelen = getline(&line, &linesize, stdin)) > 0) {
    151 		if (line[linelen - 1] == '\n')
    152 			line[--linelen] = '\0';
    153 
    154 		if (line[0] == '%')
    155 			continue;
    156 
    157 		if (line[0] == '\\') {
    158 			if (line[1] == '\0')
    159 				continue;
    160 
    161 			/* ignore text before first header */
    162 			if (fp)
    163 				fprintesc(fp, line+1);
    164 		} else if (line[0] == '#' && line[1] == '#') {
    165 			if (fp) {
    166 				fclose(fp);
    167 				fp = NULL;
    168 			}
    169 			strlcpy(title, line + 2, sizeof(title));
    170 			mkfilename(fname, title, sizeof(fname), i++);
    171 			if (!(fp = fopen(fname, "w")))
    172 				err(1, "fopen: %s", fname);
    173 			if (line[2] == '\0')
    174 				fputs("\n", fp);
    175 			else
    176 				fprintunderline(fp, title);
    177 		} else if (linelen > 5 && !strncmp(line, "#pause", linelen)) {
    178 			if (fp) {
    179 				fclose(fp);
    180 				fp = NULL;
    181 			}
    182 			strlcpy(fname_old, fname, sizeof(fname_old));
    183 			mkfilename(fname, title, sizeof(fname), i++);
    184 			copyfile(fname, fname_old);
    185 			if (fname[0] != '\0' && !(fp = fopen(fname, "a")))
    186 				err(1, "fopen: %s", fname);
    187 		} else {
    188 			/* ignore text before first header */
    189 			if (fp)
    190 				fprintesc(fp, line);
    191 		}
    192 	}
    193 
    194 	free(line);
    195 
    196 	return 0;
    197 }