Example #1
0
/** 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));
}
Example #2
0
/** 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);
}
Example #3
0
/** 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;
    }
}
Example #4
0
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;
}
Example #5
0
/** 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;
}
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
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);
}
Example #10
0
/** 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);
    }}
}
Example #11
0
       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;
}
Example #12
0
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;
}