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 }