UConverterDataISO2022* myData2022 = ((UConverterDataISO2022*)_this->extraInfo);
uint32_t key = myData2022->key;
int32_t offset = 0;
+ int8_t initialToULength = _this->toULength;
char c;
value = VALID_NON_TERMINAL_2022;
return;
} else if (value == INVALID_2022 ) {
*err = U_ILLEGAL_ESCAPE_SEQUENCE;
- return;
} else /* value == VALID_TERMINAL_2022 */ {
switch(var){
#ifdef U_ENABLE_GENERIC_ISO_2022
}
if(U_SUCCESS(*err)) {
_this->toULength = 0;
+ } else if(*err==U_ILLEGAL_ESCAPE_SEQUENCE) {
+ if(_this->toULength>1) {
+ /*
+ * Ticket 5691: consistent illegal sequences:
+ * - We include at least the first byte (ESC) in the illegal sequence.
+ * - If any of the non-initial bytes could be the start of a character,
+ * we stop the illegal sequence before the first one of those.
+ * In escape sequences, all following bytes are "printable", that is,
+ * unless they are completely illegal (>7f in SBCS, outside 21..7e in DBCS),
+ * they are valid single/lead bytes.
+ * For simplicity, we always only report the initial ESC byte as the
+ * illegal sequence and back out all other bytes we looked at.
+ */
+ /* Back out some bytes. */
+ int8_t backOutDistance=_this->toULength-1;
+ int8_t bytesFromThisBuffer=_this->toULength-initialToULength;
+ if(backOutDistance<=bytesFromThisBuffer) {
+ /* same as initialToULength<=1 */
+ *source-=backOutDistance;
+ } else {
+ /* Back out bytes from the previous buffer: Need to replay them. */
+ _this->preToULength=(int8_t)(bytesFromThisBuffer-backOutDistance);
+ /* same as -(initialToULength-1) */
+ /* preToULength is negative! */
+ uprv_memcpy(_this->preToU, _this->toUBytes+1, -_this->preToULength);
+ *source-=bytesFromThisBuffer;
+ }
+ _this->toULength=1;
+ }
}
}
}
else{
cnv->toUBytes[0] =(char) sourceChar;
- cnv->toULength = 2;
+ cnv->toULength = 1;
}
if(targetUniChar == (missingCharMarker-1/*0xfffe*/)){
mySourceChar = args->converter->toUBytes[0];
args->converter->toULength = 0;
cs = (StateEnum)pToU2022State->cs[pToU2022State->g];
+ targetUniChar = missingCharMarker;
goto getTrailByte;
}
default:
/* G0 DBCS */
if(mySource < mySourceLimit) {
- char trailByte;
+ int leadIsOk, trailIsOk;
+ uint8_t trailByte;
getTrailByte:
+ trailByte = (uint8_t)*mySource;
+ /* old
tempBuf[0] = (char) (mySourceChar);
tempBuf[1] = trailByte = *mySource++;
mySourceChar = (mySourceChar << 8) | (uint8_t)(trailByte);
targetUniChar = ucnv_MBCSSimpleGetNextUChar(myData->myConverterArray[cs], tempBuf, 2, FALSE);
+ */
+ /*
+ * Ticket 5691: consistent illegal sequences:
+ * - We include at least the first byte in the illegal sequence.
+ * - If any of the non-initial bytes could be the start of a character,
+ *Ê Êwe stop the illegal sequence before the first one of those.
+ *
+ * In ISO-2022 DBCS, if the second byte is in the 21..7e range or is
+ * an ESC/SO/SI, we report only the first byte as the illegal sequence.
+ * Otherwise we convert or report the pair of bytes.
+ */
+ leadIsOk = (uint8_t)(mySourceChar - 0x21) <= (0x7e - 0x21);
+ trailIsOk = (uint8_t)(trailByte - 0x21) <= (0x7e - 0x21);
+ if (leadIsOk && trailIsOk) {
+ ++mySource;
+ tempBuf[0] = (char) (mySourceChar);
+ tempBuf[1] = trailByte;
+ mySourceChar = (mySourceChar << 8) | trailByte;
+ targetUniChar = ucnv_MBCSSimpleGetNextUChar(myData->myConverterArray[cs], tempBuf, 2, FALSE);
+ } else if (!(trailIsOk || IS_2022_CONTROL(trailByte))) {
+ /* report a pair of illegal bytes if the second byte is not a DBCS starter */
+ ++mySource;
+ /* add another bit so that the code below writes 2 bytes in case of error */
+ mySourceChar = 0x10000 | (mySourceChar << 8) | trailByte;
+ }
} else {
args->converter->toUBytes[0] = (uint8_t)mySourceChar;
args->converter->toULength = 1;
MBCS_FROM_UCHAR32_ISO2022(sharedData,sourceChar,&targetByteUnit,useFallback,&length,MBCS_OUTPUT_2);
/* only DBCS or SBCS characters are expected*/
/* DB characters with high bit set to 1 are expected */
- if(length > 2 || length==0 ||(((targetByteUnit & 0x8080) != 0x8080)&& length==2)){
+ if( length > 2 || length==0 ||
+ (length == 1 && targetByteUnit > 0x7f) ||
+ (length == 2 &&
+ ((uint16_t)(targetByteUnit - 0xa1a1) > (0xfefe - 0xa1a1) ||
+ (uint8_t)(targetByteUnit - 0xa1) > (0xfe - 0xa1)))
+ ) {
targetByteUnit=missingCharMarker;
}
if (targetByteUnit != missingCharMarker){
myData->isEmptySegment = FALSE; /* Any invalid char errors will be detected separately, so just reset this */
if(myData->toU2022State.g == 1) {
if(mySource < mySourceLimit) {
- char trailByte;
+ int leadIsOk, trailIsOk;
+ uint8_t trailByte;
getTrailByte:
+ /* old
trailByte = *mySource++;
tempBuf[0] = (char)(mySourceChar + 0x80);
tempBuf[1] = (char)(trailByte + 0x80);
mySourceChar = (mySourceChar << 8) | (uint8_t)(trailByte);
if((mySourceChar & 0x8080) == 0) {
targetUniChar = ucnv_MBCSSimpleGetNextUChar(sharedData, tempBuf, 2, useFallback);
- } else {
- /* illegal bytes > 0x7f */
- targetUniChar = missingCharMarker;
+ */
+ targetUniChar = missingCharMarker;
+ trailByte = (uint8_t)*mySource;
+ /*
+ * Ticket 5691: consistent illegal sequences:
+ * - We include at least the first byte in the illegal sequence.
+ * - If any of the non-initial bytes could be the start of a character,
+ * we stop the illegal sequence before the first one of those.
+ *
+ * In ISO-2022 DBCS, if the second byte is in the 21..7e range or is
+ * an ESC/SO/SI, we report only the first byte as the illegal sequence.
+ * Otherwise we convert or report the pair of bytes.
+ */
+ leadIsOk = (uint8_t)(mySourceChar - 0x21) <= (0x7e - 0x21);
+ trailIsOk = (uint8_t)(trailByte - 0x21) <= (0x7e - 0x21);
+ if (leadIsOk && trailIsOk) {
+ ++mySource;
+ tempBuf[0] = (char)(mySourceChar + 0x80);
+ tempBuf[1] = (char)(trailByte + 0x80);
+ targetUniChar = ucnv_MBCSSimpleGetNextUChar(sharedData, tempBuf, 2, useFallback);
+ mySourceChar = (mySourceChar << 8) | trailByte;
+ } else if (!(trailIsOk || IS_2022_CONTROL(trailByte))) {
+ /* report a pair of illegal bytes if the second byte is not a DBCS starter */
+ ++mySource;
+ /* add another bit so that the code below writes 2 bytes in case of error */
+ mySourceChar = 0x10000 | (mySourceChar << 8) | trailByte;
}
} else {
args->converter->toUBytes[0] = (uint8_t)mySourceChar;
break;
}
}
- else{
+ else if(mySourceChar <= 0x7f) {
targetUniChar = ucnv_MBCSSimpleGetNextUChar(sharedData, mySource - 1, 1, useFallback);
+ } else {
+ targetUniChar = 0xffff;
}
if(targetUniChar < 0xfffe){
if(args->offsets) {
/* continue with a partial double-byte character */
mySourceChar = args->converter->toUBytes[0];
args->converter->toULength = 0;
+ targetUniChar = missingCharMarker;
goto getTrailByte;
}
UConverterSharedData *cnv;
StateEnum tempState;
int32_t tempBufLen;
- char trailByte;
+ int leadIsOk, trailIsOk;
+ uint8_t trailByte;
getTrailByte:
+ /* old
trailByte = *mySource++;
tempState = (StateEnum)pToU2022State->cs[pToU2022State->g];
if(tempState > CNS_11643_0) {
tempBuf[0] = (char) (mySourceChar);
tempBuf[1] = trailByte;
tempBufLen = 2;
+ */
+ trailByte = (uint8_t)*mySource;
+ /*
+ * Ticket 5691: consistent illegal sequences:
+ * - We include at least the first byte in the illegal sequence.
+ * - If any of the non-initial bytes could be the start of a character,
+ * we stop the illegal sequence before the first one of those.
+ *
+ * In ISO-2022 DBCS, if the second byte is in the 21..7e range or is
+ * an ESC/SO/SI, we report only the first byte as the illegal sequence.
+ * Otherwise we convert or report the pair of bytes.
+ */
+ leadIsOk = (uint8_t)(mySourceChar - 0x21) <= (0x7e - 0x21);
+ trailIsOk = (uint8_t)(trailByte - 0x21) <= (0x7e - 0x21);
+ if (leadIsOk && trailIsOk) {
+ ++mySource;
+ tempState = (StateEnum)pToU2022State->cs[pToU2022State->g];
+ if(tempState >= CNS_11643_0) {
+ cnv = myData->myConverterArray[CNS_11643];
+ tempBuf[0] = (char) (0x80+(tempState-CNS_11643_0));
+ tempBuf[1] = (char) (mySourceChar);
+ tempBuf[2] = (char) trailByte;
+ tempBufLen = 3;
+
+ }else{
+ cnv = myData->myConverterArray[tempState];
+ tempBuf[0] = (char) (mySourceChar);
+ tempBuf[1] = (char) trailByte;
+ tempBufLen = 2;
+ }
+ targetUniChar = ucnv_MBCSSimpleGetNextUChar(cnv, tempBuf, tempBufLen, FALSE);
+ mySourceChar = (mySourceChar << 8) | trailByte;
+ } else if (!(trailIsOk || IS_2022_CONTROL(trailByte))) {
+ /* report a pair of illegal bytes if the second byte is not a DBCS starter */
+ ++mySource;
+ /* add another bit so that the code below writes 2 bytes in case of error */
+ mySourceChar = 0x10000 | (mySourceChar << 8) | trailByte;
}
- mySourceChar = (mySourceChar << 8) | (uint8_t)(trailByte);
if(pToU2022State->g>=2) {
/* return from a single-shift state to the previous one */
pToU2022State->g=pToU2022State->prevG;
}
- targetUniChar = ucnv_MBCSSimpleGetNextUChar(cnv, tempBuf, tempBufLen, FALSE);
} else {
args->converter->toUBytes[0] = (uint8_t)mySourceChar;
args->converter->toULength = 1;
UChar *myTarget = args->target;
const char *mySourceLimit = args->sourceLimit;
UChar32 targetUniChar = 0x0000;
- UChar mySourceChar = 0x0000;
+ int32_t mySourceChar = 0x0000;
UConverterDataHZ* myData=(UConverterDataHZ*)(args->converter->extraInfo);
tempBuf[0]=0;
tempBuf[1]=0;
if(myTarget < args->targetLimit){
mySourceChar= (unsigned char) *mySource++;
-
- switch(mySourceChar){
- case 0x0A:
- if(args->converter->mode ==UCNV_TILDE){
- args->converter->mode=0;
-
- }
- *(myTarget++)=(UChar)mySourceChar;
- myData->isEmptySegment = FALSE;
- continue;
- case UCNV_TILDE:
- if(args->converter->mode ==UCNV_TILDE){
- *(myTarget++)=(UChar)mySourceChar;
- args->converter->mode=0;
- myData->isEmptySegment = FALSE;
- continue;
-
- }
- else if(args->converter->toUnicodeStatus !=0){
- args->converter->mode=0;
- break;
- }
- else{
+ if(args->converter->mode == UCNV_TILDE) {
+ /* second byte after ~ */
+ args->converter->mode=0;
+ switch(mySourceChar) {
+ case 0x0A:
+ /* no output for ~\n (line-continuation marker) */
+ continue;
+ case UCNV_TILDE:
+ if(args->offsets) {
+ args->offsets[myTarget - args->target]=(int32_t)(mySource - args->source - 2);
+ }
+ *(myTarget++)=(UChar)mySourceChar;
+ myData->isEmptySegment = FALSE;
+ continue;
+ case UCNV_OPEN_BRACE:
+ case UCNV_CLOSE_BRACE:
+ myData->isStateDBCS = (mySourceChar == UCNV_OPEN_BRACE);
+ if (myData->isEmptySegment) {
+ myData->isEmptySegment = FALSE; /* we are handling it, reset to avoid future spurious errors */
+ *err = U_PARSE_ERROR; /* temporary err to flag empty segment, will be reset to U_ILLEGAL_ESCAPE_SEQUENCE in _toUnicodeWithCallback */
+ args->converter->toUBytes[0] = UCNV_TILDE;
+ args->converter->toUBytes[1] = mySourceChar;
+ args->converter->toULength = 2;
+ args->target = myTarget;
+ args->source = mySource;
+ return;
+ }
+ myData->isEmptySegment = TRUE;
+ continue;
+ default:
+ /* if the first byte is equal to TILDE and the trail byte
+ * is not a valid byte then it is an error condition
+ */
+ /* old
+ myData->isEmptySegment = FALSE;
+ mySourceChar= (UChar)(((UCNV_TILDE+0x80) << 8) | ((mySourceChar & 0x00ff)+0x80));
+ goto SAVE_STATE;
+ */
+ /*
+ * Ticket 5691: consistent illegal sequences:
+ * - We include at least the first byte in the illegal sequence.
+ * - If any of the non-initial bytes could be the start of a character,
+ * we stop the illegal sequence before the first one of those.
+ */
+ myData->isEmptySegment = FALSE; /* different error here, reset this to avoid spurious future error */
+ *err = U_ILLEGAL_ESCAPE_SEQUENCE;
+ args->converter->toUBytes[0] = UCNV_TILDE;
+ if( myData->isStateDBCS ?
+ (0x21 <= mySourceChar && mySourceChar <= 0x7e) :
+ mySourceChar <= 0x7f
+ ) {
+ /* The current byte could be the start of a character: Back it out. */
+ args->converter->toULength = 1;
+ --mySource;
+ } else {
+ /* Include the current byte in the illegal sequence. */
+ args->converter->toUBytes[1] = mySourceChar;
+ args->converter->toULength = 2;
+ }
+ args->target = myTarget;
+ args->source = mySource;
+ return;
+ }
+ } else if(myData->isStateDBCS) {
+ if(args->converter->toUnicodeStatus == 0x00){
+ /* lead byte */
+ if(mySourceChar == UCNV_TILDE) {
args->converter->mode = UCNV_TILDE;
- continue;
- }
-
-
- case UCNV_OPEN_BRACE:
- if(args->converter->mode == UCNV_TILDE){
- args->converter->mode=0;
- myData->isStateDBCS = TRUE;
- myData->isEmptySegment = TRUE;
- continue;
- }
- else{
- break;
- }
-
-
- case UCNV_CLOSE_BRACE:
- if(args->converter->mode == UCNV_TILDE){
- args->converter->mode=0;
- myData->isStateDBCS = FALSE;
- if (myData->isEmptySegment) {
- myData->isEmptySegment = FALSE; /* we are handling it, reset to avoid future spurious errors */
- *err = U_PARSE_ERROR; /* temporary err to flag empty segment, will be reset to U_ILLEGAL_ESCAPE_SEQUENCE in _toUnicodeWithCallback */
- args->converter->toUBytes[0] = UCNV_TILDE;
- args->converter->toUBytes[1] = mySourceChar;
- args->converter->toULength = 2;
- goto EXIT;
- }
- myData->isEmptySegment = TRUE;
- continue;
- }
- else{
- break;
- }
-
- default:
- /* if the first byte is equal to TILDE and the trail byte
- * is not a valid byte then it is an error condition
- */
- if(args->converter->mode == UCNV_TILDE){
- args->converter->mode=0;
- mySourceChar= (UChar)(((UCNV_TILDE+0x80) << 8) | ((mySourceChar & 0x00ff)+0x80));
- myData->isEmptySegment = FALSE; /* different error here, reset this to avoid spurious future error */
- goto SAVE_STATE;
+ } else {
+ /* add another bit to distinguish a 0 byte from not having seen a lead byte */
+ args->converter->toUnicodeStatus = (uint32_t) (mySourceChar | 0x100);
+ myData->isEmptySegment = FALSE; /* the segment has something, either valid or will produce a different error, so reset this */
}
-
- break;
-
- }
-
- myData->isEmptySegment = FALSE; /* the segment has something, either valid or will produce a different error, so reset this */
- if(myData->isStateDBCS){
- if(args->converter->toUnicodeStatus == 0x00){
- args->converter->toUnicodeStatus = (UChar) mySourceChar;
continue;
}
else{
+ /* trail byte */
+ /* old
tempBuf[0] = (char) (args->converter->toUnicodeStatus+0x80) ;
tempBuf[1] = (char) (mySourceChar+0x80);
mySourceChar= (UChar)(((args->converter->toUnicodeStatus+0x80) << 8) | ((mySourceChar & 0x00ff)+0x80));
args->converter->toUnicodeStatus =0x00;
targetUniChar = ucnv_MBCSSimpleGetNextUChar(myData->gbConverter->sharedData,
tempBuf, 2, args->converter->useFallback);
+ */
+ int leadIsOk, trailIsOk;
+ uint32_t leadByte = args->converter->toUnicodeStatus & 0xff;
+ targetUniChar = 0xffff;
+ /*
+ * Ticket 5691: consistent illegal sequences:
+ * - We include at least the first byte in the illegal sequence.
+ * - If any of the non-initial bytes could be the start of a character,
+ * we stop the illegal sequence before the first one of those.
+ *
+ * In HZ DBCS, if the second byte is in the 21..7e range,
+ * we report only the first byte as the illegal sequence.
+ * Otherwise we convert or report the pair of bytes.
+ */
+ leadIsOk = (uint8_t)(leadByte - 0x21) <= (0x7d - 0x21);
+ trailIsOk = (uint8_t)(mySourceChar - 0x21) <= (0x7e - 0x21);
+ if (leadIsOk && trailIsOk) {
+ tempBuf[0] = (char) (leadByte+0x80) ;
+ tempBuf[1] = (char) (mySourceChar+0x80);
+ targetUniChar = ucnv_MBCSSimpleGetNextUChar(myData->gbConverter->sharedData,
+ tempBuf, 2, args->converter->useFallback);
+ mySourceChar= (leadByte << 8) | mySourceChar;
+ } else if (trailIsOk) {
+ /* report a single illegal byte and continue with the following DBCS starter byte */
+ --mySource;
+ mySourceChar = (int32_t)leadByte;
+ } else {
+ /* report a pair of illegal bytes if the second byte is not a DBCS starter */
+ /* add another bit so that the code below writes 2 bytes in case of error */
+ mySourceChar= 0x10000 | (leadByte << 8) | mySourceChar;
+ }
+ args->converter->toUnicodeStatus =0x00;
}
}
else{
- if(args->converter->fromUnicodeStatus == 0x00){
- targetUniChar = ucnv_MBCSSimpleGetNextUChar(myData->gbConverter->sharedData,
- mySource - 1, 1, args->converter->useFallback);
- }
- else{
- goto SAVE_STATE;
+ if(mySourceChar == UCNV_TILDE) {
+ args->converter->mode = UCNV_TILDE;
+ continue;
+ } else if(mySourceChar <= 0x7f) {
+ targetUniChar = (UChar)mySourceChar; /* ASCII */
+ myData->isEmptySegment = FALSE; /* the segment has something valid */
+ } else {
+ targetUniChar = 0xffff;
+ myData->isEmptySegment = FALSE; /* different error here, reset this to avoid spurious future error */
}
-
}
if(targetUniChar < 0xfffe){
if(args->offsets) {
*(myTarget++)=(UChar)targetUniChar;
}
- else if(targetUniChar>=0xfffe){
-SAVE_STATE:
+ else /* targetUniChar>=0xfffe */ {
if(targetUniChar == 0xfffe){
*err = U_INVALID_CHAR_FOUND;
}
else{
*err = U_ILLEGAL_CHAR_FOUND;
}
- if(myData->isStateDBCS){
- /* this should never occur since isStateDBCS is set to true
- * only after tempBuf[0] and tempBuf[1]
- * are set to the input .. just to please BEAM
- */
- if(tempBuf[0]==0 || tempBuf[1]==0){
- *err = U_INTERNAL_PROGRAM_ERROR;
- }else{
- args->converter->toUBytes[0] = (uint8_t)(tempBuf[0]-0x80);
- args->converter->toUBytes[1] = (uint8_t)(tempBuf[1]-0x80);
+ if(mySourceChar > 0xff){
+ args->converter->toUBytes[0] = (uint8_t)(mySourceChar >> 8);
+ args->converter->toUBytes[1] = (uint8_t)mySourceChar;
args->converter->toULength=2;
}
- }
else{
args->converter->toUBytes[0] = (uint8_t)mySourceChar;
args->converter->toULength=1;
break;
}
}
-EXIT:
+
args->target = myTarget;
args->source = mySource;
}
/*
******************************************************************************
*
-* Copyright (C) 2000-2006, International Business Machines
+* Copyright (C) 2000-2006,2008, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
pArgs->offsets=offsets;
}
+static UBool
+hasValidTrailBytes(const int32_t (*stateTable)[256], uint8_t state) {
+ const int32_t *row=stateTable[state];
+ int32_t b, entry;
+ /* First test for final entries in this state for some commonly valid byte values. */
+ entry=row[0xa1];
+ if( !MBCS_ENTRY_IS_TRANSITION(entry) &&
+ MBCS_ENTRY_FINAL_ACTION(entry)!=MBCS_STATE_ILLEGAL
+ ) {
+ return TRUE;
+ }
+ entry=row[0x41];
+ if( !MBCS_ENTRY_IS_TRANSITION(entry) &&
+ MBCS_ENTRY_FINAL_ACTION(entry)!=MBCS_STATE_ILLEGAL
+ ) {
+ return TRUE;
+ }
+ /* Then test for final entries in this state. */
+ for(b=0; b<=0xff; ++b) {
+ entry=row[b];
+ if( !MBCS_ENTRY_IS_TRANSITION(entry) &&
+ MBCS_ENTRY_FINAL_ACTION(entry)!=MBCS_STATE_ILLEGAL
+ ) {
+ return TRUE;
+ }
+ }
+ /* Then recurse for transition entries. */
+ for(b=0; b<=0xff; ++b) {
+ entry=row[b];
+ if( MBCS_ENTRY_IS_TRANSITION(entry) &&
+ hasValidTrailBytes(stateTable, (uint8_t)MBCS_ENTRY_TRANSITION_STATE(entry))
+ ) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Is byte b a single/lead byte in this state?
+ * Recurse for transition states, because here we don't want to say that
+ * b is a lead byte if all byte sequences that start with b are illegal.
+ */
+static UBool
+isSingleOrLead(const int32_t (*stateTable)[256], uint8_t state, UBool isDBCSOnly, uint8_t b) {
+ const int32_t *row=stateTable[state];
+ int32_t entry=row[b];
+ if(MBCS_ENTRY_IS_TRANSITION(entry)) { /* lead byte */
+ return hasValidTrailBytes(stateTable, (uint8_t)MBCS_ENTRY_TRANSITION_STATE(entry));
+ } else {
+ uint8_t action=(uint8_t)(MBCS_ENTRY_FINAL_ACTION(entry));
+ if(action==MBCS_STATE_CHANGE_ONLY && isDBCSOnly) {
+ return FALSE; /* SI/SO are illegal for DBCS-only conversion */
+ } else {
+ return action!=MBCS_STATE_ILLEGAL;
+ }
+ }
+}
+
U_CFUNC void
ucnv_MBCSToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs,
UErrorCode *pErrorCode) {
sourceIndex=nextSourceIndex;
} else if(U_FAILURE(*pErrorCode)) {
/* callback(illegal) */
+ if(byteIndex>1) {
+ /*
+ * Ticket 5691: consistent illegal sequences:
+ * - We include at least the first byte in the illegal sequence.
+ * - If any of the non-initial bytes could be the start of a character,
+ * we stop the illegal sequence before the first one of those.
+ */
+ UBool isDBCSOnly=(UBool)(cnv->sharedData->mbcs.dbcsOnlyState!=0);
+ int8_t i;
+ for(i=1;
+ i<byteIndex && !isSingleOrLead(stateTable, state, isDBCSOnly, bytes[i]);
+ ++i) {}
+ if(i<byteIndex) {
+ /* Back out some bytes. */
+ int8_t backOutDistance=byteIndex-i;
+ int32_t bytesFromThisBuffer=(int32_t)(source-(const uint8_t *)pArgs->source);
+ byteIndex=i; /* length of reported illegal byte sequence */
+ if(backOutDistance<=bytesFromThisBuffer) {
+ source-=backOutDistance;
+ } else {
+ /* Back out bytes from the previous buffer: Need to replay them. */
+ cnv->preToULength=(int8_t)(bytesFromThisBuffer-backOutDistance);
+ /* preToULength is negative! */
+ uprv_memcpy(cnv->preToU, bytes+i, -cnv->preToULength);
+ source=(const uint8_t *)pArgs->source;
+ }
+ }
+ }
break;
} else /* unassigned sequences indicated with byteIndex>0 */ {
/* try an extension mapping */
&offsets, sourceIndex,
pArgs->flush,
pErrorCode);
- sourceIndex=nextSourceIndex+(int32_t)(source-(const uint8_t *)pArgs->source);
+ sourceIndex=nextSourceIndex+=(int32_t)(source-(const uint8_t *)pArgs->source);
if(U_FAILURE(*pErrorCode)) {
/* not mappable or buffer overflow */
if(c<0) {
if(U_SUCCESS(*pErrorCode) && source==sourceLimit && lastSource<source) {
- *pErrorCode=U_TRUNCATED_CHAR_FOUND;
- }
- if(U_FAILURE(*pErrorCode)) {
/* incomplete character byte sequence */
uint8_t *bytes=cnv->toUBytes;
cnv->toULength=(int8_t)(source-lastSource);
do {
*bytes++=*lastSource++;
} while(lastSource<source);
+ *pErrorCode=U_TRUNCATED_CHAR_FOUND;
+ } else if(U_FAILURE(*pErrorCode)) {
+ /* callback(illegal) */
+ /*
+ * Ticket 5691: consistent illegal sequences:
+ * - We include at least the first byte in the illegal sequence.
+ * - If any of the non-initial bytes could be the start of a character,
+ * we stop the illegal sequence before the first one of those.
+ */
+ UBool isDBCSOnly=(UBool)(cnv->sharedData->mbcs.dbcsOnlyState!=0);
+ uint8_t *bytes=cnv->toUBytes;
+ *bytes++=*lastSource++; /* first byte */
+ if(lastSource==source) {
+ cnv->toULength=1;
+ } else /* lastSource<source: multi-byte character */ {
+ int8_t i;
+ for(i=1;
+ lastSource<source && !isSingleOrLead(stateTable, state, isDBCSOnly, *lastSource);
+ ++i
+ ) {
+ *bytes++=*lastSource++;
+ }
+ cnv->toULength=i;
+ source=lastSource;
+ }
} else {
/* no output because of empty input or only state changes */
*pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2006, International Business Machines Corporation and
+ * Copyright (c) 1997-2006,2008, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/*
static const uint8_t text943[] = {
- 0x82, 0xa9, 0x82, 0x20, /*0xc8,*/ 0x61, 0x8a, 0xbf, 0x8e, 0x9a };
- static const UChar toUnicode943sub[] = { 0x304b, 0xfffd, /*0xff88,*/ 0x0061, 0x6f22, 0x5b57};
- static const UChar toUnicode943skip[]= { 0x304b, /*0xff88,*/ 0x0061, 0x6f22, 0x5b57};
+ 0x82, 0xa9, 0x82, 0x20, 0x61, 0x8a, 0xbf, 0x8e, 0x9a };
+ static const UChar toUnicode943sub[] = { 0x304b, 0x1a, 0x20, 0x0061, 0x6f22, 0x5b57 };
+ static const UChar toUnicode943skip[]= { 0x304b, 0x20, 0x0061, 0x6f22, 0x5b57 };
static const UChar toUnicode943stop[]= { 0x304b};
- static const int32_t fromIBM943Offssub[] = {0, 2, 4, 5, 7};
- static const int32_t fromIBM943Offsskip[] = { 0, 4, 5, 7};
+ static const int32_t fromIBM943Offssub[] = { 0, 2, 3, 4, 5, 7 };
+ static const int32_t fromIBM943Offsskip[] = { 0, 3, 4, 5, 7 };
static const int32_t fromIBM943Offsstop[] = { 0};
gInBufferSize = inputsize;
{
static const uint8_t sampleText[] = {
0x82, 0xa9, 0x61, 0x62, 0x63 , 0x82,
- 0xff, /*0x82, 0xa9,*/ 0x32, 0x33};
- static const UChar toUnicode943sub[] = {0x304b, 0x0061, 0x0062, 0x0063, 0xfffd,/*0x304b,*/ 0x0032, 0x0033};
- static const int32_t fromIBM943Offssub[] = {0, 2, 3, 4, 5, 7, 8};
+ 0xff, 0x32, 0x33};
+ static const UChar toUnicode943sub[] = { 0x304b, 0x0061, 0x0062, 0x0063, 0x1a, 0x1a, 0x0032, 0x0033 };
+ static const int32_t fromIBM943Offssub[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
/*checking illegal value for ibm-943 with substitute*/
gInBufferSize = inputsize;
gOutBufferSize = outputsize;
TestNextUCharError(cnv, source, source, U_INDEX_OUTOFBOUNDS_ERROR, "sourceLimit <= source");
/*Test for the condition where there is an invalid character*/
{
- static const uint8_t source2[]={0xa1, 0x01};
+ static const uint8_t source2[]={0xa1, 0x80};
TestNextUCharError(cnv, (const char*)source2, (const char*)source2+sizeof(source2), U_ZERO_ERROR, "an invalid character");
}
/*Test for the condition where we have a truncated char*/
TestISO_2022_KR() {
/* test input */
static const uint16_t in[]={
- 0x9F4B,0x9F4E,0x9F52,0x9F5F,0x9F61,0x9F66,0x9F67,0x9F6A,0x000A,0x000D
- ,0x9F6C,0x9F77,0x9F8D,0x9F90,0x9F95,0x9F9C,0xAC00,0xAC01,0xAC02,0xAC04
+ 0x9F4B,0x9F4E,0x9F52,0x9F5F,0x9F61,0x9F67,0x9F6A,0x000A,0x000D
+ ,0x9F6C,0x9F77,0x9F8D,0x9F90,0x9F95,0x9F9C,0xAC00,0xAC01,0xAC04
,0xAC07,0xAC08,0xAC09,0x0025,0x0026,0x0027,0x000A,0x000D,0x0028,0x0029
,0x002A,0x002B,0x002C,0x002D,0x002E,0x53C3,0x53C8,0x53C9,0x53CA,0x53CB
- ,0x53CD,0x53D4,0x53D6,0x53D7,0x53DB,0x000A,0x000D,0x53DF,0x53E1,0x53E2
+ ,0x53CD,0x53D4,0x53D6,0x53D7,0x53DB,0x000A,0x000D,0x53E1,0x53E2
,0x53E3,0x53E4,0x000A,0x000D};
const UChar* uSource;
const UChar* uSourceLimit;
//*******************************************************************************
//
-// Copyright (C) 2003-2006, International Business Machines
+// Copyright (C) 2003-2006,2008 International Business Machines
// Corporation and others. All Rights Reserved.
//
// file name: conversion.txt
toUnicode {
Headers { "charset", "bytes", "unicode", "offsets", "flush", "fallbacks", "errorCode", "callback", "invalidChars" }
Cases {
+ // Test ticket 5691: consistent illegal sequences
+ // The following test cases are for illegal character byte sequences.
+ //
+ // Unfortunately, we cannot use the Shift-JIS examples from the ticket
+ // comments because our Shift-JIS table is Windows-compatible and
+ // therefore has no illegal single bytes. Same for GBK.
+ // Instead, we use the stricter GB 18030 also for 2-byte examples.
+ // The byte sequences are generally slightly different from the ticket
+ // comment, simply using assigned characters rather than just
+ // theoretically valid sequences.
+ {
+ "gb18030",
+ :bin{ 618140813c81ff7a },
+ "a\u4e02\\x81<\\x81\\xFFz",
+ :intvector{ 0,1,3,3,3,3,4,5,5,5,5,5,5,5,5,7 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "EUC-JP",
+ :bin{ 618fb0a98fb03c8f3cb0a97a },
+ "a\u4e28\\x8F\\xB0<\\x8F<\u9022z",
+ :intvector{ 0,1,4,4,4,4,5,5,5,5,6,7,7,7,7,8,9,11 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "gb18030",
+ :bin{ 618130fc318130fc8181303c3e813cfc817a },
+ "a\u05ed\\x810\u9f07\\x810<>\\x81<\u9f07z",
+ :intvector{ 0,1,5,5,5,5,6,7,9,9,9,9,10,11,12,13,13,13,13,14,15,17 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "UTF-8",
+ :bin{ 61f1808182f180813cf18081fff180ff3cf1ff3c3e7a },
+ "a\U00040042\\xF1\\x80\\x81<\\xF1\\x80\\x81\\xFF\\xF1\\x80\\xFF<\\xF1\\xFF<>z",
+ :intvector{ 0,1,1,5,5,5,5,5,5,5,5,5,5,5,5,8,9,9,9,9,9,9,9,9,9,9,9,9,12,12,12,12,13,13,13,13,13,13,13,13,15,15,15,15,16,17,17,17,17,18,18,18,18,19,20,21 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "ISO-2022-JP",
+ :bin{ 1b24424141af4142affe41431b2842 },
+ "\u758f\\xAF\u758e\\xAF\\xFE\u790e",
+ :intvector{ 3,5,5,5,5,6,8,8,8,8,8,8,8,8,10 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "ibm-25546",
+ :bin{ 411b242943420e4141af4142affe41430f5a },
+ "AB\uc88b\\xAF\uc88c\\xAF\\xFE\uc88dZ",
+ :intvector{ 0,5,7,9,9,9,9,10,12,12,12,12,12,12,12,12,14,17 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "ISO-2022-KR",
+ :bin{ 411b242943420e4141af4142affe41430f5a },
+ "AB\uc88b\\xAF\uc88c\\xAF\\xFE\uc88dZ",
+ :intvector{ 0,5,7,9,9,9,9,10,12,12,12,12,12,12,12,12,14,17 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "ISO-2022-CN",
+ :bin{ 411b242941420e4141af4142affe41430f5a },
+ "AB\u4eae\\xAF\u8c05\\xAF\\xFE\u64a9Z",
+ :intvector{ 0,5,7,9,9,9,9,10,12,12,12,12,12,12,12,12,14,17 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "HZ",
+ :bin{ 417e7b4141af4142affe41437e7d5a },
+ "A\u4eae\\xAF\u8c05\\xAF\\xFE\u64a9Z",
+ :intvector{ 0,3,5,5,5,5,6,8,8,8,8,8,8,8,8,10,14 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ // Test ticket 5691: consistent illegal sequences
+ // The following test cases are for illegal escape/designator/shift sequences.
+ //
+ // ISO-2022-JP and -CN with illegal escape sequences.
+ {
+ "ISO-2022-JP",
+ :bin{ 611b24201b244241411b283f1b28427a },
+ "a\\x1B$ \u758f\\x1B\u2538z",
+ :intvector{ 0,1,1,1,1,2,3,7,9,9,9,9,10,15 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "ISO-2022-CN",
+ :bin{ 611b2429201b2429410e41410f7a },
+ "a\\x1B$) \u4eaez",
+ :intvector{ 0,1,1,1,1,2,3,4,10,13 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ // Test ticket 5691: ISO-2022-JP-2 with illegal single-shift SS2 and SS3 sequences.
+ // The first ESC N comes before its designator sequence, the last sequence is ESC+space.
+ {
+ "ISO-2022-JP-2",
+ :bin{ 4e1b4e4e1b2e414e1b4e4e4e1b204e },
+ "N\\x1BNNN\xceN\\x1B N",
+ :intvector{ 0,1,1,1,1,2,3,7,10,11,12,12,12,12,13,14 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "ISO-2022-CN-EXT",
+ :bin{ 4e1b4e4e1b242a484e1b4e4e4e4e1b204e },
+ "N\\x1BNNN\u8f0eN\\x1B N",
+ :intvector{ 0,1,1,1,1,2,3,8,11,13,14,14,14,14,15,16 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ {
+ "ISO-2022-CN-EXT",
+ :bin{ 4f1b4f4f1b242b494f1b4f4f4f4f1b204f },
+ "O\\x1BOOO\u492bO\\x1B O",
+ :intvector{ 0,1,1,1,1,2,3,8,11,13,14,14,14,14,15,16 },
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ // Test ticket 5691: HZ with illegal tilde sequences.
+ {
+ "HZ",
+ :bin{ 417e20427e21437e80447e7b41417e207e41427e7f41437e7d5a },
+ "A\\x7E B\\x7E!C\\x7E\\x80D\u4eae\\x7E\\x20\\x7E\u8c05\\x7E\\x7F\u64a9Z",
+ :intvector{ 0,1,1,1,1,2,3,4,4,4,4,5,6,7,7,7,7,7,7,7,7,9, // SBCS
+ 12,14,14,14,14,14,14,14,14,16,16,16,16,17,19,19,19,19,19,19,19,19,21, // DBCS
+ 25 }, // SBCS
+ :int{1}, :int{0}, "", "&C", :bin{""}
+ }
+ // Test ticket 5691: Example from Peter Edberg.
+ {
+ "ISO-2022-JP",
+ :bin{ 1b244230212f7e742630801b284a621b2458631b2842648061 },
+ "\u4e9c\ufffd\u7199\ufffdb\ufffd$Xcd\ufffda",
+ :intvector{ 3,5,7,9,14,15,16,17,18,22,23,24 },
+ :int{1}, :int{0}, "", "?", :bin{""}
+ }
+ // test that HZ limits its byte values to lead bytes 21..7d and trail bytes 21..7e
+ {
+ "HZ",
+ :bin{ 7e7b21212120217e217f772100007e217e7e7d207e7e807e0a2b },
+ "\u3000\ufffd\u3013\ufffd\u9ccc\ufffd\ufffd\u3013 ~\ufffd+",
+ :intvector{ 2,4,6,8,10,12,14,15,19,20,22,25 },
+ :int{1}, :int{1}, "", "?", :bin{""}
+ }
+ // improve coverage of ISO-2022-JP converter with hardcoded JIS X 0201 and
+ // using the Shift-JIS table for JIS X 0208 (ticket #5797)
+ {
+ "ISO-2022-JP",
+ :bin{ 1b284a7d7e801b2442306c20217f7e21202160217f22202225227f5f211b2842 },
+ "}\u203e\ufffd\u4e00\ufffd\ufffd\ufffd\ufffd\xf7\ufffd\ufffd\u25b2\ufffd\u6f3e",
+ :intvector{ 3,4,5,9,11,12,14,16,17,19,21,23,25,27 },
+ :int{1}, :int{1}, "", "?", :bin{""}
+ }
// improve coverage of unrolled loops in ucnvmbcs.c/ucnv_MBCSSingleToBMPWithOffsets()
{
"ISO-8859-3",
{
"ISO-2022-CN-EXT",
:bin{ 411b4e2121 }, "\x41", :intvector{ 0 },
- :int{1}, :int{1}, "illesc", ".", :bin{ 1b4e }
+ :int{1}, :int{1}, "illesc", ".", :bin{ 1b }
}
// G3 designator: recognized, but not supported for -CN (only for -CN-EXT)
{
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="icuzdump"
ProjectGUID="{655F4481-B461-4DF0-AF10-0D01114A26C1}"
RootNamespace="icuzdump"
Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
GenerateDebugInformation="true"
ProgramDatabaseFile=".\x86\Debug/icuzdump.pdb"
SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="0"
/>
<Tool
<Tool
Name="VCAppVerifierTool"
/>
- <Tool
- Name="VCWebDeploymentTool"
- />
<Tool
Name="VCPostBuildEventTool"
/>
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
<Tool
Name="VCAppVerifierTool"
/>
- <Tool
- Name="VCWebDeploymentTool"
- />
<Tool
Name="VCPostBuildEventTool"
/>
#ifndef lint
#ifndef NOID
-static char elsieid[] = "@(#)localtime.c 8.5";
+static char elsieid[] = "@(#)localtime.c 8.9";
#endif /* !defined NOID */
#endif /* !defined lint */
** Prototypes for static functions.
*/
-static long detzcode P((const char * codep));
-static time_t detzcode64 P((const char * codep));
-static int differ_by_repeat P((time_t t1, time_t t0));
-static const char * getzname P((const char * strp));
-static const char * getqzname P((const char * strp, const int delim));
-static const char * getnum P((const char * strp, int * nump, int min,
- int max));
-static const char * getsecs P((const char * strp, long * secsp));
-static const char * getoffset P((const char * strp, long * offsetp));
-static const char * getrule P((const char * strp, struct rule * rulep));
-static void gmtload P((struct state * sp));
-static struct tm * gmtsub P((const time_t * timep, long offset,
- struct tm * tmp));
-static struct tm * localsub P((const time_t * timep, long offset,
- struct tm * tmp));
-static int increment_overflow P((int * number, int delta));
-static int leaps_thru_end_of P((int y));
-static int long_increment_overflow P((long * number, int delta));
-static int long_normalize_overflow P((long * tensptr,
- int * unitsptr, int base));
-static int normalize_overflow P((int * tensptr, int * unitsptr,
- int base));
-static void settzname P((void));
-static time_t time1 P((struct tm * tmp,
- struct tm * (*funcp) P((const time_t *,
- long, struct tm *)),
- long offset));
-static time_t time2 P((struct tm *tmp,
- struct tm * (*funcp) P((const time_t *,
- long, struct tm*)),
- long offset, int * okayp));
-static time_t time2sub P((struct tm *tmp,
- struct tm * (*funcp) P((const time_t *,
- long, struct tm*)),
- long offset, int * okayp, int do_norm_secs));
-static struct tm * timesub P((const time_t * timep, long offset,
- const struct state * sp, struct tm * tmp));
-static int tmcomp P((const struct tm * atmp,
- const struct tm * btmp));
-static time_t transtime P((time_t janfirst, int year,
- const struct rule * rulep, long offset));
-static int tzload P((const char * name, struct state * sp,
- int doextend));
-static int tzparse P((const char * name, struct state * sp,
- int lastditch));
+static long detzcode(const char * codep);
+static time_t detzcode64(const char * codep);
+static int differ_by_repeat(time_t t1, time_t t0);
+static const char * getzname(const char * strp);
+static const char * getqzname(const char * strp, const int delim);
+static const char * getnum(const char * strp, int * nump, int min,
+ int max);
+static const char * getsecs(const char * strp, long * secsp);
+static const char * getoffset(const char * strp, long * offsetp);
+static const char * getrule(const char * strp, struct rule * rulep);
+static void gmtload(struct state * sp);
+static struct tm * gmtsub(const time_t * timep, long offset,
+ struct tm * tmp);
+static struct tm * localsub(const time_t * timep, long offset,
+ struct tm * tmp);
+static int increment_overflow(int * number, int delta);
+static int leaps_thru_end_of(int y);
+static int long_increment_overflow(long * number, int delta);
+static int long_normalize_overflow(long * tensptr,
+ int * unitsptr, int base);
+static int normalize_overflow(int * tensptr, int * unitsptr,
+ int base);
+static void settzname(void);
+static time_t time1(struct tm * tmp,
+ struct tm * (*funcp)(const time_t *,
+ long, struct tm *),
+ long offset);
+static time_t time2(struct tm *tmp,
+ struct tm * (*funcp)(const time_t *,
+ long, struct tm*),
+ long offset, int * okayp);
+static time_t time2sub(struct tm *tmp,
+ struct tm * (*funcp)(const time_t *,
+ long, struct tm*),
+ long offset, int * okayp, int do_norm_secs);
+static struct tm * timesub(const time_t * timep, long offset,
+ const struct state * sp, struct tm * tmp);
+static int tmcomp(const struct tm * atmp,
+ const struct tm * btmp);
+static time_t transtime(time_t janfirst, int year,
+ const struct rule * rulep, long offset);
+static int typesequiv(const struct state * sp, int a, int b);
+static int tzload(const char * name, struct state * sp,
+ int doextend);
+static int tzparse(const char * name, struct state * sp,
+ int lastditch);
#ifdef ALL_STATE
static struct state * lclptr;
}
static void
-settzname P((void))
+settzname(void)
{
register struct state * const sp = lclptr;
register int i;
sp->ttis[sp->typecnt++] = ts.ttis[1];
}
}
- i = 2 * YEARSPERREPEAT;
- sp->goback = sp->goahead = sp->timecnt > i;
- sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
- differ_by_repeat(sp->ats[i], sp->ats[0]);
- sp->goahead = sp->goahead &&
- sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
- differ_by_repeat(sp->ats[sp->timecnt - 1],
- sp->ats[sp->timecnt - 1 - i]);
+ sp->goback = sp->goahead = FALSE;
+ if (sp->timecnt > 1) {
+ for (i = 1; i < sp->timecnt; ++i)
+ if (typesequiv(sp, sp->types[i], sp->types[0]) &&
+ differ_by_repeat(sp->ats[i], sp->ats[0])) {
+ sp->goback = TRUE;
+ break;
+ }
+ for (i = sp->timecnt - 2; i >= 0; --i)
+ if (typesequiv(sp, sp->types[sp->timecnt - 1],
+ sp->types[i]) &&
+ differ_by_repeat(sp->ats[sp->timecnt - 1],
+ sp->ats[i])) {
+ sp->goahead = TRUE;
+ break;
+ }
+ }
return 0;
}
+static int
+typesequiv(sp, a, b)
+const struct state * const sp;
+const int a;
+const int b;
+{
+ register int result;
+
+ if (sp == NULL ||
+ a < 0 || a >= sp->typecnt ||
+ b < 0 || b >= sp->typecnt)
+ result = FALSE;
+ else {
+ register const struct ttinfo * ap = &sp->ttis[a];
+ register const struct ttinfo * bp = &sp->ttis[b];
+ result = ap->tt_gmtoff == bp->tt_gmtoff &&
+ ap->tt_isdst == bp->tt_isdst &&
+ ap->tt_ttisstd == bp->tt_ttisstd &&
+ ap->tt_ttisgmt == bp->tt_ttisgmt &&
+ strcmp(&sp->chars[ap->tt_abbrind],
+ &sp->chars[bp->tt_abbrind]) == 0;
+ }
+ return result;
+}
+
static const int mon_lengths[2][MONSPERYEAR] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
static
#endif /* !defined STD_INSPIRED */
void
-tzsetwall P((void))
+tzsetwall(void)
{
if (lcl_is_set < 0)
return;
}
void
-tzset P((void))
+tzset(void)
{
register const char * name;
static time_t
time2sub(tmp, funcp, offset, okayp, do_norm_secs)
struct tm * const tmp;
-struct tm * (* const funcp) P((const time_t*, long, struct tm*));
+struct tm * (* const funcp)(const time_t*, long, struct tm*);
const long offset;
int * const okayp;
const int do_norm_secs;
** It's okay to guess wrong since the guess
** gets checked.
*/
- /*
- ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
- */
sp = (const struct state *)
- (((void *) funcp == (void *) localsub) ?
- lclptr : gmtptr);
+ ((funcp == localsub) ? lclptr : gmtptr);
#ifdef ALL_STATE
if (sp == NULL)
return WRONG;
static time_t
time2(tmp, funcp, offset, okayp)
struct tm * const tmp;
-struct tm * (* const funcp) P((const time_t*, long, struct tm*));
+struct tm * (* const funcp)(const time_t*, long, struct tm*);
const long offset;
int * const okayp;
{
static time_t
time1(tmp, funcp, offset)
struct tm * const tmp;
-struct tm * (* const funcp) P((const time_t *, long, struct tm *));
+struct tm * (* const funcp)(const time_t *, long, struct tm *);
const long offset;
{
register time_t t;
** We try to divine the type they started from and adjust to the
** type they need.
*/
- /*
- ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
- */
- sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
- lclptr : gmtptr);
+ sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr);
#ifdef ALL_STATE
if (sp == NULL)
return WRONG;
#ifndef lint
#ifndef NOID
-static char privatehid[] = "@(#)private.h 8.2";
+static char privatehid[] = "@(#)private.h 8.6";
#endif /* !defined NOID */
#endif /* !defined lint */
#define HAVE_SETTIMEOFDAY 3
#endif /* !defined HAVE_SETTIMEOFDAY */
-#ifndef HAVE_STRERROR
-#define HAVE_STRERROR 1
-#endif /* !defined HAVE_STRERROR */
-
#ifndef HAVE_SYMLINK
#define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
#endif /* !defined WEXITSTATUS */
#if HAVE_UNISTD_H
-#include "unistd.h" /* for F_OK and R_OK */
+#include "unistd.h" /* for F_OK, R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */
-#if !HAVE_UNISTD_H
#ifndef F_OK
#define F_OK 0
#endif /* !defined F_OK */
#ifndef R_OK
#define R_OK 4
#endif /* !defined R_OK */
-#endif /* !HAVE_UNISTD_H */
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
** Workarounds for compilers/systems.
*/
-/*
-** If your compiler lacks prototypes, "#define P(x) ()".
-*/
-
-#ifndef P
-#define P(x) x
-#endif /* !defined P */
-
-/*
-** SunOS 4.1.1 headers lack EXIT_SUCCESS.
-*/
-
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif /* !defined EXIT_SUCCESS */
-
-/*
-** SunOS 4.1.1 headers lack EXIT_FAILURE.
-*/
-
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif /* !defined EXIT_FAILURE */
-
-/*
-** SunOS 4.1.1 headers lack FILENAME_MAX.
-*/
-
-#ifndef FILENAME_MAX
-
-#ifndef MAXPATHLEN
-#ifdef unix
-#include "sys/param.h"
-#endif /* defined unix */
-#endif /* !defined MAXPATHLEN */
-
-#ifdef MAXPATHLEN
-#define FILENAME_MAX MAXPATHLEN
-#endif /* defined MAXPATHLEN */
-#ifndef MAXPATHLEN
-#define FILENAME_MAX 1024 /* Pure guesswork */
-#endif /* !defined MAXPATHLEN */
-
-#endif /* !defined FILENAME_MAX */
-
-/*
-** SunOS 4.1.1 libraries lack remove.
-*/
-
-#ifndef remove
-extern int unlink P((const char * filename));
-#define remove unlink
-#endif /* !defined remove */
-
-/*
-** Some ancient errno.h implementations don't declare errno.
-** But some newer errno.h implementations define it as a macro.
-** Fix the former without affecting the latter.
-*/
-
-#ifndef errno
-extern int errno;
-#endif /* !defined errno */
-
/*
** Some time.h implementations don't declare asctime_r.
** Others might define it as a macro.
*/
#ifndef asctime_r
-extern char * asctime_r();
+extern char * asctime_r(struct tm const *, char *);
#endif
/*
** Private function declarations.
*/
-char * icalloc P((int nelem, int elsize));
-char * icatalloc P((char * old, const char * new));
-char * icpyalloc P((const char * string));
-char * imalloc P((int n));
-void * irealloc P((void * pointer, int size));
-void icfree P((char * pointer));
-void ifree P((char * pointer));
-const char * scheck P((const char * string, const char * format));
+char * icalloc(int nelem, int elsize);
+char * icatalloc(char * old, const char * new);
+char * icpyalloc(const char * string);
+char * imalloc(int n);
+void * irealloc(void * pointer, int size);
+void icfree(char * pointer);
+void ifree(char * pointer);
+const char * scheck(const char * string, const char * format);
/*
** Finally, some convenience items.
#if HAVE_INCOMPATIBLE_CTIME_R
#undef asctime_r
#undef ctime_r
-char *asctime_r P((struct tm const *, char *));
-char *ctime_r P((time_t const *, char *));
+char *asctime_r(struct tm const *, char *);
+char *ctime_r(time_t const *, char *);
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
#ifndef YEARSPERREPEAT
#ifndef SECSPERREPEAT
#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
#endif /* !defined SECSPERREPEAT */
-
+
#ifndef SECSPERREPEAT_BITS
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
#endif /* !defined SECSPERREPEAT_BITS */
-static char elsieid[] = "@(#)zdump.c 8.3";
+static char elsieid[] = "@(#)zdump.c 8.8";
/*
** This code has been made independent of the rest of the time
#define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR)
#define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY)
+#ifndef HAVE_GETTEXT
+#define HAVE_GETTEXT 0
+#endif
#if HAVE_GETTEXT
#include "locale.h" /* for setlocale */
#include "libintl.h"
#define TZ_DOMAIN "tz"
#endif /* !defined TZ_DOMAIN */
-#ifndef P
-#define P(x) x
-#endif /* !defined P */
-
extern char ** environ;
-extern int getopt P((int argc, char * const argv[],
- const char * options));
+extern int getopt(int argc, char * const argv[],
+ const char * options);
extern char * optarg;
extern int optind;
extern char * tzname[2];
static char * progname;
static int warned;
-static char * abbr P((struct tm * tmp));
-static void abbrok P((const char * abbrp, const char * zone));
-static long delta P((struct tm * newp, struct tm * oldp));
-static void dumptime P((const struct tm * tmp));
-static time_t hunt P((char * name, time_t lot, time_t hit));
-static void setabsolutes P((void));
-static void show P((char * zone, time_t t, int v));
-static const char * tformat P((void));
-static time_t yeartot P((long y));
+static char * abbr(struct tm * tmp);
+static void abbrok(const char * abbrp, const char * zone);
+static long delta(struct tm * newp, struct tm * oldp);
+static void dumptime(const struct tm * tmp);
+static time_t hunt(char * name, time_t lot, time_t hit);
+static void setabsolutes(void);
+static void show(char * zone, time_t t, int v);
+static const char * tformat(void);
+static time_t yeartot(long y);
#ifdef ICU
typedef struct listentry {
char * name;
struct listentry * next;
} listentry;
-static time_t huntICU P((char * name, time_t lot, time_t hit, FILE *fp));
-static void dumptimeICU P((FILE * fp, time_t t));
-static void showICU P((FILE * fp, char * zone, time_t t1, time_t t2));
-static int getall P((struct listentry ** namelist));
-static void getzones P((char * basedir, char * subdir, struct listentry ** last, int * count));
+static time_t huntICU(char * name, time_t lot, time_t hit, FILE *fp);
+static void dumptimeICU(FILE * fp, time_t t);
+static void showICU(FILE * fp, char * zone, time_t t1, time_t t2);
+static int getall(struct listentry ** namelist);
+static void getzones(char * basedir, char * subdir, struct listentry ** last, int * count);
#endif
#ifndef TYPECHECK
warned = TRUE;
}
+static void
+usage(const char *progname, FILE *stream, int status)
+{
+ (void) fprintf(stream,
+_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n\
+\n\
+Report bugs to tz@elsie.nci.nih.gov.\n"),
+ progname, progname);
+ exit(status);
+}
+
int
main(argc, argv)
int argc;
if (strcmp(argv[i], "--version") == 0) {
(void) printf("%s\n", elsieid);
exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "--help") == 0) {
+ usage(progname, stdout, EXIT_SUCCESS);
}
vflag = 0;
cutarg = NULL;
else cutarg = optarg;
if ((c != EOF && c != -1) ||
(optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
- (void) fprintf(stderr,
-_("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
- progname, progname);
- exit(EXIT_FAILURE);
+ usage(progname, stderr, EXIT_FAILURE);
}
#endif
if (vflag) {
(void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
}
for ( ; ; ) {
- if (t >= cuthitime)
+ if (t >= cuthitime || t >= cuthitime - SECSPERHOUR * 12)
break;
newt = t + SECSPERHOUR * 12;
- if (newt >= cuthitime)
- break;
- if (newt <= t)
- break;
newtmp = localtime(&newt);
if (newtmp != NULL)
newtm = *newtmp;
}
static void
-setabsolutes()
+setabsolutes(void)
{
if (0.5 == (time_t) 0.5) {
/*
t = t1;
t1 = 2 * t1 + 1;
}
-
+
absolute_max_time = t;
t = -t;
absolute_min_time = t - 1;
*/
static const char *
-tformat()
+tformat(void)
{
if (0.5 == (time_t) 0.5) { /* floating */
if (sizeof (time_t) > sizeof (double))
** 2006-07-17 by Arthur David Olson.
*/
-static char elsieid[] = "@(#)zic.c 8.7";
+static char elsieid[] = "@(#)zic.c 8.18";
#include "private.h"
#include "locale.h"
zic_t z_untiltime;
};
-extern int getopt P((int argc, char * const argv[],
- const char * options));
-extern int link P((const char * fromname, const char * toname));
+extern int getopt(int argc, char * const argv[],
+ const char * options);
+extern int link(const char * fromname, const char * toname);
extern char * optarg;
extern int optind;
-static void addtt P((zic_t starttime, int type));
+static void addtt(zic_t starttime, int type);
#ifdef ICU
-static int addtype P((long gmtoff, long rawoff, long dstoff,
+static int addtype(long gmtoff, long rawoff, long dstoff,
const char * abbr, int isdst,
- int ttisstd, int ttisgmt));
+ int ttisstd, int ttisgmt);
#else
-static int addtype P((long gmtoff, const char * abbr, int isdst,
- int ttisstd, int ttisgmt));
+static int addtype(long gmtoff, const char * abbr, int isdst,
+ int ttisstd, int ttisgmt);
#endif
-static void leapadd P((zic_t t, int positive, int rolling, int count));
-static void adjleap P((void));
-static void associate P((void));
-static int ciequal P((const char * ap, const char * bp));
-static void convert P((long val, char * buf));
-static void convert64 P((zic_t val, char * buf));
-static void dolink P((const char * fromfile, const char * tofile));
-static void doabbr P((char * abbr, const char * format,
- const char * letters, int isdst, int doquotes));
-static void eat P((const char * name, int num));
-static void eats P((const char * name, int num,
- const char * rname, int rnum));
-static long eitol P((int i));
-static void error P((const char * message));
-static char ** getfields P((char * buf));
-static long gethms P((const char * string, const char * errstrng,
- int signable));
-static void infile P((const char * filename));
-static void inleap P((char ** fields, int nfields));
-static void inlink P((char ** fields, int nfields));
-static void inrule P((char ** fields, int nfields));
-static int inzcont P((char ** fields, int nfields));
-static int inzone P((char ** fields, int nfields));
-static int inzsub P((char ** fields, int nfields, int iscont));
-static int is32 P((zic_t x));
-static int itsabbr P((const char * abbr, const char * word));
-static int itsdir P((const char * name));
-static int lowerit P((int c));
-static char * memcheck P((char * tocheck));
-static int mkdirs P((char * filename));
-static void newabbr P((const char * abbr));
-static long oadd P((long t1, long t2));
-static void outzone P((const struct zone * zp, int ntzones));
-static void puttzcode P((long code, FILE * fp));
-static void puttzcode64 P((zic_t code, FILE * fp));
-static int rcomp P((const void * leftp, const void * rightp));
-static zic_t rpytime P((const struct rule * rp, int wantedy));
-static void rulesub P((struct rule * rp,
+static void leapadd(zic_t t, int positive, int rolling, int count);
+static void adjleap(void);
+static void associate(void);
+static int ciequal(const char * ap, const char * bp);
+static void convert(long val, char * buf);
+static void convert64(zic_t val, char * buf);
+static void dolink(const char * fromfield, const char * tofield);
+static void doabbr(char * abbr, const char * format,
+ const char * letters, int isdst, int doquotes);
+static void eat(const char * name, int num);
+static void eats(const char * name, int num,
+ const char * rname, int rnum);
+static long eitol(int i);
+static void error(const char * message);
+static char ** getfields(char * buf);
+static long gethms(const char * string, const char * errstrng,
+ int signable);
+static void infile(const char * filename);
+static void inleap(char ** fields, int nfields);
+static void inlink(char ** fields, int nfields);
+static void inrule(char ** fields, int nfields);
+static int inzcont(char ** fields, int nfields);
+static int inzone(char ** fields, int nfields);
+static int inzsub(char ** fields, int nfields, int iscont);
+static int is32(zic_t x);
+static int itsabbr(const char * abbr, const char * word);
+static int itsdir(const char * name);
+static int lowerit(int c);
+static char * memcheck(char * tocheck);
+static int mkdirs(char * filename);
+static void newabbr(const char * abbr);
+static long oadd(long t1, long t2);
+static void outzone(const struct zone * zp, int ntzones);
+static void puttzcode(long code, FILE * fp);
+static void puttzcode64(zic_t code, FILE * fp);
+static int rcomp(const void * leftp, const void * rightp);
+static zic_t rpytime(const struct rule * rp, int wantedy);
+static void rulesub(struct rule * rp,
const char * loyearp, const char * hiyearp,
const char * typep, const char * monthp,
- const char * dayp, const char * timep));
-static int stringoffset P((char * result, long offset));
-static int stringrule P((char * result, const struct rule * rp,
- long dstoff, long gmtoff));
-static void stringzone P((char * result,
- const struct zone * zp, int ntzones));
-static void setboundaries P((void));
-static zic_t tadd P((zic_t t1, long t2));
-static void usage P((void));
-static void writezone P((const char * name, const char * string));
-static int yearistype P((int year, const char * type));
-
-#if !HAVE_STRERROR
-static char * strerror P((int));
-#endif /* !HAVE_STRERROR */
+ const char * dayp, const char * timep);
+static int stringoffset(char * result, long offset);
+static int stringrule(char * result, const struct rule * rp,
+ long dstoff, long gmtoff);
+static void stringzone(char * result,
+ const struct zone * zp, int ntzones);
+static void setboundaries(void);
+static zic_t tadd(zic_t t1, long t2);
+static void usage(FILE *stream, int status);
+static void writezone(const char * name, const char * string);
+static int yearistype(int year, const char * type);
+#ifdef ICU
+static void emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset,
+ const struct rule* rule,
+ int ruleIndex, int startYear);
+static void emit_icu_link(FILE* f, const char* from, const char* to);
+static void emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex);
+static int add_icu_final_rules(const struct rule* r1, const struct rule* r2);
+#endif
static int charcnt;
static int errors;
};
#ifdef ICU
-
/* Indices into rules[] for final rules. They will occur in pairs,
* with finalRules[i] occurring before finalRules[i+1] in the year.
* Each zone need only store a start year, a standard offset, and an
* index into finalRules[]. FinalRules[] are aliases into rules[]. */
-
-static const struct rule ** finalRules;
-static int finalRulesCount;
-
+static const struct rule ** finalRules;
+static int finalRulesCount;
#endif
-static struct lookup const * byword P((const char * string,
- const struct lookup * lp));
+static struct lookup const * byword(const char * string,
+ const struct lookup * lp);
static struct lookup const line_codes[] = {
{ "Rule", LC_RULE },
** Error handling.
*/
-#if !HAVE_STRERROR
-static char *
-strerror(errnum)
-int errnum;
-{
- extern char * sys_errlist[];
- extern int sys_nerr;
-
- return (errnum > 0 && errnum <= sys_nerr) ?
- sys_errlist[errnum] : _("Unknown system error");
-}
-#endif /* !HAVE_STRERROR */
-
static void
eats(name, num, rname, rnum)
const char * const name;
}
static void
-usage P((void))
+usage(FILE *stream, int status)
{
- (void) fprintf(stderr, _("%s: usage is %s \
-[ --version ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
-\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
- progname, progname);
- exit(EXIT_FAILURE);
+ (void) fprintf(stream, _("%s: usage is %s \
+[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
+\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\
+\n\
+Report bugs to tz@elsie.nci.nih.gov.\n"),
+ progname, progname);
+ exit(status);
}
#ifdef ICU
-
/* File into which we will write supplemental ICU data. */
-static FILE * icuFile;
-
-void emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset,
- const struct rule* rule,
- int ruleIndex, int startYear) {
- /* machine-readable section */
- fprintf(f, "zone %s %d %d %s", zoneName, zoneOffset, startYear, rule->r_name);
-
- /* human-readable section */
- fprintf(f, " # zone %s, offset %d, year >= %d, rule %s (%d)\n",
- zoneName, zoneOffset, startYear,
- rule->r_name, ruleIndex);
+static FILE * icuFile;
+
+static void
+emit_icu_zone(FILE* f, const char* zoneName, int zoneOffset,
+ const struct rule* rule,
+ int ruleIndex, int startYear) {
+ /* machine-readable section */
+ fprintf(f, "zone %s %d %d %s", zoneName, zoneOffset, startYear, rule->r_name);
+
+ /* human-readable section */
+ fprintf(f, " # zone %s, offset %d, year >= %d, rule %s (%d)\n",
+ zoneName, zoneOffset, startYear,
+ rule->r_name, ruleIndex);
}
-void emit_icu_link(FILE* f, const char* from, const char* to) {
- /* machine-readable section */
- fprintf(f, "link %s %s\n", from, to);
+static void
+emit_icu_link(FILE* f, const char* from, const char* to) {
+ /* machine-readable section */
+ fprintf(f, "link %s %s\n", from, to);
}
static const char* DYCODE[] = {"DOM", "DOWGEQ", "DOWLEQ"};
-void emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex) {
- if (r->r_yrtype != NULL) {
- warning("year types not supported by ICU");
- fprintf(stderr, "rule %s, file %s, line %d\n",
- r->r_name, r->r_filename, r->r_linenum);
+static void
+emit_icu_rule(FILE* f, const struct rule* r, int ruleIndex) {
+ if (r->r_yrtype != NULL) {
+ warning("year types not supported by ICU");
+ fprintf(stderr, "rule %s, file %s, line %d\n",
+ r->r_name, r->r_filename, r->r_linenum);
}
- /* machine-readable section */
- fprintf(f, "rule %s %s %d %d %d %d %d %d %d",
- r->r_name, DYCODE[r->r_dycode],
- r->r_month, r->r_dayofmonth,
- (r->r_dycode == DC_DOM ? -1 : r->r_wday),
- r->r_tod, r->r_todisstd, r->r_todisgmt, r->r_stdoff
- );
-
- /* human-readable section */
- fprintf(f, " # %d: %s, file %s, line %d",
- ruleIndex, r->r_name, r->r_filename, r->r_linenum);
- fprintf(f, ", mode %s", DYCODE[r->r_dycode]);
- fprintf(f, ", %s, dom %d", mon_names[r->r_month].l_word, r->r_dayofmonth);
- if (r->r_dycode != DC_DOM) {
- fprintf(f, ", %s", wday_names[r->r_wday].l_word);
- }
- fprintf(f, ", time %d", r->r_tod);
- fprintf(f, ", isstd %d", r->r_todisstd);
- fprintf(f, ", isgmt %d", r->r_todisgmt);
- fprintf(f, ", offset %ld", r->r_stdoff);
- fprintf(f, "\n");
+ /* machine-readable section */
+ fprintf(f, "rule %s %s %d %d %d %ld %d %d %ld",
+ r->r_name, DYCODE[r->r_dycode],
+ r->r_month, r->r_dayofmonth,
+ (r->r_dycode == DC_DOM ? -1 : r->r_wday),
+ r->r_tod, r->r_todisstd, r->r_todisgmt, r->r_stdoff
+ );
+
+ /* human-readable section */
+ fprintf(f, " # %d: %s, file %s, line %d",
+ ruleIndex, r->r_name, r->r_filename, r->r_linenum);
+ fprintf(f, ", mode %s", DYCODE[r->r_dycode]);
+ fprintf(f, ", %s, dom %d", mon_names[r->r_month].l_word, r->r_dayofmonth);
+ if (r->r_dycode != DC_DOM) {
+ fprintf(f, ", %s", wday_names[r->r_wday].l_word);
+ }
+ fprintf(f, ", time %ld", r->r_tod);
+ fprintf(f, ", isstd %d", r->r_todisstd);
+ fprintf(f, ", isgmt %d", r->r_todisgmt);
+ fprintf(f, ", offset %ld", r->r_stdoff);
+ fprintf(f, "\n");
}
+static int
+add_icu_final_rules(const struct rule* r1, const struct rule* r2) {
+ int i;
+
+ for (i=0; i<finalRulesCount; ++i) { /* i+=2 should work too */
+ if (r1==finalRules[i]) return i; /* [sic] pointer comparison */
+ }
+
+ finalRules = (const struct rule**) (void*) erealloc((char *) finalRules,
+ (finalRulesCount + 2) * sizeof(*finalRules));
+ finalRules[finalRulesCount++] = r1;
+ finalRules[finalRulesCount++] = r2;
+ return finalRulesCount - 2;
+}
#endif
static const char * psxrules;
if (strcmp(argv[i], "--version") == 0) {
(void) printf("%s\n", elsieid);
exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "--help") == 0) {
+ usage(stdout, EXIT_SUCCESS);
}
while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
switch (c) {
default:
- usage();
+ usage(stderr, EXIT_FAILURE);
case 'd':
if (directory == NULL)
directory = optarg;
break;
}
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
- usage(); /* usage message by request */
+ usage(stderr, EXIT_FAILURE); /* usage message by request */
if (directory == NULL)
directory = TZDIR;
if (yitcommand == NULL)
#ifdef ICU
if ((icuFile = fopen(ICU_ZONE_FILE, "w")) == NULL) {
- const char *e = strerror(errno);
- (void) fprintf(stderr, _("%s: Can't open %s: %s\n"),
- progname, ICU_ZONE_FILE, e);
- (void) exit(EXIT_FAILURE);
- }
+ const char *e = strerror(errno);
+ (void) fprintf(stderr, _("%s: Can't open %s: %s\n"),
+ progname, ICU_ZONE_FILE, e);
+ (void) exit(EXIT_FAILURE);
+ }
#endif
for (i = optind; i < argc; ++i)
infile(argv[i]);
eat(links[i].l_filename, links[i].l_linenum);
dolink(links[i].l_from, links[i].l_to);
#ifdef ICU
- emit_icu_link(icuFile, links[i].l_from, links[i].l_to);
+ emit_icu_link(icuFile, links[i].l_from, links[i].l_to);
#endif
if (noise)
for (j = 0; j < nlinks; ++j)
dolink(psxrules, TZDEFRULES);
}
#ifdef ICU
- for (i=0; i<finalRulesCount; ++i) {
- emit_icu_rule(icuFile, finalRules[i], i);
- }
+ for (i=0; i<finalRulesCount; ++i) {
+ emit_icu_rule(icuFile, finalRules[i], i);
+ }
#endif /*ICU*/
return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
static void
-dolink(fromfile, tofile)
-const char * const fromfile;
-const char * const tofile;
+dolink(fromfield, tofield)
+const char * const fromfield;
+const char * const tofield;
{
register char * fromname;
register char * toname;
- if (fromfile[0] == '/')
- fromname = ecpyalloc(fromfile);
+ if (fromfield[0] == '/')
+ fromname = ecpyalloc(fromfield);
else {
fromname = ecpyalloc(directory);
fromname = ecatalloc(fromname, "/");
- fromname = ecatalloc(fromname, fromfile);
+ fromname = ecatalloc(fromname, fromfield);
}
- if (tofile[0] == '/')
- toname = ecpyalloc(tofile);
+ if (tofield[0] == '/')
+ toname = ecpyalloc(tofield);
else {
toname = ecpyalloc(directory);
toname = ecatalloc(toname, "/");
- toname = ecatalloc(toname, tofile);
+ toname = ecatalloc(toname, tofield);
}
/*
** We get to be careful here since
if (result != 0 &&
access(fromname, F_OK) == 0 &&
!itsdir(fromname)) {
- const char *s = tofile;
+ const char *s = tofield;
register char * symlinkcontents = NULL;
while ((s = strchr(s+1, '/')) != NULL)
"../");
symlinkcontents =
ecatalloc(symlinkcontents,
- fromfile);
+ fromname);
result = symlink(symlinkcontents,
toname);
if (result == 0)
#define TIME_T_BITS_IN_FILE 64
static void
-setboundaries P((void))
+setboundaries(void)
{
register int i;
}
static void
-associate P((void))
+associate(void)
{
register struct zone * zp;
register struct rule * rp;
const char * const errstring;
const int signable;
{
- int hh, mm, ss, sign;
+ long hh;
+ int mm, ss, sign;
if (string == NULL || *string == '\0')
return 0;
sign = -1;
++string;
} else sign = 1;
- if (sscanf(string, scheck(string, "%d"), &hh) == 1)
+ if (sscanf(string, scheck(string, "%ld"), &hh) == 1)
mm = ss = 0;
- else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)
+ else if (sscanf(string, scheck(string, "%ld:%d"), &hh, &mm) == 2)
ss = 0;
- else if (sscanf(string, scheck(string, "%d:%d:%d"),
+ else if (sscanf(string, scheck(string, "%ld:%d:%d"),
&hh, &mm, &ss) != 3) {
error(errstring);
return 0;
}
- if ((hh < 0 || hh >= HOURSPERDAY ||
+ if (hh < 0 ||
mm < 0 || mm >= MINSPERHOUR ||
- ss < 0 || ss > SECSPERMIN) &&
- !(hh == HOURSPERDAY && mm == 0 && ss == 0)) {
+ ss < 0 || ss > SECSPERMIN) {
error(errstring);
return 0;
}
- if (noise && hh == HOURSPERDAY)
+ if (LONG_MAX / SECSPERHOUR < hh) {
+ error(_("time overflow"));
+ return 0;
+ }
+ if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0)
warning(_("24:00 not handled by pre-1998 versions of zic"));
- return eitol(sign) *
- (eitol(hh * MINSPERHOUR + mm) *
- eitol(SECSPERMIN) + eitol(ss));
+ if (noise && (hh > HOURSPERDAY ||
+ (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
+warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
+ return oadd(eitol(sign) * hh * eitol(SECSPERHOUR),
+ eitol(sign) * (eitol(mm) * eitol(SECSPERMIN) + eitol(ss)));
}
static void
(size_t) sizeof tzh.field, (size_t) 1, fp)
tzh = tzh0;
#ifdef ICU
- * (ICUZoneinfoVersion*) &tzh.tzh_reserved = TZ_ICU_VERSION;
- (void) strncpy(tzh.tzh_magic, TZ_ICU_MAGIC, sizeof tzh.tzh_magic);
+ * (ICUZoneinfoVersion*) &tzh.tzh_reserved = TZ_ICU_VERSION;
+ (void) strncpy(tzh.tzh_magic, TZ_ICU_MAGIC, sizeof tzh.tzh_magic);
#else
(void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
#endif
for (i = 0; i < typecnt; ++i)
if (writetype[i]) {
#ifdef ICU
- puttzcode((long) rawoffs[i], fp);
- puttzcode((long) dstoffs[i], fp);
+ puttzcode((long) rawoffs[i], fp);
+ puttzcode((long) dstoffs[i], fp);
#else
- puttzcode((long) gmtoffs[i], fp);
+ puttzcode(gmtoffs[i], fp);
#endif
(void) putc(isdsts[i], fp);
(void) putc((unsigned char) indmap[abbrinds[i]], fp);
}
}
-#ifdef ICU
-
-int add_icu_final_rules(const struct rule* r1, const struct rule* r2) {
- int i;
-
- for (i=0; i<finalRulesCount; ++i) { /* i+=2 should work too */
- if (r1==finalRules[i]) return i; /* [sic] pointer comparison */
- }
-
- finalRules = (const struct rule**) (void*) erealloc((char *) finalRules,
- (finalRulesCount + 2) * sizeof(*finalRules));
- finalRules[finalRulesCount++] = r1;
- finalRules[finalRulesCount++] = r2;
- return finalRulesCount - 2;
-}
-
-#endif /*ICU*/
-
static void
outzone(zpfirst, zonecount)
const struct zone * const zpfirst;
register int max_abbr_len;
register int max_envvar_len;
#ifdef ICU
- int finalRuleYear, finalRuleIndex;
- const struct rule* finalRule1;
- const struct rule* finalRule2;
+ int finalRuleYear, finalRuleIndex;
+ const struct rule* finalRule1;
+ const struct rule* finalRule2;
#endif
max_abbr_len = 2 + max_format_len + max_abbrvar_len;
}
for (i = 0; i < zonecount; ++i) {
zp = &zpfirst[i];
- updateminmax(zp->z_untilrule.r_loyear);
+ if (i < zonecount - 1)
+ updateminmax(zp->z_untilrule.r_loyear);
for (j = 0; j < zp->z_nrules; ++j) {
rp = &zp->z_rules[j];
if (rp->r_lowasnum)
wp = ecpyalloc(_("no POSIX environment variable for zone"));
wp = ecatalloc(wp, " ");
- wp = ecatalloc(wp, zpfirst->z_name);
+ wp = ecatalloc(wp, zpfirst->z_name);
warning(wp);
ifree(wp);
}
else max_year = INT_MAX;
}
/*
- ** For the benefit of older systems, generate data through 2037.
+ ** For the benefit of older systems,
+ ** generate data from 1900 through 2037.
*/
+ if (min_year > 1900)
+ min_year = 1900;
if (max_year < 2037)
max_year = 2037;
for (i = 0; i < zonecount; ++i) {
*startbuf = '\0';
startoff = zp->z_gmtoff;
#ifdef ICU
- finalRuleYear = finalRuleIndex = -1;
- finalRule1 = finalRule2 = NULL;
- if (i == (zonecount - 1)) { /* !useuntil */
- /* Look for exactly 2 rules that end at 'max' and
- * note them. Determine max(r_loyear) for the 2 of
- * them. */
- for (j=0; j<zp->z_nrules; ++j) {
- rp = &zp->z_rules[j];
- if (rp->r_hiyear == INT_MAX) {
- if (finalRule1 == NULL) {
- finalRule1 = rp;
- finalRuleYear = rp->r_loyear;
- } else if (finalRule2 == NULL) {
- finalRule2 = rp;
- if (rp->r_loyear > finalRuleYear) {
- finalRuleYear = rp->r_loyear;
- }
- } else {
- error("more than two max rules found (ICU)");
- exit(EXIT_FAILURE);
- }
- }
- }
- if (finalRule1 != NULL && finalRule2 == NULL) {
- error("only one max rule found (ICU)");
- exit(EXIT_FAILURE);
- }
- if (finalRule1 != NULL) {
- /* Swap if necessary so finalRule1 occurs before
- * finalRule2 */
- if (finalRule1->r_month > finalRule2->r_month) {
- const struct rule* t = finalRule1;
- finalRule1 = finalRule2;
- finalRule2 = t;
- }
- /* Add final rule to our list */
- finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2);
- }
- }
+ finalRuleYear = finalRuleIndex = -1;
+ finalRule1 = finalRule2 = NULL;
+ if (i == (zonecount - 1)) { /* !useuntil */
+ /* Look for exactly 2 rules that end at 'max' and
+ * note them. Determine max(r_loyear) for the 2 of
+ * them. */
+ for (j=0; j<zp->z_nrules; ++j) {
+ rp = &zp->z_rules[j];
+ if (rp->r_hiyear == INT_MAX) {
+ if (finalRule1 == NULL) {
+ finalRule1 = rp;
+ finalRuleYear = rp->r_loyear;
+ } else if (finalRule2 == NULL) {
+ finalRule2 = rp;
+ if (rp->r_loyear > finalRuleYear) {
+ finalRuleYear = rp->r_loyear;
+ }
+ } else {
+ error("more than two max rules found (ICU)");
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ if (finalRule1 != NULL && finalRule2 == NULL) {
+ error("only one max rule found (ICU)");
+ exit(EXIT_FAILURE);
+ }
+ if (finalRule1 != NULL) {
+ if (finalRule1->r_stdoff == finalRule2->r_stdoff) {
+ /* America/Resolute in 2009a uses a pair of rules
+ * which does not change the offset. ICU ignores
+ * such rules without actual time transitions. */
+ finalRuleYear = finalRuleIndex = -1;
+ finalRule1 = finalRule2 = NULL;
+ } else {
+ /* Swap if necessary so finalRule1 occurs before
+ * finalRule2 */
+ if (finalRule1->r_month > finalRule2->r_month) {
+ const struct rule* t = finalRule1;
+ finalRule1 = finalRule2;
+ finalRule2 = t;
+ }
+ /* Add final rule to our list */
+ finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2);
+ }
+ }
+ }
#endif
if (zp->z_nrules == 0) {
(char *) NULL, stdoff != 0, FALSE);
type = addtype(oadd(zp->z_gmtoff, stdoff),
#ifdef ICU
- zp->z_gmtoff, stdoff,
+ zp->z_gmtoff, stdoff,
#endif
startbuf, stdoff != 0, startttisstd,
startttisgmt);
}
}
#ifdef ICU
- if (year >= finalRuleYear && rp == finalRule1) {
- /* We want to shift final year 1 year after
- * the actual final rule takes effect (year + 1),
- * because the previous type is valid until the first
- * transition defined by the final rule. Otherwise
- * we may see unexpected offset shift at the
- * begining of the year when the final rule takes
- * effect. */
-
- /* ICU currently can support signed int32 transition
- * times. Thus, the transitions in year 2038 may be
- * truncated. At this moment (tzdata2008g), only
- * Rule Brazil is impacted by this limitation, because
- * the final set of rules are starting in 2038. Although
- * this code put the first couple of transitions populated
- * by the final rules, they will be dropped off when
- * collecting transition times. So, we need to keep
- * the start year of the final rule in 2038, not 2039.
- * Fortunately, the Brazil rules in 2038 and beyond use
- * the same base offset/dst saving amount. Thus, even
- * we skip the first couple of transitions, the final
- * rule set for 2038 works properly. So for now,
- * we do not increment the final rule start year only when
- * it falls into year 2038. We need to revisit this code
- * in future to fix the root cause of this problem (ICU
- * resource type limitation - signed int32).
- * Oct 7, 2008 - Yoshito */
- int finalStartYear = (year == 2038) ? year : year + 1;
- emit_icu_zone(icuFile,
- zpfirst->z_name, zp->z_gmtoff,
- rp, finalRuleIndex, finalStartYear);
- /* only emit this for the first year */
- finalRule1 = NULL;
- }
+ if (year >= finalRuleYear && rp == finalRule1) {
+ /* We want to shift final year 1 year after
+ * the actual final rule takes effect (year + 1),
+ * because the previous type is valid until the first
+ * transition defined by the final rule. Otherwise
+ * we may see unexpected offset shift at the
+ * begining of the year when the final rule takes
+ * effect. */
+
+ /* ICU currently can support signed int32 transition
+ * times. Thus, the transitions in year 2038 may be
+ * truncated. At this moment (tzdata2008g), only
+ * Rule Brazil is impacted by this limitation, because
+ * the final set of rules are starting in 2038. Although
+ * this code put the first couple of transitions populated
+ * by the final rules, they will be dropped off when
+ * collecting transition times. So, we need to keep
+ * the start year of the final rule in 2038, not 2039.
+ * Fortunately, the Brazil rules in 2038 and beyond use
+ * the same base offset/dst saving amount. Thus, even
+ * we skip the first couple of transitions, the final
+ * rule set for 2038 works properly. So for now,
+ * we do not increment the final rule start year only when
+ * it falls into year 2038. We need to revisit this code
+ * in future to fix the root cause of this problem (ICU
+ * resource type limitation - signed int32).
+ * Oct 7, 2008 - Yoshito */
+ int finalStartYear = (year == 2038) ? year : year + 1;
+ emit_icu_zone(icuFile,
+ zpfirst->z_name, zp->z_gmtoff,
+ rp, finalRuleIndex, finalStartYear);
+ /* only emit this for the first year */
+ finalRule1 = NULL;
+ }
#endif
eats(zp->z_filename, zp->z_linenum,
rp->r_filename, rp->r_linenum);
offset = oadd(zp->z_gmtoff, rp->r_stdoff);
#ifdef ICU
type = addtype(offset, zp->z_gmtoff, rp->r_stdoff,
- ab, rp->r_stdoff != 0,
+ ab, rp->r_stdoff != 0,
rp->r_todisstd, rp->r_todisgmt);
#else
type = addtype(offset, ab, rp->r_stdoff != 0,
else addtt(starttime,
#ifdef ICU
addtype(startoff,
- zp->z_gmtoff, startoff - zp->z_gmtoff,
- startbuf,
+ zp->z_gmtoff, startoff - zp->z_gmtoff,
+ startbuf,
startoff != zp->z_gmtoff,
startttisstd,
startttisgmt));
error(_("internal error - addtype called with bad isdst/dstoff"));
(void) exit(EXIT_FAILURE);
}
- if (gmtoff != (rawoff + dstoff)) {
+ if (gmtoff != (rawoff + dstoff)) {
error(_("internal error - addtype called with bad gmt/raw/dstoff"));
(void) exit(EXIT_FAILURE);
- }
+ }
#endif
/*
** See if there's already an entry for this zone type.
for (i = 0; i < typecnt; ++i) {
if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
#ifdef ICU
- rawoff == rawoffs[i] && dstoff == dstoffs[i] &&
+ rawoff == rawoffs[i] && dstoff == dstoffs[i] &&
#endif
strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
ttisstd == ttisstds[i] &&
error(_("too many local time types"));
exit(EXIT_FAILURE);
}
+ if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) {
+ error(_("UTC offset out of range"));
+ exit(EXIT_FAILURE);
+ }
gmtoffs[i] = gmtoff;
#ifdef ICU
- rawoffs[i] = rawoff;
- dstoffs[i] = dstoff;
+ rawoffs[i] = rawoff;
+ dstoffs[i] = dstoff;
#endif
isdsts[i] = isdst;
ttisstds[i] = ttisstd;
}
static void
-adjleap P((void))
+adjleap(void)
{
register int i;
register long last = 0;
else while ((*dp = *cp++) != '"')
if (*dp != '\0')
++dp;
- else error(_(
+ else {
+ error(_(
"Odd number of quotation marks"
));
+ exit(1);
+ }
} while (*cp != '\0' && *cp != '#' &&
(!isascii(*cp) || !isspace((unsigned char) *cp)));
if (isascii(*cp) && isspace((unsigned char) *cp))
static int
mkdirs(argname)
-char * const argname;
+char * argname;
{
register char * name;
register char * cp;