00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "config.h"
00039 #include <stdio.h>
00040 #include <ctype.h>
00041 #include <sys/time.h>
00042 #include <time.h>
00043 #include <wchar.h>
00044 #include <limits.h>
00045 #include <stdlib.h>
00046 #include <string.h>
00047 #include <glib.h>
00048 #include "qof.h"
00049 #include "qofdate-p.h"
00050
00051 static QofLogModule log_module = QOF_MOD_DATE;
00052
00053 #define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
00054 #define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
00055
00056 #define FPRINTFTIME 0
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define SHR(a, b) \
00069 (-1 >> 1 == -1 \
00070 ? (a) >> (b) \
00071 : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
00072
00073
00074
00075
00076
00077 #define INT_strlen _BOUND(t) \
00078 ((sizeof (t) * CHAR_BIT - 1) * 146 / 485 + 2)
00079
00080
00081
00082 #define TM_YEAR_BASE 0
00083
00084 #define add(n, f) \
00085 do \
00086 { \
00087 gint _n = (n); \
00088 gint _delta = width - _n; \
00089 gint _incr = _n + (_delta > 0 ? _delta : 0); \
00090 if ((size_t) _incr >= maxsize - i) \
00091 return 0; \
00092 if (p) \
00093 { \
00094 if (digits == 0 && _delta > 0) \
00095 { \
00096 if (pad == ('0')) \
00097 memset_zero (p, _delta); \
00098 else \
00099 memset_space (p, _delta); \
00100 } \
00101 f; \
00102 p += FPRINTFTIME ? 0 : _n; \
00103 } \
00104 i += _incr; \
00105 } while (0)
00106
00107 # define add1(C) add (1, *p = C)
00108
00109 # define cpy(n, s) \
00110 add ((n), \
00111 if (to_lowcase) \
00112 memcpy_lowcase (p, (s), _n); \
00113 else if (to_uppcase) \
00114 memcpy_uppcase (p, (s), _n); \
00115 else \
00116 memcpy ((void *) p, (void const *) (s), _n))
00117
00118 #define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
00119 #define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
00120
00121
00122
00123
00124
00125 #define ISDIGIT(Ch) ((guint) (Ch) - ('0') <= 9)
00126
00127
00128
00129
00130 #define ISO_WEEK_START_WDAY 1
00131 #define ISO_WEEK1_WDAY 4
00132 #define YDAY_MINIMUM (-366)
00133
00134 static const mbstate_t mbstate_zero;
00135 const gchar *format_end = NULL;
00136
00137 static gchar *
00138 memcpy_lowcase (gchar * dest, const gchar * src, size_t len)
00139 {
00140 while (len-- > 0)
00141 dest[len] = TOLOWER ((guchar) src[len], loc);
00142 return dest;
00143 }
00144
00145 static gchar *
00146 memcpy_uppcase (gchar * dest, const gchar * src, size_t len)
00147 {
00148 while (len-- > 0)
00149 dest[len] = TOUPPER ((guchar) src[len], loc);
00150 return dest;
00151 }
00152
00153 static gint
00154 iso_week_days (gint yday, gint wday)
00155 {
00156
00157 gint big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
00158 return (yday
00159 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
00160 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
00161 }
00162
00163 size_t
00164 strftime_case (gboolean upcase, gchar * s,
00165 size_t maxsize, const gchar *format, const QofDate *qd,
00166 gint ut, glong ns)
00167 {
00168 const gchar *zone;
00169 gint hour12 = qd->qd_hour;
00170 size_t i = 0;
00171 gchar *p = s;
00172 const gchar *f;
00173 QofDate copy = *qd;
00174 qd = ©
00175 zone = (const gchar *) qd->qd_zone;
00176 if (ut)
00177 {
00178 if (!(zone && *zone))
00179 zone = "GMT";
00180 }
00181 else
00182 {
00183
00184
00185 tzset ();
00186 }
00187
00188 if (hour12 > 12)
00189 hour12 -= 12;
00190 else if (hour12 == 0)
00191 hour12 = 12;
00192
00193 for (f = format; *f != '\0'; ++f)
00194 {
00195 gint pad = 0;
00196 gint modifier;
00197 gint digits = 0;
00198 glong number_value;
00199 guint u_number_value;
00200 gboolean negative_number;
00201 gboolean always_output_a_sign;
00202 gint tz_colon_mask;
00203 const gchar *subfmt;
00204 gchar sign_char;
00205 gchar *bufp;
00206 gchar buf[MAX_DATE_BUFFER];
00207 gint width = -1;
00208 gboolean to_lowcase = FALSE;
00209 gboolean to_uppcase = upcase;
00210 size_t colons;
00211 gboolean change_case = FALSE;
00212 gint format_char;
00213
00214 switch (*f)
00215 {
00216 case ('%'):
00217 break;
00218
00219 case ('\b'):
00220 case ('\t'):
00221 case ('\n'):
00222 case ('\v'):
00223 case ('\f'):
00224 case ('\r'):
00225 case (' '):
00226 case ('!'):
00227 case ('"'):
00228 case ('#'):
00229 case ('&'):
00230 case ('\''):
00231 case ('('):
00232 case (')'):
00233 case ('*'):
00234 case ('+'):
00235 case (','):
00236 case ('-'):
00237 case ('.'):
00238 case ('/'):
00239 case ('0'):
00240 case ('1'):
00241 case ('2'):
00242 case ('3'):
00243 case ('4'):
00244 case ('5'):
00245 case ('6'):
00246 case ('7'):
00247 case ('8'):
00248 case ('9'):
00249 case (':'):
00250 case (';'):
00251 case ('<'):
00252 case ('='):
00253 case ('>'):
00254 case ('?'):
00255 case ('A'):
00256 case ('B'):
00257 case ('C'):
00258 case ('D'):
00259 case ('E'):
00260 case ('F'):
00261 case ('G'):
00262 case ('H'):
00263 case ('I'):
00264 case ('J'):
00265 case ('K'):
00266 case ('L'):
00267 case ('M'):
00268 case ('N'):
00269 case ('O'):
00270 case ('P'):
00271 case ('Q'):
00272 case ('R'):
00273 case ('S'):
00274 case ('T'):
00275 case ('U'):
00276 case ('V'):
00277 case ('W'):
00278 case ('X'):
00279 case ('Y'):
00280 case ('Z'):
00281 case ('['):
00282 case ('\\'):
00283 case (']'):
00284 case ('^'):
00285 case ('_'):
00286 case ('a'):
00287 case ('b'):
00288 case ('c'):
00289 case ('d'):
00290 case ('e'):
00291 case ('f'):
00292 case ('g'):
00293 case ('h'):
00294 case ('i'):
00295 case ('j'):
00296 case ('k'):
00297 case ('l'):
00298 case ('m'):
00299 case ('n'):
00300 case ('o'):
00301 case ('p'):
00302 case ('q'):
00303 case ('r'):
00304 case ('s'):
00305 case ('t'):
00306 case ('u'):
00307 case ('v'):
00308 case ('w'):
00309 case ('x'):
00310 case ('y'):
00311 case ('z'):
00312 case ('{'):
00313 case ('|'):
00314 case ('}'):
00315 case ('~'):
00316
00317
00318
00319
00320 add1 (*f);
00321 continue;
00322
00323 default:
00324
00325
00326
00327 {
00328 mbstate_t mbstate = mbstate_zero;
00329 size_t len = 0;
00330 size_t fsize;
00331
00332 if (!format_end)
00333 format_end = f + strlen (f) + 1;
00334 fsize = format_end - f;
00335
00336 do
00337 {
00338 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
00339
00340 if (bytes == 0)
00341 break;
00342
00343 if (bytes == (size_t) - 2)
00344 {
00345 len += strlen (f + len);
00346 break;
00347 }
00348
00349 if (bytes == (size_t) - 1)
00350 {
00351 len++;
00352 break;
00353 }
00354
00355 len += bytes;
00356 }
00357 while (!mbsinit (&mbstate));
00358
00359 cpy (len, f);
00360 f += len - 1;
00361 continue;
00362 }
00363 }
00364
00365
00366 while (1)
00367 {
00368 switch (*++f)
00369 {
00370
00371 case ('_'):
00372 case ('-'):
00373 case ('0'):
00374 pad = *f;
00375 continue;
00376
00377
00378 case ('^'):
00379 to_uppcase = TRUE;
00380 continue;
00381 case ('#'):
00382 change_case = TRUE;
00383 continue;
00384
00385 default:
00386 break;
00387 }
00388 break;
00389 }
00390
00391
00392 if (ISDIGIT (*f))
00393 {
00394 width = 0;
00395 do
00396 {
00397 if (width > INT_MAX / 10
00398 || (width == INT_MAX / 10
00399 && *f - ('0') > INT_MAX % 10))
00400
00401 width = INT_MAX;
00402 else
00403 {
00404 width *= 10;
00405 width += *f - ('0');
00406 }
00407 ++f;
00408 }
00409 while (ISDIGIT (*f));
00410 }
00411
00412
00413 switch (*f)
00414 {
00415 case ('E'):
00416 case ('O'):
00417 modifier = *f++;
00418 break;
00419
00420 default:
00421 modifier = 0;
00422 break;
00423 }
00424
00425
00426 format_char = *f;
00427 switch (format_char)
00428 {
00429 #define DO_NUMBER(d, v) \
00430 digits = d; \
00431 number_value = v; goto do_number
00432 #define DO_SIGNED_NUMBER(d, negative, v) \
00433 digits = d; \
00434 negative_number = negative; \
00435 u_number_value = v; goto do_signed_number
00436
00437
00438
00439
00440 #define DO_TZ_OFFSET(d, negative, mask, v) \
00441 digits = d; \
00442 negative_number = negative; \
00443 tz_colon_mask = mask; \
00444 u_number_value = v; goto do_tz_offset
00445 #define DO_NUMBER_SPACEPAD(d, v) \
00446 digits = d; \
00447 number_value = v; goto do_number_spacepad
00448
00449 case ('%'):
00450 if (modifier != 0)
00451 goto bad_format;
00452 add1 (*f);
00453 break;
00454
00455 case ('a'):
00456 if (modifier != 0)
00457 goto bad_format;
00458 if (change_case)
00459 {
00460 to_uppcase = TRUE;
00461 to_lowcase = FALSE;
00462 }
00463 goto underlying_strftime;
00464
00465 case 'A':
00466 if (modifier != 0)
00467 goto bad_format;
00468 if (change_case)
00469 {
00470 to_uppcase = TRUE;
00471 to_lowcase = FALSE;
00472 }
00473 goto underlying_strftime;
00474
00475 case ('b'):
00476 case ('h'):
00477 if (change_case)
00478 {
00479 to_uppcase = TRUE;
00480 to_lowcase = FALSE;
00481 }
00482 if (modifier != 0)
00483 goto bad_format;
00484 goto underlying_strftime;
00485
00486 case ('B'):
00487 if (modifier != 0)
00488 goto bad_format;
00489 if (change_case)
00490 {
00491 to_uppcase = TRUE;
00492 to_lowcase = FALSE;
00493 }
00494 goto underlying_strftime;
00495
00496 case ('c'):
00497 if (modifier == ('O'))
00498 goto bad_format;
00499 goto underlying_strftime;
00500
00501 subformat:
00502 {
00503 size_t len = strftime_case (to_uppcase,
00504 NULL, ((size_t) - 1),
00505 subfmt, qd, ut, ns);
00506 add (len, strftime_case (to_uppcase, p,
00507 (maxsize - i), subfmt, qd, ut, ns));
00508 }
00509 break;
00510
00511 underlying_strftime:
00512 {
00513
00514 gchar ufmt[5];
00515 gchar *u = ufmt;
00516 gchar ubuf[1024];
00517 size_t len;
00518
00519
00520
00521 # ifdef strftime
00522 # undef strftime
00523 size_t strftime ();
00524 #endif
00525
00526
00527
00528 *u++ = ' ';
00529 *u++ = '%';
00530 if (modifier != 0)
00531 *u++ = modifier;
00532 *u++ = format_char;
00533 *u = '\0';
00534 {
00535 glong nanosecs;
00536 struct tm bad;
00537 if(!qof_date_to_struct_tm ((QofDate*)qd, &bad, &nanosecs))
00538 {
00539 PERR (" locale format out of range.");
00540 break;
00541 }
00542 len = strftime (ubuf, sizeof ubuf, ufmt, &bad);
00543 }
00544 if (len != 0)
00545 cpy (len - 1, ubuf + 1);
00546 }
00547 break;
00548
00549 case ('C'):
00550 if (modifier == ('O'))
00551 goto bad_format;
00552 if (modifier == ('E'))
00553 {
00554 goto underlying_strftime;
00555 }
00556
00557 {
00558
00559 gint century = qd->qd_year / 100 + TM_YEAR_BASE / 100;
00560 century -= qd->qd_year % 100 < 0 && 0 < century;
00561 DO_SIGNED_NUMBER (2,
00562 qd->qd_year < -TM_YEAR_BASE, century);
00563 }
00564
00565 case ('x'):
00566 if (modifier == ('O'))
00567 goto bad_format;
00568 goto underlying_strftime;
00569 case ('D'):
00570 if (modifier != 0)
00571 goto bad_format;
00572 subfmt = ("%m/%d/%y");
00573 goto subformat;
00574
00575 case ('d'):
00576 if (modifier == ('E'))
00577 goto bad_format;
00578
00579 DO_NUMBER (2, qd->qd_mday);
00580
00581 case ('e'):
00582 if (modifier == ('E'))
00583 goto bad_format;
00584
00585 DO_NUMBER_SPACEPAD (2, qd->qd_mday);
00586
00587
00588
00589 do_tz_offset:
00590 always_output_a_sign = TRUE;
00591 goto do_number_body;
00592
00593 do_number_spacepad:
00594
00595 if (pad != ('0') && pad != ('-'))
00596 pad = ('_');
00597
00598 do_number:
00599
00600 negative_number = number_value < 0;
00601 u_number_value = number_value;
00602
00603 do_signed_number:
00604 always_output_a_sign = FALSE;
00605 tz_colon_mask = 0;
00606
00607 do_number_body:
00608
00609
00610
00611
00612
00613 if (modifier == ('O') && !negative_number)
00614 {
00615 goto underlying_strftime;
00616 }
00617
00618 bufp = buf + sizeof (buf) / sizeof (buf[0]);
00619
00620 if (negative_number)
00621 u_number_value = -u_number_value;
00622
00623 do
00624 {
00625 if (tz_colon_mask & 1)
00626 *--bufp = ':';
00627 tz_colon_mask >>= 1;
00628 *--bufp = u_number_value % 10 + ('0');
00629 u_number_value /= 10;
00630 }
00631 while (u_number_value != 0 || tz_colon_mask != 0);
00632
00633 do_number_sign_and_padding:
00634 if (digits < width)
00635 digits = width;
00636
00637 sign_char = (negative_number ? ('-')
00638 : always_output_a_sign ? ('+') : 0);
00639
00640 if (pad == ('-'))
00641 {
00642 if (sign_char)
00643 add1 (sign_char);
00644 }
00645 else
00646 {
00647 gint padding =
00648 digits - (buf + (sizeof (buf) / sizeof (buf[0])) -
00649 bufp) - !!sign_char;
00650
00651 if (padding > 0)
00652 {
00653 if (pad == ('_'))
00654 {
00655 if ((size_t) padding >= maxsize - i)
00656 return 0;
00657
00658 if (p)
00659 memset_space (p, padding);
00660 i += padding;
00661 width = width > padding ? width - padding : 0;
00662 if (sign_char)
00663 add1 (sign_char);
00664 }
00665 else
00666 {
00667 if ((size_t) digits >= maxsize - i)
00668 return 0;
00669
00670 if (sign_char)
00671 add1 (sign_char);
00672
00673 if (p)
00674 memset_zero (p, padding);
00675 i += padding;
00676 width = 0;
00677 }
00678 }
00679 else
00680 {
00681 if (sign_char)
00682 add1 (sign_char);
00683 }
00684 }
00685
00686 cpy (buf + sizeof (buf) / sizeof (buf[0]) - bufp, bufp);
00687 break;
00688
00689 case ('F'):
00690 if (modifier != 0)
00691 goto bad_format;
00692 subfmt = ("%Y-%m-%d");
00693 goto subformat;
00694
00695 case ('H'):
00696 if (modifier == ('E'))
00697 goto bad_format;
00698
00699 DO_NUMBER (2, qd->qd_hour);
00700
00701 case ('I'):
00702 if (modifier == ('E'))
00703 goto bad_format;
00704
00705 DO_NUMBER (2, hour12);
00706
00707 case ('k'):
00708 if (modifier == ('E'))
00709 goto bad_format;
00710
00711 DO_NUMBER_SPACEPAD (2, qd->qd_hour);
00712
00713 case ('l'):
00714 if (modifier == ('E'))
00715 goto bad_format;
00716
00717 DO_NUMBER_SPACEPAD (2, hour12);
00718
00719 case ('j'):
00720 if (modifier == ('E'))
00721 goto bad_format;
00722
00723 DO_SIGNED_NUMBER (3, qd->qd_yday < -1, qd->qd_yday + 1U);
00724
00725 case ('M'):
00726 if (modifier == ('E'))
00727 goto bad_format;
00728
00729 DO_NUMBER (2, qd->qd_min);
00730
00731 case ('m'):
00732 if (modifier == ('E'))
00733 goto bad_format;
00734
00735 DO_SIGNED_NUMBER (2, qd->qd_mon < -1, qd->qd_mon);
00736
00737 case ('N'):
00738 if (modifier == ('E'))
00739 goto bad_format;
00740
00741 number_value = ns;
00742 if (width == -1)
00743 width = 9;
00744 else
00745 {
00746
00747 gint j;
00748 for (j = width; j < 9; j++)
00749 number_value /= 10;
00750 }
00751
00752 DO_NUMBER (width, number_value);
00753
00754 case ('n'):
00755 add1 (('\n'));
00756 break;
00757
00758 case ('P'):
00759 to_lowcase = TRUE;
00760 format_char = ('p');
00761
00762 case ('p'):
00763 if (change_case)
00764 {
00765 to_uppcase = FALSE;
00766 to_lowcase = TRUE;
00767 }
00768 goto underlying_strftime;
00769
00770 case ('R'):
00771 subfmt = ("%H:%M");
00772 goto subformat;
00773
00774 case ('r'):
00775 goto underlying_strftime;
00776
00777 case ('S'):
00778 if (modifier == ('E'))
00779 goto bad_format;
00780
00781 DO_NUMBER (2, qd->qd_sec);
00782
00783 case ('s'):
00784
00785
00786
00787 {
00788 glong nanosecs;
00789 QofTime *time;
00790 QofTimeSecs t;
00791
00792 time = qof_date_to_qtime ((QofDate*)qd);
00793 t = qof_time_get_secs (time);
00794 nanosecs = qof_time_get_nanosecs (time);
00795
00796
00797
00798
00799 bufp = buf + sizeof (buf) / sizeof (buf[0]);
00800 negative_number = t < 0;
00801
00802 do
00803 {
00804 gint d = t % 10;
00805 t /= 10;
00806 *--bufp = (negative_number ? -d : d) + ('0');
00807 }
00808 while (t != 0);
00809
00810 digits = 1;
00811 always_output_a_sign = FALSE;
00812 goto do_number_sign_and_padding;
00813 }
00814
00815 case ('X'):
00816 if (modifier == ('O'))
00817 goto bad_format;
00818 goto underlying_strftime;
00819 case ('T'):
00820 subfmt = ("%H:%M:%S");
00821 goto subformat;
00822
00823 case ('t'):
00824 add1 (('\t'));
00825 break;
00826
00827 case ('u'):
00828 DO_NUMBER (1, (qd->qd_wday - 1 + 7) % 7 + 1);
00829
00830 case ('U'):
00831 if (modifier == ('E'))
00832 goto bad_format;
00833
00834 DO_NUMBER (2, (qd->qd_yday - qd->qd_wday + 7) / 7);
00835
00836 case ('V'):
00837 case ('g'):
00838 case ('G'):
00839 if (modifier == ('E'))
00840 goto bad_format;
00841 {
00842 gint year_adjust = 0;
00843 gint days = iso_week_days (qd->qd_yday, qd->qd_wday);
00844
00845 if (days < 0)
00846 {
00847
00848 year_adjust = -1;
00849 days =
00850 iso_week_days (qd->qd_yday +
00851 (365 + qof_date_isleap (qd->qd_year - 1)),
00852 qd->qd_wday);
00853 }
00854 else
00855 {
00856 gint d =
00857 iso_week_days (qd->qd_yday - (365 +
00858 qof_date_isleap (qd->qd_year)),
00859 qd->qd_wday);
00860 if (0 <= d)
00861 {
00862
00863 year_adjust = 1;
00864 days = d;
00865 }
00866 }
00867
00868 switch (*f)
00869 {
00870 case ('g'):
00871 {
00872
00873 gint yy = (qd->qd_year % 100 + year_adjust) % 100;
00874 DO_NUMBER (2, (0 <= yy
00875 ? yy : qd->qd_year <
00876 -TM_YEAR_BASE -
00877 year_adjust ? -yy : yy + 100));
00878 }
00879
00880 case ('G'):
00881
00882 DO_SIGNED_NUMBER (4,
00883 qd->qd_year <
00884 -TM_YEAR_BASE - year_adjust,
00885 (qd->qd_year + (guint) TM_YEAR_BASE +
00886 year_adjust));
00887
00888 default:
00889 DO_NUMBER (2, days / 7 + 1);
00890 }
00891 }
00892
00893 case ('W'):
00894 if (modifier == ('E'))
00895 goto bad_format;
00896
00897 DO_NUMBER (2,
00898 (qd->qd_yday - (qd->qd_wday - 1 + 7) % 7 + 7) / 7);
00899
00900 case ('w'):
00901 if (modifier == ('E'))
00902 goto bad_format;
00903
00904 DO_NUMBER (1, qd->qd_wday);
00905
00906 case ('Y'):
00907 if (modifier == 'E')
00908 {
00909 goto underlying_strftime;
00910 }
00911 if (modifier == ('O'))
00912 goto bad_format;
00913 else
00914
00915 DO_SIGNED_NUMBER (4, qd->qd_year < -TM_YEAR_BASE,
00916 qd->qd_year + TM_YEAR_BASE);
00917
00918 case ('y'):
00919 if (modifier == ('E'))
00920 {
00921 goto underlying_strftime;
00922 }
00923
00924 {
00925 gint64 yy = qd->qd_year % 100;
00926 if (yy < 0)
00927 yy = qd->qd_year < -TM_YEAR_BASE ? -yy : yy + 100;
00928 DO_NUMBER (2, yy);
00929 }
00930
00931 case ('Z'):
00932 if (change_case)
00933 {
00934 to_uppcase = FALSE;
00935 to_lowcase = TRUE;
00936 }
00937
00938
00939 if (!(zone && *zone) && qd->qd_is_dst >= 0)
00940 zone = tzname[qd->qd_is_dst != 0];
00941 if (!zone)
00942 zone = "";
00943
00944 cpy (strlen (zone), zone);
00945 break;
00946
00947 case (':'):
00948
00949
00950 for (colons = 1; f[colons] == (':'); colons++)
00951 continue;
00952 if (f[colons] != ('z'))
00953 goto bad_format;
00954 f += colons;
00955 goto do_z_conversion;
00956
00957 case ('z'):
00958 colons = 0;
00959
00960 do_z_conversion:
00961 if (qd->qd_is_dst < 0)
00962 break;
00963
00964 {
00965 gint diff;
00966 gint hour_diff;
00967 gint min_diff;
00968 gint sec_diff;
00969 diff = qd->qd_gmt_off;
00970 hour_diff = diff / 60 / 60;
00971 min_diff = diff / 60 % 60;
00972 sec_diff = diff % 60;
00973
00974 switch (colons)
00975 {
00976 case 0:
00977 DO_TZ_OFFSET (5, diff < 0, 0,
00978 hour_diff * 100 + min_diff);
00979
00980 case 1:
00981 tz_hh_mm:
00982 DO_TZ_OFFSET (6, diff < 0, 04,
00983 hour_diff * 100 + min_diff);
00984
00985 case 2:
00986 tz_hh_mm_ss:
00987 DO_TZ_OFFSET (9, diff < 0, 024,
00988 hour_diff * 10000 + min_diff * 100 + sec_diff);
00989
00990 case 3:
00991 if (sec_diff != 0)
00992 goto tz_hh_mm_ss;
00993 if (min_diff != 0)
00994 goto tz_hh_mm;
00995 DO_TZ_OFFSET (3, diff < 0, 0, hour_diff);
00996
00997 default:
00998 goto bad_format;
00999 }
01000 }
01001
01002 case ('\0'):
01003 --f;
01004
01005 default:
01006
01007
01008
01009 bad_format:
01010 {
01011 gint flen;
01012 for (flen = 1; f[1 - flen] != ('%'); flen++)
01013 continue;
01014 cpy (flen, &f[1 - flen]);
01015 }
01016 break;
01017 }
01018 }
01019 return i;
01020 }