1 /* $Id: out.c,v 1.2 2009/10/27 21:40:07 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <sys/types.h> 18 19 #include <assert.h> 20 #include <ctype.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <time.h> 25 26 #include "out.h" 27 28 /* 29 * Convert a `scaling unit' to a consistent form, or fail. Scaling 30 * units are documented in groff.7, mdoc.7, man.7. 31 */ 32 int 33 a2roffsu(const char *src, struct roffsu *dst, enum roffscale def) 34 { 35 char buf[BUFSIZ], hasd; 36 int i; 37 enum roffscale unit; 38 39 if ('\0' == *src) 40 return(0); 41 42 i = hasd = 0; 43 44 switch (*src) { 45 case ('+'): 46 src++; 47 break; 48 case ('-'): 49 buf[i++] = *src++; 50 break; 51 default: 52 break; 53 } 54 55 if ('\0' == *src) 56 return(0); 57 58 while (i < BUFSIZ) { 59 if ( ! isdigit((u_char)*src)) { 60 if ('.' != *src) 61 break; 62 else if (hasd) 63 break; 64 else 65 hasd = 1; 66 } 67 buf[i++] = *src++; 68 } 69 70 if (BUFSIZ == i || (*src && *(src + 1))) 71 return(0); 72 73 buf[i] = '\0'; 74 75 switch (*src) { 76 case ('c'): 77 unit = SCALE_CM; 78 break; 79 case ('i'): 80 unit = SCALE_IN; 81 break; 82 case ('P'): 83 unit = SCALE_PC; 84 break; 85 case ('p'): 86 unit = SCALE_PT; 87 break; 88 case ('f'): 89 unit = SCALE_FS; 90 break; 91 case ('v'): 92 unit = SCALE_VS; 93 break; 94 case ('m'): 95 unit = SCALE_EM; 96 break; 97 case ('\0'): 98 if (SCALE_MAX == def) 99 return(0); 100 unit = SCALE_BU; 101 break; 102 case ('u'): 103 unit = SCALE_BU; 104 break; 105 case ('M'): 106 unit = SCALE_MM; 107 break; 108 case ('n'): 109 unit = SCALE_EN; 110 break; 111 default: 112 return(0); 113 } 114 115 if ((dst->scale = atof(buf)) < 0) 116 dst->scale = 0; 117 dst->unit = unit; 118 dst->pt = hasd; 119 120 return(1); 121 } 122 123 124 /* 125 * Correctly writes the time in nroff form, which differs from standard 126 * form in that a space isn't printed in lieu of the extra %e field for 127 * single-digit dates. 128 */ 129 void 130 time2a(time_t t, char *dst, size_t sz) 131 { 132 struct tm tm; 133 char buf[5]; 134 char *p; 135 size_t nsz; 136 137 assert(sz > 1); 138 localtime_r(&t, &tm); 139 140 p = dst; 141 nsz = 0; 142 143 dst[0] = '\0'; 144 145 if (0 == (nsz = strftime(p, sz, "%B ", &tm))) 146 return; 147 148 p += (int)nsz; 149 sz -= nsz; 150 151 if (0 == strftime(buf, sizeof(buf), "%e, ", &tm)) 152 return; 153 154 nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz); 155 156 if (nsz >= sz) 157 return; 158 159 p += (int)nsz; 160 sz -= nsz; 161 162 (void)strftime(p, sz, "%Y", &tm); 163 } 164 165