/** Clear VCR and all breakpoints and watchpoints via scan chain 7 * * \param arm11 Target state variable. * */ void arm11_sc7_clear_vbw(arm11_common_t * arm11) { arm11_sc7_action_t clear_bw[arm11->brp + arm11->wrp + 1]; arm11_sc7_action_t * pos = clear_bw; {size_t i; for (i = 0; i < asizeof(clear_bw); i++) { clear_bw[i].write = true; clear_bw[i].value = 0; }} {size_t i; for (i = 0; i < arm11->brp; i++) (pos++)->address = ARM11_SC7_BCR0 + i; } {size_t i; for (i = 0; i < arm11->wrp; i++) (pos++)->address = ARM11_SC7_WCR0 + i; } (pos++)->address = ARM11_SC7_VCR; arm11_sc7_run(arm11, clear_bw, asizeof(clear_bw)); }
/** Execute one instruction via ITR repeatedly while * passing data to the core via DTR on each execution. * * No Ready check during transmission. * * The executed instruction \em must read data from DTR. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode ARM opcode * \param data Pointer to the data words to be passed to the core * \param count Number of data words and instruction repetitions * */ void arm11_run_instr_data_to_core_noack(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count) { arm11_add_IR(arm11, ARM11_ITRSEL, -1); arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE); arm11_add_IR(arm11, ARM11_EXTEST, -1); scan_field_t chain5_fields[3]; arm11_setup_field(arm11, 32, NULL/*&Data*/, NULL, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, NULL /*&Ready*/, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2); u8 Readies[count + 1]; u8 * ReadyPos = Readies; while (count--) { chain5_fields[0].out_value = (void *)(data++); chain5_fields[1].in_value = ReadyPos++; if (count) { jtag_add_dr_scan(asizeof(chain5_fields), chain5_fields, TAP_DRPAUSE); jtag_add_pathmove(asizeof(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay), arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay); } else { jtag_add_dr_scan(asizeof(chain5_fields), chain5_fields, TAP_IDLE); } } arm11_add_IR(arm11, ARM11_INTEST, -1); chain5_fields[0].out_value = 0; chain5_fields[1].in_value = ReadyPos++; arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_DRPAUSE); jtag_execute_queue(); size_t error_count = 0; {size_t i; for (i = 0; i < asizeof(Readies); i++) { if (Readies[i] != 1) { error_count++; } }} if (error_count) LOG_ERROR("Transfer errors " ZU, error_count); }
/** Execute one instruction via ITR repeatedly while * reading data from the core via DTR on each execution. * * The executed instruction \em must write data to DTR. * * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block * * \param arm11 Target state variable. * \param opcode ARM opcode * \param data Pointer to an array that receives the data words from the core * \param count Number of data words and instruction repetitions * */ void arm11_run_instr_data_from_core(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count) { arm11_add_IR(arm11, ARM11_ITRSEL, -1); arm11_add_debug_INST(arm11, opcode, NULL, TAP_IDLE); arm11_add_IR(arm11, ARM11_INTEST, -1); scan_field_t chain5_fields[3]; u32 Data; u8 Ready; u8 nRetry; arm11_setup_field(arm11, 32, NULL, &Data, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2); while (count--) { do { arm11_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, count ? TAP_IDLE : TAP_DRPAUSE); jtag_execute_queue(); JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d", Data, Ready, nRetry); } while (!Ready); *data++ = Data; } }
int arm11_add_dr_scan_vc(int num_fields, scan_field_t *fields, tap_state_t state) { if (cmd_queue_cur_state == TAP_DRPAUSE) jtag_add_pathmove(asizeof(arm11_move_pd_to_sd_via_cd), arm11_move_pd_to_sd_via_cd); jtag_add_dr_scan(num_fields, fields, state); return ERROR_OK; }
/** Write an instruction into the ITR register * * \param arm11 Target state variable. * \param inst An ARM11 processor instruction/opcode. * \param flag Optional parameter to retrieve the InstCompl flag * (this will be written when the JTAG chain is executed). * \param state Pass the final TAP state or -1 for the default * value (Run-Test/Idle). * * \remarks By default this ends with Run-Test/Idle state * and causes the instruction to be executed. If * a subsequent write to DTR is needed before * executing the instruction then TAP_DRPAUSE should be * passed to \p state. * * \remarks This adds to the JTAG command queue but does \em not execute it. */ void arm11_add_debug_INST(arm11_common_t * arm11, u32 inst, u8 * flag, tap_state_t state) { JTAG_DEBUG("INST <= 0x%08x", inst); scan_field_t itr[2]; arm11_setup_field(arm11, 32, &inst, NULL, itr + 0); arm11_setup_field(arm11, 1, NULL, flag, itr + 1); arm11_add_dr_scan_vc(asizeof(itr), itr, state == -1 ? TAP_IDLE : state); }
static remote_group_table_t * get_group_table(idigi_remote_group_type_t group_type, unsigned int group_index) { remote_group_table_t * group_ptr = NULL; switch (group_type) { case idigi_remote_group_setting: if (group_index < asizeof(remote_setting_table)) { group_ptr = &remote_setting_table[group_index]; } break; case idigi_remote_group_state: if (group_index < asizeof(remote_state_table)) { group_ptr = &remote_state_table[group_index]; } break; } return group_ptr; }
static char * _strptime(pTHX_ const char *buf, const char *fmt, struct tm *tm, int *got_GMT) { char c; const char *ptr; int i, len; int Ealternative, Oalternative; /* There seems to be a slightly improved version at * http://www.opensource.apple.com/source/Libc/Libc-583/stdtime/strptime-fbsd.c * which we may end up borrowing more from */ ptr = fmt; while (*ptr != 0) { if (*buf == 0) break; c = *ptr++; if (c != '%') { if (isspace((unsigned char)c)) while (*buf != 0 && isspace((unsigned char)*buf)) buf++; else if (c != *buf++) return 0; continue; } Ealternative = 0; Oalternative = 0; label: c = *ptr++; switch (c) { case 0: case '%': if (*buf++ != '%') return 0; break; case '+': buf = _strptime(aTHX_ buf, Locale->date_fmt, tm, got_GMT); if (buf == 0) return 0; break; case 'C': if (!isdigit((unsigned char)*buf)) return 0; /* XXX This will break for 3-digit centuries. */ len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 19) return 0; tm->tm_year = i * 100 - 1900; break; case 'c': /* NOTE: c_fmt is intentionally ignored */ buf = _strptime(aTHX_ buf, "%a %Ef %T %Y", tm, got_GMT); if (buf == 0) return 0; break; case 'D': buf = _strptime(aTHX_ buf, "%m/%d/%y", tm, got_GMT); if (buf == 0) return 0; break; case 'E': if (Ealternative || Oalternative) break; Ealternative++; goto label; case 'O': if (Ealternative || Oalternative) break; Oalternative++; goto label; case 'F': case 'f': if (!Ealternative) break; buf = _strptime(aTHX_ buf, (c == 'f') ? Locale->Ef_fmt : Locale->EF_fmt, tm, got_GMT); if (buf == 0) return 0; break; case 'R': buf = _strptime(aTHX_ buf, "%H:%M", tm, got_GMT); if (buf == 0) return 0; break; case 'r': buf = _strptime(aTHX_ buf, "%I:%M:%S %p", tm, got_GMT); if (buf == 0) return 0; break; case 'n': /* whitespace */ case 't': if (!isspace((unsigned char)*buf)) return 0; while (isspace((unsigned char)*buf)) buf++; break; case 'T': buf = _strptime(aTHX_ buf, "%H:%M:%S", tm, got_GMT); if (buf == 0) return 0; break; case 'X': buf = _strptime(aTHX_ buf, Locale->X_fmt, tm, got_GMT); if (buf == 0) return 0; break; case 'x': buf = _strptime(aTHX_ buf, Locale->x_fmt, tm, got_GMT); if (buf == 0) return 0; break; case 'j': if (!isdigit((unsigned char)*buf)) return 0; len = 3; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 366) return 0; tm->tm_yday = i - 1; break; case 'M': case 'S': if (*buf == 0 || isspace((unsigned char)*buf)) break; if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'M') { if (i > 59) return 0; tm->tm_min = i; } else { if (i > 60) return 0; tm->tm_sec = i; } if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'H': case 'I': case 'k': case 'l': /* * Of these, %l is the only specifier explicitly * documented as not being zero-padded. However, * there is no harm in allowing zero-padding. * * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'H' || c == 'k') { if (i > 23) return 0; } else if (i > 12) return 0; tm->tm_hour = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'p': /* * XXX This is bogus if parsed before hour-related * specifiers. */ len = strlen(Locale->am); if (strncasecmp(buf, Locale->am, len) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour == 12) tm->tm_hour = 0; buf += len; break; } len = strlen(Locale->pm); if (strncasecmp(buf, Locale->pm, len) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour != 12) tm->tm_hour += 12; buf += len; break; } return 0; case 'A': case 'a': for (i = 0; i < asizeof(Locale->weekday); i++) { if (c == 'A') { len = strlen(Locale->weekday[i]); if (strncasecmp(buf, Locale->weekday[i], len) == 0) break; } else { len = strlen(Locale->wday[i]); if (strncasecmp(buf, Locale->wday[i], len) == 0) break; } } if (i == asizeof(Locale->weekday)) return 0; tm->tm_wday = i; buf += len; break; case 'U': case 'W': /* * XXX This is bogus, as we can not assume any valid * information present in the tm structure at this * point to calculate a real value, so just check the * range for now. */ if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 53) return 0; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'w': if (!isdigit((unsigned char)*buf)) return 0; i = *buf - '0'; if (i > 6) return 0; tm->tm_wday = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'd': case 'e': /* * The %e specifier is explicitly documented as not * being zero-padded but there is no harm in allowing * such padding. * * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 31) return 0; tm->tm_mday = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'B': case 'b': case 'h': for (i = 0; i < asizeof(Locale->month); i++) { if (Oalternative) { if (c == 'B') { len = strlen(Locale->alt_month[i]); if (strncasecmp(buf, Locale->alt_month[i], len) == 0) break; } } else { if (c == 'B') { len = strlen(Locale->month[i]); if (strncasecmp(buf, Locale->month[i], len) == 0) break; } else { len = strlen(Locale->mon[i]); if (strncasecmp(buf, Locale->mon[i], len) == 0) break; } } } if (i == asizeof(Locale->month)) return 0; tm->tm_mon = i; buf += len; break; case 'm': if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 12) return 0; tm->tm_mon = i - 1; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 's': { char *cp; int sverrno; long n; time_t t; struct tm mytm; sverrno = errno; errno = 0; n = strtol(buf, &cp, 10); if (errno == ERANGE || (long)(t = n) != n) { errno = sverrno; return 0; } errno = sverrno; buf = cp; memset(&mytm, 0, sizeof(mytm)); my_init_tm(&mytm); /* XXX workaround - see my_init_tm() above */ mytm = *gmtime(&t); tm->tm_sec = mytm.tm_sec; tm->tm_min = mytm.tm_min; tm->tm_hour = mytm.tm_hour; tm->tm_mday = mytm.tm_mday; tm->tm_mon = mytm.tm_mon; tm->tm_year = mytm.tm_year; tm->tm_wday = mytm.tm_wday; tm->tm_yday = mytm.tm_yday; tm->tm_isdst = mytm.tm_isdst; } break; case 'Y': case 'y': if (*buf == 0 || isspace((unsigned char)*buf)) break; if (!isdigit((unsigned char)*buf)) return 0; len = (c == 'Y') ? 4 : 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'Y') i -= 1900; if (c == 'y' && i < 69) i += 100; if (i < 0) return 0; tm->tm_year = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'Z': { const char *cp; char *zonestr; for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} if (cp - buf) { zonestr = (char *)malloc(cp - buf + 1); if (!zonestr) { errno = ENOMEM; return 0; } strncpy(zonestr, buf, cp - buf); zonestr[cp - buf] = '\0'; my_tzset(aTHX); if (0 == strcmp(zonestr, "GMT")) { *got_GMT = 1; } free(zonestr); if (!*got_GMT) return 0; buf += cp - buf; } } break; case 'z': { int sign = 1; if (*buf != '+') { if (*buf == '-') sign = -1; else return 0; } buf++; i = 0; for (len = 4; len > 0; len--) { if (isdigit((int)*buf)) { i *= 10; i += *buf - '0'; buf++; } else return 0; } tm->tm_hour -= sign * (i / 100); tm->tm_min -= sign * (i % 100); *got_GMT = 1; } break; } } return (char *)buf; }
static char* _strptime(const char* buf, const char* fmt, struct tm* tm, int* GMTp) { char c; const char* ptr; int i, len; int Ealternative, Oalternative; struct lc_time_T* tptr = __get_current_time_locale(); ptr = fmt; while (*ptr != 0) { if (*buf == 0) { break; } c = *ptr++; if (c != '%') { if (isspace((unsigned char)c)) while (*buf != 0 && isspace((unsigned char)*buf)) { buf++; } else if (c != *buf++) { return 0; } continue; } Ealternative = 0; Oalternative = 0; label: c = *ptr++; switch (c) { case 0: case '%': if (*buf++ != '%') { return 0; } break; case '+': buf = _strptime(buf, tptr->date_fmt, tm, GMTp); if (buf == 0) { return 0; } break; case 'C': if (!isdigit((unsigned char)*buf)) { return 0; } /* XXX This will break for 3-digit centuries. */ len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 19) { return 0; } tm->tm_year = i * 100 - 1900; break; case 'c': buf = _strptime(buf, tptr->c_fmt, tm, GMTp); if (buf == 0) { return 0; } break; case 'D': buf = _strptime(buf, "%m/%d/%y", tm, GMTp); if (buf == 0) { return 0; } break; case 'E': if (Ealternative || Oalternative) { break; } Ealternative++; goto label; case 'O': if (Ealternative || Oalternative) { break; } Oalternative++; goto label; case 'F': buf = _strptime(buf, "%Y-%m-%d", tm, GMTp); if (buf == 0) { return 0; } break; case 'R': buf = _strptime(buf, "%H:%M", tm, GMTp); if (buf == 0) { return 0; } break; case 'r': buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp); if (buf == 0) { return 0; } break; case 'T': buf = _strptime(buf, "%H:%M:%S", tm, GMTp); if (buf == 0) { return 0; } break; case 'X': buf = _strptime(buf, tptr->X_fmt, tm, GMTp); if (buf == 0) { return 0; } break; case 'x': buf = _strptime(buf, tptr->x_fmt, tm, GMTp); if (buf == 0) { return 0; } break; case 'j': if (!isdigit((unsigned char)*buf)) { return 0; } len = 3; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 366) { return 0; } tm->tm_yday = i - 1; break; case 'M': case 'S': if (*buf == 0 || isspace((unsigned char)*buf)) { break; } if (!isdigit((unsigned char)*buf)) { return 0; } len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'M') { if (i > 59) { return 0; } tm->tm_min = i; } else { if (i > 60) { return 0; } tm->tm_sec = i; } if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) { ptr++; } break; case 'H': case 'I': case 'k': case 'l': /* * Of these, %l is the only specifier explicitly * documented as not being zero-padded. However, * there is no harm in allowing zero-padding. * * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit((unsigned char)*buf)) { return 0; } len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'H' || c == 'k') { if (i > 23) { return 0; } } else if (i > 12) { return 0; } tm->tm_hour = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) { ptr++; } break; case 'p': /* * XXX This is bogus if parsed before hour-related * specifiers. */ len = strlen(tptr->am); if (strncasecmp(buf, tptr->am, len) == 0) { if (tm->tm_hour > 12) { return 0; } if (tm->tm_hour == 12) { tm->tm_hour = 0; } buf += len; break; } len = strlen(tptr->pm); if (strncasecmp(buf, tptr->pm, len) == 0) { if (tm->tm_hour > 12) { return 0; } if (tm->tm_hour != 12) { tm->tm_hour += 12; } buf += len; break; } return 0; case 'A': case 'a': for (i = 0; i < asizeof(tptr->weekday); i++) { len = strlen(tptr->weekday[i]); if (strncasecmp(buf, tptr->weekday[i], len) == 0) { break; } len = strlen(tptr->wday[i]); if (strncasecmp(buf, tptr->wday[i], len) == 0) { break; } } if (i == asizeof(tptr->weekday)) { return 0; } tm->tm_wday = i; buf += len; break; case 'U': case 'W': /* * XXX This is bogus, as we can not assume any valid * information present in the tm structure at this * point to calculate a real value, so just check the * range for now. */ if (!isdigit((unsigned char)*buf)) { return 0; } len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 53) { return 0; } if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) { ptr++; } break; case 'w': if (!isdigit((unsigned char)*buf)) { return 0; } i = *buf - '0'; if (i > 6) { return 0; } tm->tm_wday = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) { ptr++; } break; case 'd': case 'e': /* * The %e specifier is explicitly documented as not * being zero-padded but there is no harm in allowing * such padding. * * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit((unsigned char)*buf)) { return 0; } len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 31) { return 0; } tm->tm_mday = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) { ptr++; } break; case 'B': case 'b': case 'h': for (i = 0; i < asizeof(tptr->month); i++) { if (Oalternative) { if (c == 'B') { len = strlen(tptr->alt_month[i]); if (strncasecmp(buf, tptr->alt_month[i], len) == 0) { break; } } } else { len = strlen(tptr->month[i]); if (strncasecmp(buf, tptr->month[i], len) == 0) { break; } len = strlen(tptr->mon[i]); if (strncasecmp(buf, tptr->mon[i], len) == 0) { break; } } } if (i == asizeof(tptr->month)) { return 0; } tm->tm_mon = i; buf += len; break; case 'm': if (!isdigit((unsigned char)*buf)) { return 0; } len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 12) { return 0; } tm->tm_mon = i - 1; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) { ptr++; } break; case 's': { char* cp; int sverrno; long n; time_t t; sverrno = errno; errno = 0; n = strtol(buf, &cp, 10); if (errno == ERANGE || (long)(t = n) != n) { errno = sverrno; return 0; } errno = sverrno; buf = cp; gmtime_r(&t, tm); *GMTp = 1; } break; case 'Y': case 'y': if (*buf == 0 || isspace((unsigned char)*buf)) { break; } if (!isdigit((unsigned char)*buf)) { return 0; } len = (c == 'Y') ? 4 : 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'Y') { i -= 1900; } if (c == 'y' && i < 69) { i += 100; } if (i < 0) { return 0; } tm->tm_year = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) { ptr++; } break; case 'Z': { const char* cp; char* zonestr; for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) { /*empty*/ } if (cp - buf) { zonestr = alloca(cp - buf + 1); strncpy(zonestr, buf, cp - buf); zonestr[cp - buf] = '\0'; tzset(); if (0 == strcmp(zonestr, "GMT")) { *GMTp = 1; } else if (0 == strcmp(zonestr, tzname[0])) { tm->tm_isdst = 0; } else if (0 == strcmp(zonestr, tzname[1])) { tm->tm_isdst = 1; } else { return 0; } buf += cp - buf; } } break; } } return (char*)buf; }
static char * _strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp, locale_t locale) { char c; const char *ptr; int day_offset = -1, wday_offset; int week_offset; int i, len; int flags; int Ealternative, Oalternative; const struct lc_time_T *tptr = __get_current_time_locale(locale); static int start_of_month[2][13] = { {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} }; flags = FLAG_NONE; ptr = fmt; while (*ptr != 0) { c = *ptr++; if (c != '%') { if (isspace_l((unsigned char)c, locale)) while (*buf != 0 && isspace_l((unsigned char)*buf, locale)) buf++; else if (c != *buf++) return (NULL); continue; } Ealternative = 0; Oalternative = 0; label: c = *ptr++; switch (c) { case '%': if (*buf++ != '%') return (NULL); break; case '+': buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale); if (buf == NULL) return (NULL); flags |= FLAG_WDAY | FLAG_MONTH | FLAG_MDAY | FLAG_YEAR; break; case 'C': if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); /* XXX This will break for 3-digit centuries. */ len = 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 19) return (NULL); tm->tm_year = i * 100 - TM_YEAR_BASE; flags |= FLAG_YEAR; break; case 'c': buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale); if (buf == NULL) return (NULL); flags |= FLAG_WDAY | FLAG_MONTH | FLAG_MDAY | FLAG_YEAR; break; case 'D': buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale); if (buf == NULL) return (NULL); flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR; break; case 'E': if (Ealternative || Oalternative) break; Ealternative++; goto label; case 'O': if (Ealternative || Oalternative) break; Oalternative++; goto label; case 'F': buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale); if (buf == NULL) return (NULL); flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR; break; case 'R': buf = _strptime(buf, "%H:%M", tm, GMTp, locale); if (buf == NULL) return (NULL); break; case 'r': buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp, locale); if (buf == NULL) return (NULL); break; case 'T': buf = _strptime(buf, "%H:%M:%S", tm, GMTp, locale); if (buf == NULL) return (NULL); break; case 'X': buf = _strptime(buf, tptr->X_fmt, tm, GMTp, locale); if (buf == NULL) return (NULL); break; case 'x': buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale); if (buf == NULL) return (NULL); flags |= FLAG_MONTH | FLAG_MDAY | FLAG_YEAR; break; case 'j': if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); len = 3; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 366) return (NULL); tm->tm_yday = i - 1; flags |= FLAG_YDAY; break; case 'M': case 'S': if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); len = 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'M') { if (i > 59) return (NULL); tm->tm_min = i; } else { if (i > 60) return (NULL); tm->tm_sec = i; } break; case 'H': case 'I': case 'k': case 'l': /* * Of these, %l is the only specifier explicitly * documented as not being zero-padded. However, * there is no harm in allowing zero-padding. * * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); len = 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'H' || c == 'k') { if (i > 23) return (NULL); } else if (i > 12) return (NULL); tm->tm_hour = i; break; case 'p': /* * XXX This is bogus if parsed before hour-related * specifiers. */ len = strlen(tptr->am); if (strncasecmp_l(buf, tptr->am, len, locale) == 0) { if (tm->tm_hour > 12) return (NULL); if (tm->tm_hour == 12) tm->tm_hour = 0; buf += len; break; } len = strlen(tptr->pm); if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) { if (tm->tm_hour > 12) return (NULL); if (tm->tm_hour != 12) tm->tm_hour += 12; buf += len; break; } return (NULL); case 'A': case 'a': for (i = 0; i < asizeof(tptr->weekday); i++) { len = strlen(tptr->weekday[i]); if (strncasecmp_l(buf, tptr->weekday[i], len, locale) == 0) break; len = strlen(tptr->wday[i]); if (strncasecmp_l(buf, tptr->wday[i], len, locale) == 0) break; } if (i == asizeof(tptr->weekday)) return (NULL); buf += len; tm->tm_wday = i; flags |= FLAG_WDAY; break; case 'U': case 'W': /* * XXX This is bogus, as we can not assume any valid * information present in the tm structure at this * point to calculate a real value, so just check the * range for now. */ if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); len = 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 53) return (NULL); if (c == 'U') day_offset = TM_SUNDAY; else day_offset = TM_MONDAY; week_offset = i; break; case 'w': if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); i = *buf - '0'; buf++; if (i > 6) return (NULL); tm->tm_wday = i; flags |= FLAG_WDAY; break; case 'e': /* * With %e format, our strftime(3) adds a blank space * before single digits. */ if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) buf++; /* FALLTHROUGH */ case 'd': /* * The %e specifier was once explicitly documented as * not being zero-padded but was later changed to * equivalent to %d. There is no harm in allowing * such padding. * * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); len = 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 31) return (NULL); tm->tm_mday = i; flags |= FLAG_MDAY; break; case 'B': case 'b': case 'h': for (i = 0; i < asizeof(tptr->month); i++) { if (Oalternative) { if (c == 'B') { len = strlen(tptr->alt_month[i]); if (strncasecmp_l(buf, tptr->alt_month[i], len, locale) == 0) break; } } else { len = strlen(tptr->month[i]); if (strncasecmp_l(buf, tptr->month[i], len, locale) == 0) break; } } /* * Try the abbreviated month name if the full name * wasn't found and Oalternative was not requested. */ if (i == asizeof(tptr->month) && !Oalternative) { for (i = 0; i < asizeof(tptr->month); i++) { len = strlen(tptr->mon[i]); if (strncasecmp_l(buf, tptr->mon[i], len, locale) == 0) break; } } if (i == asizeof(tptr->month)) return (NULL); tm->tm_mon = i; buf += len; flags |= FLAG_MONTH; break; case 'm': if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); len = 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 12) return (NULL); tm->tm_mon = i - 1; flags |= FLAG_MONTH; break; case 's': { char *cp; int sverrno; long n; time_t t; sverrno = errno; errno = 0; n = strtol_l(buf, &cp, 10, locale); if (errno == ERANGE || (long)(t = n) != n) { errno = sverrno; return (NULL); } errno = sverrno; buf = cp; if (gmtime_r(&t, tm) == NULL) return (NULL); *GMTp = 1; flags |= FLAG_YDAY | FLAG_WDAY | FLAG_MONTH | FLAG_MDAY | FLAG_YEAR; } break; case 'Y': case 'y': if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; if (!isdigit_l((unsigned char)*buf, locale)) return (NULL); len = (c == 'Y') ? 4 : 2; for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'Y') i -= TM_YEAR_BASE; if (c == 'y' && i < 69) i += 100; if (i < 0) return (NULL); tm->tm_year = i; flags |= FLAG_YEAR; break; case 'Z': { const char *cp; char *zonestr; for (cp = buf; *cp && isupper_l((unsigned char)*cp, locale); ++cp) { /*empty*/ } if (cp - buf) { zonestr = alloca(cp - buf + 1); strncpy(zonestr, buf, cp - buf); zonestr[cp - buf] = '\0'; tzset(); if (0 == strcmp(zonestr, "GMT") || 0 == strcmp(zonestr, "UTC")) { *GMTp = 1; } else if (0 == strcmp(zonestr, tzname[0])) { tm->tm_isdst = 0; } else if (0 == strcmp(zonestr, tzname[1])) { tm->tm_isdst = 1; } else { return (NULL); } buf += cp - buf; } } break; case 'z': { int sign = 1; len = 4; /* RFC 822/ISO 8601 */ if (*buf != '+') { if (*buf == '-') sign = -1; else if (*buf == 'Z') /* ISO 8601 Z (UTC) */ len = 0; else return (NULL); } buf++; i = 0; for (; len > 0; len--) { if (isdigit_l((unsigned char)*buf, locale)) { i *= 10; i += *buf - '0'; buf++; } else if (*buf == ':' && len == 2) { buf++; /* ISO 8601 +hh:mm */ if (isdigit_l((unsigned char)*buf, locale)) { i *= 10; i += *buf - '0'; buf++; } else { return (NULL); } } else if (len == 2) { i *= 100; /* ISO 8601 +hh */ break; } else { return (NULL); } } tm->tm_hour -= sign * (i / 100); tm->tm_min -= sign * (i % 100); *GMTp = 1; } break; case 'n': case 't': while (isspace_l((unsigned char)*buf, locale)) buf++; break; default: return (NULL); } } if (!(flags & FLAG_YDAY) && (flags & FLAG_YEAR)) { if ((flags & (FLAG_MONTH | FLAG_MDAY)) == (FLAG_MONTH | FLAG_MDAY)) { tm->tm_yday = start_of_month[isleap(tm->tm_year + TM_YEAR_BASE)][tm->tm_mon] + (tm->tm_mday - 1); flags |= FLAG_YDAY; } else if (day_offset != -1) { /* Set the date to the first Sunday (or Monday) * of the specified week of the year. */ if (!(flags & FLAG_WDAY)) { tm->tm_wday = day_offset; flags |= FLAG_WDAY; } tm->tm_yday = (7 - first_wday_of(tm->tm_year + TM_YEAR_BASE) + day_offset) % 7 + (week_offset - 1 + (tm->tm_wday == 0 ? day_offset : 0)) * 7 + tm->tm_wday - day_offset; flags |= FLAG_YDAY; } } if ((flags & (FLAG_YEAR | FLAG_YDAY)) == (FLAG_YEAR | FLAG_YDAY)) { if (!(flags & FLAG_MONTH)) { i = 0; while (tm->tm_yday >= start_of_month[isleap(tm->tm_year + TM_YEAR_BASE)][i]) i++; if (i > 12) { i = 1; tm->tm_yday -= start_of_month[isleap(tm->tm_year + TM_YEAR_BASE)][12]; tm->tm_year++; } tm->tm_mon = i - 1; flags |= FLAG_MONTH; } if (!(flags & FLAG_MDAY)) { tm->tm_mday = tm->tm_yday - start_of_month[isleap(tm->tm_year + TM_YEAR_BASE)] [tm->tm_mon] + 1; flags |= FLAG_MDAY; } if (!(flags & FLAG_WDAY)) { i = 0; wday_offset = first_wday_of(tm->tm_year); while (i++ <= tm->tm_yday) { if (wday_offset++ >= 6) wday_offset = 0; } tm->tm_wday = wday_offset; flags |= FLAG_WDAY; } } return ((char *)buf); }
/** Apply reads and writes to scan chain 7 * * \see arm11_sc7_action_t * * \param arm11 Target state variable. * \param actions A list of read and/or write instructions * \param count Number of instructions in the list. * */ void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count) { arm11_add_debug_SCAN_N(arm11, 0x07, -1); arm11_add_IR(arm11, ARM11_EXTEST, -1); scan_field_t chain7_fields[3]; u8 nRW; u32 DataOut; u8 AddressOut; u8 Ready; u32 DataIn; u8 AddressIn; arm11_setup_field(arm11, 1, &nRW, &Ready, chain7_fields + 0); arm11_setup_field(arm11, 32, &DataOut, &DataIn, chain7_fields + 1); arm11_setup_field(arm11, 7, &AddressOut, &AddressIn, chain7_fields + 2); {size_t i; for (i = 0; i < count + 1; i++) { if (i < count) { nRW = actions[i].write ? 1 : 0; DataOut = actions[i].value; AddressOut = actions[i].address; } else { nRW = 0; DataOut = 0; AddressOut = 0; } do { JTAG_DEBUG("SC7 <= Address %02x Data %08x nRW %d", AddressOut, DataOut, nRW); arm11_add_dr_scan_vc(asizeof(chain7_fields), chain7_fields, TAP_DRPAUSE); jtag_execute_queue(); JTAG_DEBUG("SC7 => Address %02x Data %08x Ready %d", AddressIn, DataIn, Ready); } while (!Ready); /* 'nRW' is 'Ready' on read out */ if (i > 0) { if (actions[i - 1].address != AddressIn) { LOG_WARNING("Scan chain 7 shifted out unexpected address"); } if (!actions[i - 1].write) { actions[i - 1].value = DataIn; } else { if (actions[i - 1].value != DataIn) { LOG_WARNING("Scan chain 7 shifted out unexpected data"); } } } }} {size_t i; for (i = 0; i < count; i++) { JTAG_DEBUG("SC7 %02d: %02x %s %08x", i, actions[i].address, actions[i].write ? "<=" : "=>", actions[i].value); }} }
U_EXPORT char* strptime(const char* buf, const char* fmt, struct tm* tm) { int i, j, len; const char* ptr; ptr = fmt; while (*ptr != 0) { char c; if (*buf == 0) break; c = *ptr++; if (c != '%') { if (isspace(c)) { while (*buf != 0 && isspace(*buf)) buf++; } else { if (c != *buf++) return 0; } continue; } c = *ptr++; switch (c) { case 0: case '%': if (*buf++ != '%') return 0; break; case 'C': { buf = (const char*) strptime(buf, En_US.ldate_format, tm); if (buf == 0) return 0; } break; case 'c': { buf = (const char*) strptime(buf, "%x %X", tm); if (buf == 0) return 0; } break; case 'D': { buf = (const char*) strptime(buf, "%m/%d/%y", tm); if (buf == 0) return 0; } break; case 'R': { buf = (const char*) strptime(buf, "%H:%M", tm); if (buf == 0) return 0; } break; case 'r': { buf = (const char*) strptime(buf, "%I:%M:%S %p", tm); if (buf == 0) return 0; } break; case 'T': { buf = (const char*) strptime(buf, "%H:%M:%S", tm); if (buf == 0) return 0; } break; case 'X': { buf = (const char*) strptime(buf, En_US.time_format, tm); if (buf == 0) return 0; } break; case 'x': { buf = (const char*) strptime(buf, En_US.sdate_format, tm); if (buf == 0) return 0; } break; case 'j': { if (!isdigit(*buf)) return 0; for (i = 0; *buf != 0 && isdigit(*buf); buf++) { i *= 10; i += *buf - '0'; } if (i > 365) return 0; tm->tm_yday = i; } break; case 'M': case 'S': { if (*buf == 0 || isspace(*buf)) break; if (!isdigit(*buf)) return 0; for (j = 0, i = 0; *buf != 0 && isdigit(*buf) && j < 2; j++,buf++) { i *= 10; i += *buf - '0'; } if (i > 59) return 0; if (c == 'M') tm->tm_min = i; else tm->tm_sec = i; if (*buf != 0 && isspace(*buf)) while (*ptr != 0 && !isspace(*ptr)) ptr++; } break; case 'H': case 'I': case 'k': case 'l': { if (!isdigit(*buf)) return 0; for (j = 0, i = 0; *buf != 0 && isdigit(*buf) && j < 2; j++,buf++) { i *= 10; i += *buf - '0'; } if (c == 'H' || c == 'k') { if (i > 23) return 0; } else { if (i > 11) return 0; } tm->tm_hour = i; if (*buf != 0 && isspace(*buf)) while (*ptr != 0 && !isspace(*ptr)) ptr++; } break; case 'p': { len = strlen(En_US.am_string); if (strncasecmp(buf, En_US.am_string, len) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour == 12) tm->tm_hour = 0; buf += len; break; } len = strlen(En_US.pm_string); if (strncasecmp(buf, En_US.pm_string, len) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour != 12) tm->tm_hour += 12; buf += len; break; } } return 0; case 'A': case 'a': { for (i = 0; i < asizeof(En_US.weekday_names); i++) { len = strlen(En_US.weekday_names[i]); if (strncasecmp(buf, En_US.weekday_names[i], len) == 0) break; len = strlen(En_US.abbrev_weekday_names[i]); if (strncasecmp(buf, En_US.abbrev_weekday_names[i], len) == 0) break; } if (i == asizeof(En_US.weekday_names)) return 0; tm->tm_wday = i; buf += len; } break; case 'd': case 'e': { if (!isdigit(*buf)) return 0; for (j = 0, i = 0; *buf != 0 && isdigit(*buf) && j < 2; j++,buf++) { i *= 10; i += *buf - '0'; } if (i > 31) return 0; tm->tm_mday = i; if (*buf != 0 && isspace(*buf)) while (*ptr != 0 && !isspace(*ptr)) ptr++; } break; case 'B': case 'b': case 'h': { for (i = 0; i < asizeof(En_US.month_names); i++) { len = strlen(En_US.month_names[i]); if (strncasecmp(buf, En_US.month_names[i], len) == 0) break; len = strlen(En_US.abbrev_month_names[i]); if (strncasecmp(buf, En_US.abbrev_month_names[i], len) == 0) break; } if (i == asizeof(En_US.month_names)) return 0; tm->tm_mon = i; buf += len; } break; case 'm': { if (!isdigit(*buf)) return 0; for (j = 0, i = 0; *buf != 0 && isdigit(*buf) && j < 2; j++,buf++) { i *= 10; i += *buf - '0'; } if (i < 1 || i > 12) return 0; tm->tm_mon = i - 1; if (*buf != 0 && isspace(*buf)) while (*ptr != 0 && !isspace(*ptr)) ptr++; } break; case 'Y': case 'y': { if (*buf == 0 || isspace(*buf)) break; if (!isdigit(*buf)) return 0; for (j = 0, i = 0; *buf != 0 && isdigit(*buf) && j < ((c == 'Y') ? 4 : 2); j++,buf++) { i *= 10; i += *buf - '0'; } if (c == 'Y') i -= 1900; else if (i < 69) i += 100; /* c == 'y', 00-68 is for 20xx, the rest is for 19xx */ if (i < 0) return 0; tm->tm_year = i; if (*buf != 0 && isspace(*buf)) while (*ptr != 0 && !isspace(*ptr)) ptr++; break; } } } return (char*)buf; }
static const char * _pg_strptime(const char *buf, const char *fmt, struct pg_tm *tm, long *nsec, char ** tz, int *tzlen) { char c; const char *ptr; int i, len; int Ealternative, Oalternative; struct pg_time_locale const *loc = &pgDefaultTimeLocale; int has_am_pm = 0; /* 1 - AM, 2 - PM */ ptr = fmt; while (*ptr != 0) { if (*buf == 0) break; c = *ptr++; if (c != '%') { if (isspace((unsigned char)c)) while (*buf != 0 && isspace((unsigned char)*buf)) buf++; else if (c != *buf++) return 0; continue; } Ealternative = 0; Oalternative = 0; label: c = *ptr++; switch (c) { case 0: case '%': if (*buf++ != '%') return 0; break; case '+': buf = _pg_strptime(buf, loc->date_fmt, tm, nsec, tz, tzlen); if (buf == 0) return 0; break; case 'C': if (!isdigit((unsigned char)*buf)) return 0; /* XXX This will break for 3-digit centuries. */ len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 19) return 0; tm->tm_year = i * 100 - 1900; break; case 'c': /* Date and time, using the locale's format. */ buf = _pg_strptime(buf, loc->c_fmt, tm, nsec, tz, tzlen); if (buf == 0) return 0; break; case 'D': buf = _pg_strptime(buf, "%m/%d/%y", tm, nsec, tz, tzlen); if (buf == 0) return 0; break; case 'E': if (Ealternative || Oalternative) break; Ealternative++; goto label; case 'O': if (Ealternative || Oalternative) break; Oalternative++; goto label; case 'F': buf = _pg_strptime(buf, "%Y-%m-%d", tm, nsec, tz, tzlen); if (buf == 0) return 0; break; case 'R': buf = _pg_strptime(buf, "%H:%M", tm, nsec, tz, tzlen); if (buf == 0) return 0; break; case 'r': /* 12-hour clock time using the AM/PM notation; in the default locale, this shall be equivalent to %I:%M:%S %p */ buf = _pg_strptime(buf, loc->ampm_fmt, tm, nsec, tz, tzlen); if (buf == 0) return 0; break; case 'T': buf = _pg_strptime(buf, "%H:%M:%S", tm, nsec, tz, tzlen); if (buf == 0) return 0; break; case 'X': /* The time, using the locale's format */ buf = _pg_strptime(buf, loc->X_fmt, tm, nsec, tz, tzlen); if (buf == 0) return 0; break; case 'x': /* The date, using the locale's date format */ buf = _pg_strptime(buf, loc->x_fmt, tm, nsec, tz, tzlen); if (buf == 0) return 0; break; case 'j': if (!isdigit((unsigned char)*buf)) return 0; len = 3; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 366) return 0; tm->tm_yday = i - 1; break; case 'M': case 'S': if (*buf == 0 || isspace((unsigned char)*buf)) break; if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'M') { if (i > 59) return 0; tm->tm_min = i; } else { if (i > 60) return 0; tm->tm_sec = i; } if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'H': case 'I': case 'k': case 'l': /* * Of these, %l is the only specifier explicitly * documented as not being zero-padded. However, * there is no harm in allowing zero-padding. * * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'H' || c == 'k') { if (i > 23) return 0; } else if (i > 12) return 0; tm->tm_hour = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'p': if (strncasecmp(buf, "AM", (len=2)) == 0 || strncasecmp(buf, "A.M.", (len=4)) == 0) { has_am_pm = 1; if (tm->tm_hour > 12) return 0; buf += len; break; } if (strncasecmp(buf, "PM", (len=2)) == 0 || strncasecmp(buf, "P.M.", (len=4)) == 0) { has_am_pm = 2; if (tm->tm_hour > 12) return 0; buf += len; break; } return 0; case 'A': case 'a': for (i = 0; i < asizeof(loc->weekday); i++) { len = strlen(loc->weekday[i]); if (strncasecmp(buf, loc->weekday[i], len) == 0) break; len = strlen(loc->wday[i]); if (strncasecmp(buf, loc->wday[i], len) == 0) break; } if (i == asizeof(loc->weekday)) return 0; tm->tm_wday = i; buf += len; break; case 'U': case 'W': /* * XXX This is bogus, as we can not assume any valid * information present in the tm structure at this * point to calculate a real value, so just check the * range for now. */ if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 53) return 0; else { } if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'w': if (!isdigit((unsigned char)*buf)) return 0; i = *buf - '0'; if (i > 6) return 0; tm->tm_wday = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'd': case 'e': /* * The %e specifier is explicitly documented as not * being zero-padded but there is no harm in allowing * such padding. * * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i > 31) return 0; tm->tm_mday = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'B': case 'b': case 'h': for (i = 0; i < asizeof(loc->month); i++) { if (Oalternative) { if (c == 'B') { len = strlen(loc->month[i]); if (strncasecmp(buf, loc->month[i], len) == 0) break; } } else { len = strlen(loc->month[i]); if (strncasecmp(buf, loc->month[i], len) == 0) break; len = strlen(loc->mon[i]); if (strncasecmp(buf, loc->mon[i], len) == 0) break; } } if (i == asizeof(loc->month)) return 0; tm->tm_mon = i; buf += len; break; case 'm': if (!isdigit((unsigned char)*buf)) return 0; len = 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (i < 1 || i > 12) return 0; tm->tm_mon = i - 1; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'Q': /* number of miliseconds since the epoch (1970-01-01 00:00:00 UTC) */ case 's': /* number of seconds since the epoch (1970-01-01 00:00:00 UTC) */ { char *cp; int sverrno; long n, r, ms = 0; pg_time_t t; sverrno = errno; errno = 0; n = strtol(buf, &cp, 10); if (c == 's') { t = n; r = (long)t; } else { t = n / 1000; ms = n % 1000; r = ((long)t) * 1000 + ms; } if (errno == ERANGE || r != n) { errno = sverrno; return 0; } errno = sverrno; buf = cp; *nsec = ms * 1000000; //rb_raise(rb_eRuntimeError, "localtime !!!");//TODO //pg_localtime_r(&t, tz, tm); } break; case 'N': case 'L': { char *cp; int sverrno; sverrno = errno; errno = 0; *nsec = strtol(buf, &cp, 10); if (errno != 0) { errno = sverrno; return 0; } if (c == 'L') { if (*nsec < 0 || *nsec > 999) return 0; *nsec *= 1000000; } buf = cp; } break; case 'Y': case 'y': if (*buf == 0 || isspace((unsigned char)*buf)) break; if (!isdigit((unsigned char)*buf)) return 0; len = (c == 'Y') ? 4 : 2; for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { i *= 10; i += *buf - '0'; len--; } if (c == 'Y') i -= 1900; if (c == 'y' && i < 69) i += 100; if (i < 0) return 0; tm->tm_year = i; if (*buf != 0 && isspace((unsigned char)*buf)) while (*ptr != 0 && !isspace((unsigned char)*ptr)) ptr++; break; case 'Z': { const char *cp; char zonestr[TZ_STRLEN_MAX+1]; for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} if (cp - buf) { *tz = buf; //TODO: use tm->tm_zone ? *tzlen = cp - buf; buf += cp - buf; } // TODO: error if timezone empty? } break; } } switch(has_am_pm) { case 1: /* AM */ if (tm->tm_hour == 12) tm->tm_hour = 0; break; case 2: /* PM */ if (tm->tm_hour != 12) tm->tm_hour += 12; break; } return (char *)buf; }