1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2013 Garrett D'Amore <garrett@damore.org> 14 * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 15 */ 16 17 /* 18 * LC_TIME database generation routines for localedef. 19 */ 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <errno.h> 24 #include <sys/types.h> 25 #include <string.h> 26 #include <unistd.h> 27 #include "localedef.h" 28 #include "parser.tab.h" 29 #include "timelocal.h" 30 31 struct lc_time tm; 32 33 void 34 init_time(void) 35 { 36 (void) memset(&tm, 0, sizeof (tm)); 37 } 38 39 void 40 add_time_str(wchar_t *wcs) 41 { 42 char *str; 43 44 if ((str = to_mb_string(wcs)) == NULL) { 45 INTERR; 46 return; 47 } 48 free(wcs); 49 50 switch (last_kw) { 51 case T_D_T_FMT: 52 tm.c_fmt = str; 53 break; 54 case T_D_FMT: 55 tm.x_fmt = str; 56 break; 57 case T_T_FMT: 58 tm.X_fmt = str; 59 break; 60 case T_T_FMT_AMPM: 61 tm.ampm_fmt = str; 62 break; 63 case T_DATE_FMT: 64 /* 65 * This one is a Solaris extension, Too bad date just 66 * doesn't use %c, which would be simpler. 67 */ 68 tm.date_fmt = str; 69 break; 70 case T_ERA_D_FMT: 71 case T_ERA_T_FMT: 72 case T_ERA_D_T_FMT: 73 /* Silently ignore it. */ 74 break; 75 default: 76 free(str); 77 INTERR; 78 break; 79 } 80 } 81 82 static void 83 add_list(const char *ptr[], char *str, int limit) 84 { 85 int i; 86 for (i = 0; i < limit; i++) { 87 if (ptr[i] == NULL) { 88 ptr[i] = str; 89 return; 90 } 91 } 92 errf(_("too many list elements")); 93 } 94 95 void 96 add_time_list(wchar_t *wcs) 97 { 98 char *str; 99 100 if ((str = to_mb_string(wcs)) == NULL) { 101 INTERR; 102 return; 103 } 104 free(wcs); 105 106 switch (last_kw) { 107 case T_ABMON: 108 add_list(tm.mon, str, 12); 109 break; 110 case T_MON: 111 add_list(tm.month, str, 12); 112 break; 113 case T_ABDAY: 114 add_list(tm.wday, str, 7); 115 break; 116 case T_DAY: 117 add_list(tm.weekday, str, 7); 118 break; 119 case T_AM_PM: 120 if (tm.am == NULL) { 121 tm.am = str; 122 } else if (tm.pm == NULL) { 123 tm.pm = str; 124 } else { 125 errf(_("too many list elements")); 126 } 127 break; 128 case T_ALT_DIGITS: 129 case T_ERA: 130 free(str); 131 break; 132 default: 133 free(str); 134 INTERR; 135 break; 136 } 137 } 138 139 void 140 check_time_list(void) 141 { 142 switch (last_kw) { 143 case T_ABMON: 144 if (tm.mon[11] != NULL) 145 return; 146 break; 147 case T_MON: 148 if (tm.month[11] != NULL) 149 return; 150 break; 151 case T_ABDAY: 152 if (tm.wday[6] != NULL) 153 return; 154 break; 155 case T_DAY: 156 if (tm.weekday[6] != NULL) 157 return; 158 break; 159 case T_AM_PM: 160 if (tm.pm != NULL) 161 return; 162 break; 163 case T_ERA: 164 case T_ALT_DIGITS: 165 return; 166 default: 167 errf(_("unknown list")); 168 break; 169 } 170 171 errf(_("too few items in list (%d)"), last_kw); 172 } 173 174 void 175 reset_time_list(void) 176 { 177 int i; 178 switch (last_kw) { 179 case T_ABMON: 180 for (i = 0; i < 12; i++) { 181 free((char *)tm.mon[i]); 182 tm.mon[i] = NULL; 183 } 184 break; 185 case T_MON: 186 for (i = 0; i < 12; i++) { 187 free((char *)tm.month[i]); 188 tm.month[i] = NULL; 189 } 190 break; 191 case T_ABDAY: 192 for (i = 0; i < 7; i++) { 193 free((char *)tm.wday[i]); 194 tm.wday[i] = NULL; 195 } 196 break; 197 case T_DAY: 198 for (i = 0; i < 7; i++) { 199 free((char *)tm.weekday[i]); 200 tm.weekday[i] = NULL; 201 } 202 break; 203 case T_AM_PM: 204 free((char *)tm.am); 205 tm.am = NULL; 206 free((char *)tm.pm); 207 tm.pm = NULL; 208 break; 209 } 210 } 211 212 213 void 214 dump_time(void) 215 { 216 FILE *f; 217 int i; 218 219 if ((f = open_category()) == NULL) { 220 return; 221 } 222 223 for (i = 0; i < 12; i++) { 224 if (putl_category(tm.mon[i], f) == EOF) { 225 return; 226 } 227 } 228 for (i = 0; i < 12; i++) { 229 if (putl_category(tm.month[i], f) == EOF) { 230 return; 231 } 232 } 233 for (i = 0; i < 7; i++) { 234 if (putl_category(tm.wday[i], f) == EOF) { 235 return; 236 } 237 } 238 for (i = 0; i < 7; i++) { 239 if (putl_category(tm.weekday[i], f) == EOF) { 240 return; 241 } 242 } 243 244 /* 245 * NOTE: If date_fmt is not specified, then we'll default to 246 * using the %c for date. This is reasonable for most 247 * locales, although for reasons that I don't understand 248 * Solaris historically has had a seperate format for date. 249 */ 250 if ((putl_category(tm.X_fmt, f) == EOF) || 251 (putl_category(tm.x_fmt, f) == EOF) || 252 (putl_category(tm.c_fmt, f) == EOF) || 253 (putl_category(tm.am, f) == EOF) || 254 (putl_category(tm.pm, f) == EOF) || 255 (putl_category(tm.date_fmt ? tm.date_fmt : tm.c_fmt, f) == EOF) || 256 (putl_category(tm.ampm_fmt, f) == EOF)) { 257 return; 258 } 259 close_category(f); 260 } 261