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