diff --git a/src/BCDConverter.cc b/src/BCDConverter.cc index 99c4ef5..adaead3 100644 --- a/src/BCDConverter.cc +++ b/src/BCDConverter.cc @@ -27,7 +27,7 @@ class BCDConverter : public StreamFormatConverter { int parse (const StreamFormat&, StreamBuffer&, const char*&, bool); bool printLong(const StreamFormat&, StreamBuffer&, long); - int scanLong(const StreamFormat&, const char*, long&); + long scanLong(const StreamFormat&, const char*, long&); }; int BCDConverter:: @@ -39,64 +39,65 @@ parse(const StreamFormat& fmt, StreamBuffer&, const char*&, bool) bool BCDConverter:: printLong(const StreamFormat& fmt, StreamBuffer& output, long value) { - unsigned char bcd[6]={0,0,0,0,0,0}; // sufficient for 2^32 - int i; - int prec = fmt.prec; // number of nibbles - if (prec == -1) - { - prec = 2 * sizeof (value); - } - int width = (prec + (fmt.flags & sign_flag ? 2 : 1)) / 2; + unsigned char bcd; + bool neg = false; + long i; + unsigned long prec = fmt.prec < 0 ? 2 * sizeof(value) : fmt.prec; // number of nibbles + unsigned long width = (prec + (fmt.flags & sign_flag ? 2 : 1)) / 2; if (fmt.width > width) width = fmt.width; - if (fmt.flags & sign_flag && value < 0) + if (fmt.flags & sign_flag && value < 0 && prec > 0) { - // negative BCD value, I hope "F" as "-" is OK - bcd[5] = 0xF0; + neg = true; value = -value; } - if (prec > 10) prec = 10; - for (i = 0; i < prec; i++) - { - bcd[i/2] |= (value % 10) << (4 * (i & 1)); - value /= 10; - } if (fmt.flags & alt_flag) { // least significant byte first (little endian) - for (i = 0; i < (prec + 1) / 2; i++) + while (width-- && prec) { - output.append(bcd[i]); + bcd = value%10; + if (--prec) + { + --prec; + value /= 10; + bcd |= (value%10)<<4; + value /= 10; + } + output.append(bcd); } - for (; i < width; i++) - { - output.append('\0'); - } - output[-1] |= bcd[5]; + if (width) + output.append('\0', width); + if (neg) output[-1] |= 0xf0; } else { // most significant byte first (big endian) - int firstbyte = output.length(); - for (i = 0; i < width - (prec + 1) / 2; i++) + output.append('\0', width); + if (neg) output[-width] |= 0xf0; + i = 0; + while (width-- && prec) { - output.append('\0'); + bcd = value%10; + if (--prec) + { + --prec; + value /= 10; + bcd |= (value%10)<<4; + value /= 10; + } + output[--i]=bcd; } - for (i = (prec - 1) / 2; i >= 0; i--) - { - output.append(bcd[i]); - } - output[firstbyte] |= bcd[5]; } return true; } -int BCDConverter:: +long BCDConverter:: scanLong(const StreamFormat& fmt, const char* input, long& value) { - int length = 0; - int val = 0; + long length = 0; + long val = 0; unsigned char bcd1, bcd10; - int width = fmt.width; + long width = fmt.width; if (width == 0) width = 1; if (fmt.flags & alt_flag) { diff --git a/src/BinaryConverter.cc b/src/BinaryConverter.cc index 188ee6f..5d1907c 100644 --- a/src/BinaryConverter.cc +++ b/src/BinaryConverter.cc @@ -29,7 +29,7 @@ class BinaryConverter : public StreamFormatConverter { int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); bool printLong(const StreamFormat&, StreamBuffer&, long); - int scanLong(const StreamFormat&, const char*, long&); + long scanLong(const StreamFormat&, const char*, long&); }; int BinaryConverter:: @@ -77,7 +77,7 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value) if (x <= 0x3FFFFFFF) { prec -= 2; x <<=2; } if (x <= 0x7FFFFFFF) { prec -= 1; } } - int width = prec; + unsigned long width = prec; if (fmt.width > width) width = fmt.width; char zero = fmt.info[0]; char one = fmt.info[1]; @@ -88,7 +88,7 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value) if (!(fmt.flags & left_flag)) { // pad left - while (width > prec) + while (width > (unsigned int)prec) { output.append(' '); width--; @@ -112,7 +112,7 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value) if (!(fmt.flags & left_flag)) { // pad left - while (width > prec) + while (width > (unsigned int)prec) { output.append(fill); width--; @@ -132,13 +132,13 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value) return true; } -int BinaryConverter:: +long BinaryConverter:: scanLong(const StreamFormat& fmt, const char* input, long& value) { long val = 0; - int width = fmt.width; + long width = fmt.width; if (width == 0) width = -1; - int length = 0; + long length = 0; char zero = fmt.info[0]; char one = fmt.info[1]; if (!isspace(zero) && !isspace(one)) diff --git a/src/ChecksumConverter.cc b/src/ChecksumConverter.cc index efb73d1..6550152 100644 --- a/src/ChecksumConverter.cc +++ b/src/ChecksumConverter.cc @@ -500,7 +500,7 @@ class ChecksumConverter : public StreamFormatConverter { int parse (const StreamFormat&, StreamBuffer&, const char*&, bool); bool printPseudo(const StreamFormat&, StreamBuffer&); - int scanPseudo(const StreamFormat&, StreamBuffer&, long& cursor); + long scanPseudo(const StreamFormat&, StreamBuffer&, long& cursor); }; int ChecksumConverter:: @@ -535,7 +535,7 @@ parse(const StreamFormat&, StreamBuffer& info, const char*& source, bool) source+=3; notflag = true; } - unsigned fnum; + unsigned char fnum; int len = p-source; unsigned int init, xorout; for (fnum = 0; fnum < sizeof(checksumMap)/sizeof(checksum); fnum++) @@ -573,7 +573,7 @@ printPseudo(const StreamFormat& format, StreamBuffer& output) const char* info = format.info; unsigned int init = extract(info); unsigned int xorout = extract(info); - int fnum = extract(info); + unsigned char fnum = extract(info); int start = format.width; int length = output.length()-format.width; @@ -641,7 +641,7 @@ printPseudo(const StreamFormat& format, StreamBuffer& output) return true; } -int ChecksumConverter:: +long ChecksumConverter:: scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor) { unsigned int sum; @@ -649,8 +649,8 @@ scanPseudo(const StreamFormat& format, StreamBuffer& input, long& cursor) unsigned int init = extract(info); unsigned int xorout = extract(info); int start = format.width; - int fnum = extract(info); - int length = cursor-format.width; + unsigned char fnum = extract(info); + long length = cursor-format.width; if (format.prec > 0) length -= format.prec; diff --git a/src/EnumConverter.cc b/src/EnumConverter.cc index 8954d34..913bfed 100644 --- a/src/EnumConverter.cc +++ b/src/EnumConverter.cc @@ -29,7 +29,7 @@ class EnumConverter : public StreamFormatConverter { int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); bool printLong(const StreamFormat&, StreamBuffer&, long); - int scanLong(const StreamFormat&, const char*, long&); + long scanLong(const StreamFormat&, const char*, long&); }; // info format: 00... @@ -148,7 +148,7 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value) return true; } -int EnumConverter:: +long EnumConverter:: scanLong(const StreamFormat& fmt, const char* input, long& value) { debug("EnumConverter::scanLong(%%%c, \"%s\")\n", @@ -156,7 +156,7 @@ scanLong(const StreamFormat& fmt, const char* input, long& value) const char* s = fmt.info; long numEnums = extract(s); long index; - int length; + long length; bool match; while (numEnums--) diff --git a/src/MantissaExponentConverter.cc b/src/MantissaExponentConverter.cc index 8b13442..fb8965a 100644 --- a/src/MantissaExponentConverter.cc +++ b/src/MantissaExponentConverter.cc @@ -39,7 +39,7 @@ class MantissaExponentConverter : public StreamFormatConverter { virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); - virtual int scanDouble(const StreamFormat&, const char*, double&); + virtual long scanDouble(const StreamFormat&, const char*, double&); virtual bool printDouble(const StreamFormat&, StreamBuffer&, double); }; @@ -50,7 +50,7 @@ parse(const StreamFormat&, StreamBuffer&, return double_format; } -int MantissaExponentConverter:: +long MantissaExponentConverter:: scanDouble(const StreamFormat& fmt, const char* input, double& value) { int mantissa; diff --git a/src/RawConverter.cc b/src/RawConverter.cc index f89abcb..2da07fd 100644 --- a/src/RawConverter.cc +++ b/src/RawConverter.cc @@ -27,7 +27,7 @@ class RawConverter : public StreamFormatConverter { int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); bool printLong(const StreamFormat&, StreamBuffer&, long); - int scanLong(const StreamFormat&, const char*, long&); + long scanLong(const StreamFormat&, const char*, long&); }; int RawConverter:: @@ -40,10 +40,9 @@ parse(const StreamFormat& fmt, StreamBuffer&, bool RawConverter:: printLong(const StreamFormat& fmt, StreamBuffer& output, long value) { - int prec = fmt.prec; // number of bytes from value - if (prec == -1) prec = 1; // default: 1 byte - int width = prec; // number of bytes in output - if (prec > (int)sizeof(long)) prec=sizeof(long); + unsigned int prec = fmt.prec < 0 ? 1 : fmt.prec; // number of bytes from value, default 1 + unsigned long width = prec; // number of bytes in output + if (prec > sizeof(long)) prec=sizeof(long); if (fmt.width > width) width = fmt.width; char byte = 0; @@ -96,12 +95,12 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value) return true; } -int RawConverter:: +long RawConverter:: scanLong(const StreamFormat& fmt, const char* input, long& value) { long length = 0; long val = 0; - int width = fmt.width; + unsigned long width = fmt.width; if (width == 0) width = 1; // default: 1 byte if (fmt.flags & skip_flag) { diff --git a/src/RawFloatConverter.cc b/src/RawFloatConverter.cc index 0366a88..47eb4dd 100644 --- a/src/RawFloatConverter.cc +++ b/src/RawFloatConverter.cc @@ -29,7 +29,7 @@ class RawFloatConverter : public StreamFormatConverter { int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); bool printDouble(const StreamFormat&, StreamBuffer&, double); - int scanDouble(const StreamFormat&, const char*, double&); + long scanDouble(const StreamFormat&, const char*, double&); }; int RawFloatConverter:: @@ -90,7 +90,7 @@ printDouble(const StreamFormat& format, StreamBuffer& output, double value) return true; } -int RawFloatConverter:: +long RawFloatConverter:: scanDouble(const StreamFormat& format, const char* input, double& value) { int nbOfBytes; diff --git a/src/RegexpConverter.cc b/src/RegexpConverter.cc index 693ffd3..5f76aae 100644 --- a/src/RegexpConverter.cc +++ b/src/RegexpConverter.cc @@ -38,8 +38,8 @@ class RegexpConverter : public StreamFormatConverter { int parse (const StreamFormat& fmt, StreamBuffer&, const char*&, bool); - int scanString(const StreamFormat& fmt, const char*, char*, size_t); - int scanPseudo(const StreamFormat& fmt, StreamBuffer& input, long& cursor); + long scanString(const StreamFormat& fmt, const char*, char*, unsigned long&); + long scanPseudo(const StreamFormat& fmt, StreamBuffer& input, long& cursor); bool printPseudo(const StreamFormat& fmt, StreamBuffer& output); }; @@ -54,7 +54,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info, } if (fmt.prec > 9) { - error("Subexpression index %d too big (>9)\n", fmt.prec); + error("Subexpression index %ld too big (>9)\n", fmt.prec); return false; } @@ -115,14 +115,13 @@ parse(const StreamFormat& fmt, StreamBuffer& info, return string_format; } -int RegexpConverter:: +long RegexpConverter:: scanString(const StreamFormat& fmt, const char* input, - char* value, size_t maxlen) + char* value, unsigned long& size) { int ovector[30]; int rc; unsigned int l; - const char* info = fmt.info; pcre* code = extract(info); int length = fmt.width > 0 ? fmt.width : strlen(input); @@ -141,17 +140,18 @@ scanString(const StreamFormat& fmt, const char* input, if (fmt.flags & skip_flag) return ovector[subexpr*2+1]; l = ovector[subexpr*2+1] - ovector[subexpr*2]; - if (l >= maxlen) { + if (l >= size) { if (!(fmt.flags & sign_flag)) { error("Regexp: Matching string \"%s\" too long (%d>%ld bytes). You may want to try the + flag: \"%%+/.../\"\n", StreamBuffer(input + ovector[subexpr*2],l).expand()(), - l, (long)maxlen-1); + l, (long)size-1); return -1; } - l = maxlen-1; + l = size-1; } memcpy(value, input + ovector[subexpr*2], l); value[l] = '\0'; + size = l+1; // update number of bytes written to value return ovector[1]; // consume input until end of match } @@ -159,8 +159,8 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start) { const char* subst = fmt.info; pcre* code = extract(subst); - long length; - int rc, l, c, r, rl, n; + unsigned long length, c; + int rc, l, r, rl, n; int ovector[30]; StreamBuffer s; @@ -176,7 +176,7 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start) for (c = 0, n = 1; c < length; n++) { rc = pcre_exec(code, NULL, buffer(start+c), length-c, 0, 0, ovector, 30); - debug("pcre_exec match \"%.*s\" result = %d\n", (int)length-c, buffer(start+c), rc); + debug("pcre_exec match \"%.*s\" result = %d\n", (int)(length-c), buffer(start+c), rc); if (rc < 0) // no match return; @@ -229,7 +229,7 @@ static void regsubst(const StreamFormat& fmt, StreamBuffer& buffer, long start) } } -int RegexpConverter:: +long RegexpConverter:: scanPseudo(const StreamFormat& fmt, StreamBuffer& input, long& cursor) { /* re-write input buffer */ diff --git a/src/StreamCore.cc b/src/StreamCore.cc index 2eb269f..ed0a31e 100644 --- a/src/StreamCore.cc +++ b/src/StreamCore.cc @@ -1215,6 +1215,7 @@ normal_format: { long ldummy; double ddummy; + long unsigned size=0; switch (fmt.type) { case unsigned_format: @@ -1229,7 +1230,7 @@ normal_format: break; case string_format: consumed = StreamFormatConverter::find(fmt.conv)-> - scanString(fmt, inputLine(consumedInput), NULL, 0); + scanString(fmt, inputLine(consumedInput), NULL, size); break; case pseudo_format: // pass complete input @@ -1482,7 +1483,7 @@ scanValue(const StreamFormat& fmt, long& value) } else return -1; } - if (fmt.flags & fix_width_flag && consumed != fmt.width) return -1; + if (fmt.flags & fix_width_flag && (unsigned long)consumed != fmt.width) return -1; if (consumed > inputLine.length()-consumedInput) return -1; debug("StreamCore::scanValue(%s) scanned %li\n", name(), value); @@ -1514,7 +1515,7 @@ scanValue(const StreamFormat& fmt, double& value) } else return -1; } - if (fmt.flags & fix_width_flag && (consumed != (fmt.width + fmt.prec + 1))) return -1; + if (fmt.flags & fix_width_flag && ((unsigned long)consumed != (fmt.width + fmt.prec + 1))) return -1; if (consumed > inputLine.length()-consumedInput) return -1; debug("StreamCore::scanValue(%s) scanned %#g\n", name(), value); @@ -1523,7 +1524,7 @@ scanValue(const StreamFormat& fmt, double& value) } long StreamCore:: -scanValue(const StreamFormat& fmt, char* value, long maxlen) +scanValue(const StreamFormat& fmt, char* value, unsigned long& size) { if (fmt.type != string_format) { @@ -1531,13 +1532,12 @@ scanValue(const StreamFormat& fmt, char* value, long maxlen) name(), fmt.conv); return -1; } - if (maxlen < 0) maxlen = 0; flags |= ScanTried; if (!matchSeparator()) return -1; long consumed = StreamFormatConverter::find(fmt.conv)-> - scanString(fmt, inputLine(consumedInput), value, maxlen); - debug("StreamCore::scanValue(%s, format=%%%c, char*, maxlen=%ld) input=\"%s\"\n", - name(), fmt.conv, maxlen, inputLine.expand(consumedInput)()); + scanString(fmt, inputLine(consumedInput), value, size); + debug("StreamCore::scanValue(%s, format=%%%c, char*, size=%ld) input=\"%s\"\n", + name(), fmt.conv, size, inputLine.expand(consumedInput)()); if (consumed < 0) { if (fmt.flags & default_flag) @@ -1547,11 +1547,11 @@ scanValue(const StreamFormat& fmt, char* value, long maxlen) } else return -1; } - if (fmt.flags & fix_width_flag && consumed != fmt.width) return -1; + if (fmt.flags & fix_width_flag && (unsigned long)consumed != fmt.width) return -1; if (consumed > inputLine.length()-consumedInput) return -1; #ifndef NO_TEMPORARY debug("StreamCore::scanValue(%s) scanned \"%s\"\n", - name(), StreamBuffer(value, maxlen).expand()()); + name(), StreamBuffer(value, size).expand()()); #endif flags |= GotValue; return consumed; diff --git a/src/StreamCore.h b/src/StreamCore.h index 560af49..f668714 100644 --- a/src/StreamCore.h +++ b/src/StreamCore.h @@ -137,7 +137,7 @@ protected: bool printValue(const StreamFormat& format, char* value); long scanValue(const StreamFormat& format, long& value); long scanValue(const StreamFormat& format, double& value); - long scanValue(const StreamFormat& format, char* value, long maxlen); + long scanValue(const StreamFormat& format, char* value, unsigned long& size); long scanValue(const StreamFormat& format); StreamBuffer protocolname; diff --git a/src/StreamEpics.cc b/src/StreamEpics.cc index f2a315b..8b53a93 100644 --- a/src/StreamEpics.cc +++ b/src/StreamEpics.cc @@ -157,7 +157,7 @@ class Stream : protected StreamCore long initRecord(const char* filename, const char* protocol, const char* busname, int addr, const char* busparam); bool print(format_t *format, va_list ap); - bool scan(format_t *format, void* pvalue, size_t maxStringSize); + long scan(format_t *format, void* pvalue, size_t maxStringSize); bool process(); // device support functions @@ -554,19 +554,21 @@ long streamPrintf(dbCommon *record, format_t *format, ...) long streamScanfN(dbCommon* record, format_t *format, void* value, size_t maxStringSize) { + long size; debug("streamScanfN(%s,format=%%%c,maxStringSize=%ld)\n", record->name, format->priv->conv, (long)maxStringSize); Stream* pstream = (Stream*)record->dpvt; if (!pstream) return ERROR; - if (!pstream->scan(format, value, maxStringSize)) + size = pstream->scan(format, value, maxStringSize); + if (size == ERROR) { - return ERROR; + debug("streamScanfN(%s) failed\n", record->name); } #ifndef NO_TEMPORARY debug("streamScanfN(%s) success, value=\"%s\"\n", record->name, StreamBuffer((char*)value).expand()()); #endif - return OK; + return size; } // Stream methods //////////////////////////////////////////////////////// @@ -800,11 +802,12 @@ print(format_t *format, va_list ap) return false; } -bool Stream:: +long Stream:: scan(format_t *format, void* value, size_t maxStringSize) { // called by streamScanfN + unsigned long size = maxStringSize; // first remove old value from inputLine (if we are scanning arrays) consumedInput += currentValueLength; currentValueLength = 0; @@ -820,20 +823,17 @@ scan(format_t *format, void* value, size_t maxStringSize) break; case DBF_STRING: currentValueLength = scanValue(*format->priv, (char*)value, - maxStringSize); + size); break; default: error("INTERNAL ERROR (%s): Illegal format type\n", name()); - return false; - } - if (currentValueLength < 0) - { - currentValueLength = 0; - return false; + return ERROR; } // Don't remove scanned value from inputLine yet, because // we might need the string in a later error message. - return true; + if (currentValueLength == ERROR) return ERROR; + if (format->type == DBF_STRING) return size; + return OK; } // epicsTimerNotify virtual method /////////////////////////////////////// @@ -1163,6 +1163,7 @@ matchValue(const StreamFormat& format, const void* fieldaddress) int status; const char* putfunc; format_s fmt; + unsigned long stringsize = MAX_STRING_SIZE; fmt.type = dbfMapping[format.type]; fmt.priv = &format; @@ -1172,10 +1173,18 @@ matchValue(const StreamFormat& format, const void* fieldaddress) // to field of this or other record. StreamBuffer fieldBuffer; DBADDR* pdbaddr = (DBADDR*)fieldaddress; - long nord; - long nelem = pdbaddr->no_elements; - size_t size = nelem * dbValueSize(fmt.type); - buffer = fieldBuffer.clear().reserve(size); + size_t size; + unsigned long nord; + unsigned long nelem = pdbaddr->no_elements; + if (format.type == string_format && + (pdbaddr->field_type == DBF_CHAR || pdbaddr->field_type == DBF_UCHAR)) + { + // string to char array + size = nelem; + } + else + size = nelem * dbValueSize(fmt.type); + buffer = fieldBuffer.clear().reserve(size); // maybe write to field directly in case types match? for (nord = 0; nord < nelem; nord++) { debug("Stream::matchValue(%s): buffer before: %s\n", @@ -1232,24 +1241,27 @@ matchValue(const StreamFormat& format, const void* fieldaddress) } case string_format: { - if (pdbaddr->field_type == DBF_CHAR) + if (pdbaddr->field_type == DBF_CHAR || + pdbaddr->field_type == DBF_UCHAR) { // string to char array - consumed = scanValue(format, buffer, nelem); + stringsize = nelem; + consumed = scanValue(format, buffer, stringsize); debug("Stream::matchValue(%s): %s.%s = \"%.*s\"\n", name(), pdbaddr->precord->name, ((dbFldDes*)pdbaddr->pfldDes)->name, (int)consumed, buffer); - nord = nelem; + nord = nelem; // this shortcuts the loop } else { + stringsize = MAX_STRING_SIZE; consumed = scanValue(format, - buffer+MAX_STRING_SIZE*nord, MAX_STRING_SIZE); + buffer+MAX_STRING_SIZE*nord, stringsize); debug("Stream::matchValue(%s): %s.%s[%li] = \"%.*s\"\n", name(), pdbaddr->precord->name, ((dbFldDes*)pdbaddr->pfldDes)->name, - nord, MAX_STRING_SIZE, buffer+MAX_STRING_SIZE*nord); + nord, (int)stringsize, buffer+MAX_STRING_SIZE*nord); } break; } @@ -1290,7 +1302,7 @@ matchValue(const StreamFormat& format, const void* fieldaddress) /* convert from Unix epoch (1 Jan 1970) to EPICS epoch (1 Jan 1990) */ dval = dval-631152000u; pdbaddr->precord->time.secPastEpoch = (long)dval; - // rouding: we don't have 9 digits precision + // rounding: we don't have 9 digits precision // in a double of today's number of seconds pdbaddr->precord->time.nsec = (long)((dval-(long)dval)*1e6)*1000; debug("Stream::matchValue(%s): writing %i.%i to %s.TIME field\n", @@ -1307,10 +1319,11 @@ matchValue(const StreamFormat& format, const void* fieldaddress) #endif } if (format.type == string_format && - (pdbaddr->field_type == DBF_CHAR || pdbaddr->field_type == DBF_UCHAR)) + (pdbaddr->field_type == DBF_CHAR || + pdbaddr->field_type == DBF_UCHAR)) { /* write strings to [U]CHAR arrays */ - nord = consumed; + nord = stringsize; fmt.type = DBF_CHAR; } if (pdbaddr->precord == record || INIT_RUN) @@ -1349,25 +1362,26 @@ matchValue(const StreamFormat& format, const void* fieldaddress) case DBF_ULONG: case DBF_LONG: case DBF_ENUM: - error("%s: %s(%s.%s, %s, %li) failed\n", + error("%s: %s(%s.%s, %s, %li, %lu) failed\n", name(), putfunc, pdbaddr->precord->name, ((dbFldDes*)pdbaddr->pfldDes)->name, pamapdbfType[fmt.type].strvalue, - lval); + lval, nord); return false; case DBF_DOUBLE: - error("%s: %s(%s.%s, %s, %#g) failed\n", + error("%s: %s(%s.%s, %s, %#g, %lu) failed\n", name(), putfunc, pdbaddr->precord->name, ((dbFldDes*)pdbaddr->pfldDes)->name, pamapdbfType[fmt.type].strvalue, - dval); + dval, nord); return false; case DBF_STRING: - error("%s: %s(%s.%s, %s, \"%.*s\") failed\n", + case DBF_CHAR: + error("%s: %s(%s.%s, %s, \"%.*s\", %lu) failed\n", name(), putfunc, pdbaddr->precord->name, ((dbFldDes*)pdbaddr->pfldDes)->name, pamapdbfType[fmt.type].strvalue, - (int)consumed, buffer); + (int)consumed, buffer, nord); return false; default: return false; diff --git a/src/StreamFormat.h b/src/StreamFormat.h index 0f1ac5b..a0a87e8 100644 --- a/src/StreamFormat.h +++ b/src/StreamFormat.h @@ -50,9 +50,9 @@ typedef struct StreamFormat char conv; StreamFormatType type; unsigned short flags; - short prec; - unsigned short width; - unsigned short infolen; + long prec; + unsigned long width; + unsigned long infolen; const char* info; } StreamFormat; diff --git a/src/StreamFormatConverter.cc b/src/StreamFormatConverter.cc index 8465050..cda71c6 100644 --- a/src/StreamFormatConverter.cc +++ b/src/StreamFormatConverter.cc @@ -113,12 +113,12 @@ parseFormat(const char*& source, FormatType formatType, StreamFormat& streamForm char* p; val = strtoul (source, &p, 10); source = p; - if (val > 0xFFFF) + if (val > LONG_MAX) { error("Field width %ld out of range\n", val); return false; } - streamFormat.width = (unsigned short)val; + streamFormat.width = val; // look for prec streamFormat.prec = -1; if (*source == '.') @@ -132,7 +132,7 @@ parseFormat(const char*& source, FormatType formatType, StreamFormat& streamForm return false; } source = p; - if (val > 0x7FFF) + if (val > SHRT_MAX) { error("Precision %ld out of range\n", val); return false; @@ -205,7 +205,7 @@ printPseudo(const StreamFormat& fmt, StreamBuffer&) return false; } -int StreamFormatConverter:: +long StreamFormatConverter:: scanLong(const StreamFormat& fmt, const char*, long&) { error("Unimplemented scanLong method for %%%c format\n", @@ -213,7 +213,7 @@ scanLong(const StreamFormat& fmt, const char*, long&) return -1; } -int StreamFormatConverter:: +long StreamFormatConverter:: scanDouble(const StreamFormat& fmt, const char*, double&) { error("Unimplemented scanDouble method for %%%c format\n", @@ -221,15 +221,15 @@ scanDouble(const StreamFormat& fmt, const char*, double&) return -1; } -int StreamFormatConverter:: -scanString(const StreamFormat& fmt, const char*, char*, size_t) +long StreamFormatConverter:: +scanString(const StreamFormat& fmt, const char*, char*, unsigned long&) { error("Unimplemented scanString method for %%%c format\n", fmt.conv); return -1; } -int StreamFormatConverter:: +long StreamFormatConverter:: scanPseudo(const StreamFormat& fmt, StreamBuffer&, long&) { error("Unimplemented scanPseudo method for %%%c format\n", @@ -255,11 +255,11 @@ static void copyFormatString(StreamBuffer& info, const char* source) // Standard Long Converter for 'diouxX' -static int prepareval(const StreamFormat& fmt, const char*& input, bool& neg) +static long prepareval(const StreamFormat& fmt, const char*& input, bool& neg) { - int length = 0; + long consumed = 0; neg = false; - while (isspace(*input)) { input++; length++; } + while (isspace(*input)) { input++; consumed++; } if (fmt.width) { // take local copy because strto* don't have width parameter @@ -268,7 +268,7 @@ static int prepareval(const StreamFormat& fmt, const char*& input, bool& neg) { // normally whitespace does not count to width // but do so if space flag is present - width -= length; + width -= consumed; } strncpy((char*)fmt.info, input, width); ((char*)fmt.info)[width] = 0; @@ -283,21 +283,21 @@ static int prepareval(const StreamFormat& fmt, const char*& input, bool& neg) neg = true; skipsign: input++; - length++; + consumed++; } if (isspace(*input)) { // allow space after sign only if # flag is set if (!(fmt.flags & alt_flag)) return -1; } - return length; + return consumed; } class StdLongConverter : public StreamFormatConverter { int parse(const StreamFormat& fmt, StreamBuffer& output, const char*& value, bool scanFormat); bool printLong(const StreamFormat& fmt, StreamBuffer& output, long value); - int scanLong(const StreamFormat& fmt, const char* input, long& value); + long scanLong(const StreamFormat& fmt, const char* input, long& value); }; int StdLongConverter:: @@ -306,7 +306,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info, { if (scanFormat && fmt.prec >= 0) { - error("Use of precision field '.%d' not allowed with %%%c input conversion\n", + error("Use of precision field '.%ld' not allowed with %%%c input conversion\n", fmt.prec, fmt.conv); return false; } @@ -334,17 +334,17 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value) return true; } -int StdLongConverter:: +long StdLongConverter:: scanLong(const StreamFormat& fmt, const char* input, long& value) { char* end; - int length; + long consumed; bool neg; int base; long v; - length = prepareval(fmt, input, neg); - if (length < 0) return -1; + consumed = prepareval(fmt, input, neg); + if (consumed < 0) return -1; switch (fmt.conv) { case 'd': @@ -366,9 +366,9 @@ scanLong(const StreamFormat& fmt, const char* input, long& value) } v = strtoul(input, &end, base); if (end == input) return -1; - length += end-input; + consumed += end-input; value = neg ? -v : v; - return length; + return consumed; } RegisterConverter (StdLongConverter, "diouxX"); @@ -379,7 +379,7 @@ class StdDoubleConverter : public StreamFormatConverter { virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); virtual bool printDouble(const StreamFormat&, StreamBuffer&, double); - virtual int scanDouble(const StreamFormat&, const char*, double&); + virtual long scanDouble(const StreamFormat&, const char*, double&); }; int StdDoubleConverter:: @@ -388,7 +388,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info, { if (scanFormat && fmt.prec >= 0) { - error("Use of precision field '.%d' not allowed with %%%c input conversion\n", + error("Use of precision field '.%ld' not allowed with %%%c input conversion\n", fmt.prec, fmt.conv); return false; } @@ -411,20 +411,20 @@ printDouble(const StreamFormat& fmt, StreamBuffer& output, double value) return true; } -int StdDoubleConverter:: +long StdDoubleConverter:: scanDouble(const StreamFormat& fmt, const char* input, double& value) { char* end; - int length; + long consumed; bool neg; - length = prepareval(fmt, input, neg); - if (length < 0) return -1; + consumed = prepareval(fmt, input, neg); + if (consumed < 0) return -1; value = strtod(input, &end); if (neg) value = -value; if (end == input) return -1; - length += end-input; - return length; + consumed += end-input; + return consumed; } RegisterConverter (StdDoubleConverter, "feEgG"); @@ -435,7 +435,7 @@ class StdStringConverter : public StreamFormatConverter { virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); virtual bool printString(const StreamFormat&, StreamBuffer&, const char*); - virtual int scanString(const StreamFormat&, const char*, char*, size_t); + virtual long scanString(const StreamFormat&, const char*, char*, unsigned long&); }; int StdStringConverter:: @@ -451,7 +451,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info, } if (scanFormat && fmt.prec >= 0) { - error("Use of precision field '.%d' not allowed with %%%c input conversion\n", + error("Use of precision field '.%ld' not allowed with %%%c input conversion\n", fmt.prec, fmt.conv); return false; } @@ -483,17 +483,17 @@ printString(const StreamFormat& fmt, StreamBuffer& output, const char* value) return true; } -int StdStringConverter:: +long StdStringConverter:: scanString(const StreamFormat& fmt, const char* input, - char* value, size_t maxlen) + char* value, unsigned long &size) { - int length = 0; - + long consumed = 0; + long space_left = size; int width = fmt.width; - if ((fmt.flags & skip_flag) || value == NULL) maxlen = 0; + if ((fmt.flags & skip_flag) || value == NULL) space_left = 0; - // if user does not specify width assume "ininity" (-1) + // if user does not specify width assume "infinity" (-1) if (width == 0) { if (fmt.conv == 'c') width = 1; @@ -506,14 +506,14 @@ scanString(const StreamFormat& fmt, const char* input, // but do so if space flag is present if (fmt.flags & space_flag) { - if (maxlen > 1) + if (space_left > 1) // keep space for terminal null byte { *value++ = *input; - maxlen--; + space_left--; } width--; } - length++; + consumed++; input++; } while (*input && width) @@ -521,20 +521,22 @@ scanString(const StreamFormat& fmt, const char* input, // normally whitespace ends string // but don't end if # flag is present if (!(fmt.flags & alt_flag) && isspace(*input)) break; - if (maxlen > 1) + if (space_left > 1) { *value++ = *input; - maxlen--; + space_left--; } - length++; + consumed++; width--; input++; } - if (maxlen > 0) + if (space_left) { *value = '\0'; + space_left--; + size -= space_left; // update number of bytes copied to value } - return length; + return consumed; } RegisterConverter (StdStringConverter, "s"); @@ -545,7 +547,7 @@ class StdCharsConverter : public StreamFormatConverter { virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); virtual bool printLong(const StreamFormat&, StreamBuffer&, long); - virtual int scanString(const StreamFormat&, const char*, char*, size_t); + virtual long scanString(const StreamFormat&, const char*, char*, unsigned long&); }; int StdCharsConverter:: @@ -560,7 +562,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info, } if (scanFormat && fmt.prec >= 0) { - error("Use of precision field '.%d' not allowed with %%%c input conversion\n", + error("Use of precision field '.%ld' not allowed with %%%c input conversion\n", fmt.prec, fmt.conv); return false; } @@ -581,35 +583,37 @@ printLong(const StreamFormat& fmt, StreamBuffer& output, long value) return true; } -int StdCharsConverter:: +long StdCharsConverter:: scanString(const StreamFormat& fmt, const char* input, - char* value, size_t maxlen) + char* value, unsigned long& size) { - int length = 0; + long consumed = 0; + long width = fmt.width; + long space_left = size; - int width = fmt.width; - - if ((fmt.flags & skip_flag) || value == NULL) maxlen = 0; + if ((fmt.flags & skip_flag) || value == NULL) space_left = 0; // if user does not specify width assume 1 if (width == 0) width = 1; while (*input && width) { - if (maxlen > 1) + if (space_left > 1) // keep space for terminal null byte { *value++ = *input; - maxlen--; + space_left--; } - length++; + consumed++; width--; input++; } - if (maxlen > 0) + if (space_left) { *value = '\0'; + space_left--; + size -= space_left; // update number of bytes written to value } - return length; + return consumed; // return number of bytes consumed from input } RegisterConverter (StdCharsConverter, "c"); @@ -619,7 +623,7 @@ RegisterConverter (StdCharsConverter, "c"); class StdCharsetConverter : public StreamFormatConverter { virtual int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); - virtual int scanString(const StreamFormat&, const char*, char*, size_t); + virtual long scanString(const StreamFormat&, const char*, char*, unsigned long&); // no print method, %[ is readonly }; @@ -651,7 +655,7 @@ parse(const StreamFormat& fmt, StreamBuffer& info, } if (scanFormat && fmt.prec >= 0) { - error("Use of precision field '.%d' not allowed with %%%c input conversion\n", + error("Use of precision field '.%ld' not allowed with %%%c input conversion\n", fmt.prec, fmt.conv); return false; } @@ -698,35 +702,38 @@ parse(const StreamFormat& fmt, StreamBuffer& info, return string_format; } -int StdCharsetConverter:: +long StdCharsetConverter:: scanString(const StreamFormat& fmt, const char* input, - char* value, size_t maxlen) + char* value, unsigned long& size) { - int length = 0; - int width = fmt.width; + long consumed = 0; + long width = fmt.width; + long space_left = size; - if ((fmt.flags & skip_flag) || value == NULL) maxlen = 0; + if ((fmt.flags & skip_flag) || value == NULL) space_left = 0; - // if user does not specify width assume "ininity" (-1) + // if user does not specify width assume "infinity" (-1) if (width == 0) width = -1; while (*input && width) { if (fmt.info[*input>>3] & 1<<(*input&7)) break; - if (maxlen > 1) + if (space_left > 1) // keep space for terminal null byte { *value++ = *input; - maxlen--; + space_left--; } - length++; + consumed++; width--; input++; } - if (maxlen > 0) + if (space_left) { *value = '\0'; + space_left--; + size -= space_left; // update number of bytes written to value } - return length; + return consumed; } RegisterConverter (StdCharsetConverter, "["); diff --git a/src/StreamFormatConverter.h b/src/StreamFormatConverter.h index d1b2ced..d874dac 100644 --- a/src/StreamFormatConverter.h +++ b/src/StreamFormatConverter.h @@ -56,13 +56,13 @@ public: StreamBuffer& output, const char* value); virtual bool printPseudo(const StreamFormat& fmt, StreamBuffer& output); - virtual int scanLong(const StreamFormat& fmt, + virtual long scanLong(const StreamFormat& fmt, const char* input, long& value); - virtual int scanDouble(const StreamFormat& fmt, + virtual long scanDouble(const StreamFormat& fmt, const char* input, double& value); - virtual int scanString(const StreamFormat& fmt, - const char* input, char* value, size_t maxlen); - virtual int scanPseudo(const StreamFormat& fmt, + virtual long scanString(const StreamFormat& fmt, + const char* input, char* value, unsigned long& size); + virtual long scanPseudo(const StreamFormat& fmt, StreamBuffer& inputLine, long& cursor); }; @@ -130,8 +130,8 @@ void* ref_##converter = ®istrar_##converter\ * You only need to implement the flavour of print and/or scan suitable for * the datatype returned by parse(). * -* Now, fmt.type contains the value returned by parse(). With fmt.info() -* you will get the string you have written to info in parse() (null terminated). +* Now, fmt.type contains the value returned by parse(). With fmt.info() you +* will get the string you have written to info in parse() (null terminated). * The length of the info string can be found in fmt.infolen. * * In print*(), append the converted value to output. Do not modify what is @@ -139,9 +139,14 @@ void* ref_##converter = ®istrar_##converter\ * Return true on success, false on failure. * * In scan*(), read the value from input and return the number of consumed -* bytes. In the string version, don't write more bytes than maxlen! If the -* skip_flag is set, you don't need to write to value, since the value will be -* discarded anyway. Return -1 on failure. +* bytes. +* In the string version, don't write more bytes than size including a +* mandatory terminating null byte. Update size with the number of bytes +* written into the value, wich may differ from the number of bytes consumed +* from the input (e.g. due to leading space). If the skip_flag is set, the +* input will be discarded. Thus, don't write to value. You also don't need +* to update size. +* Return -1 on failure. * * * Register your class diff --git a/src/StreamProtocol.cc b/src/StreamProtocol.cc index ceb8bfa..af9f730 100644 --- a/src/StreamProtocol.cc +++ b/src/StreamProtocol.cc @@ -1484,7 +1484,7 @@ compileFormat(StreamBuffer& buffer, const char*& formatstr, buffer.append(infoString); debug("StreamProtocolParser::Protocol::compileFormat: format.type=%s, " - "infolen=%d infostring=\"%s\"\n", + "infolen=%ld infostring=\"%s\"\n", StreamFormatTypeStr[streamFormat.type], streamFormat.infolen, infoString.expand()()); formatstr = source; // move pointer after parsed format diff --git a/src/TimestampConverter.cc b/src/TimestampConverter.cc index f08c472..1356e61 100644 --- a/src/TimestampConverter.cc +++ b/src/TimestampConverter.cc @@ -75,7 +75,7 @@ class TimestampConverter : public StreamFormatConverter { int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); bool printDouble(const StreamFormat&, StreamBuffer&, double); - int scanDouble(const StreamFormat&, const char*, double&); + long scanDouble(const StreamFormat&, const char*, double&); }; int TimestampConverter:: @@ -516,9 +516,7 @@ startover: return input; } - - -int TimestampConverter:: +long TimestampConverter:: scanDouble(const StreamFormat& format, const char* input, double& value) { struct tm brokenDownTime; diff --git a/src/devaaiStream.c b/src/devaaiStream.c index 18d69dc..7c4f626 100644 --- a/src/devaaiStream.c +++ b/src/devaaiStream.c @@ -114,18 +114,23 @@ static long readData(dbCommon *record, format_t *format) break; case DBF_CHAR: case DBF_UCHAR: - memset(aai->bptr, 0, aai->nelm); aai->nord = 0; - if (streamScanfN(record, format, - (char *)aai->bptr, aai->nelm) == ERROR) + if ((lval = streamScanfN(record, format, + (char *)aai->bptr, aai->nelm)) == ERROR) { + memset(aai->bptr, 0, aai->nelm); return ERROR; } - ((char*)aai->bptr)[aai->nelm-1] = 0; - for (lval = aai->nelm-2; - lval >= 0 && ((char*)aai->bptr)[lval] == 0; - lval--); - aai->nord = lval+1; + if ((size_t)lval < aai->nelm) + { + memset(((char*)aai->bptr)+lval , 0, aai->nelm-lval); + lval++; + } + else + { + ((char*)aai->bptr)[aai->nelm-1] = 0; + } + aai->nord = lval; return OK; default: errlogSevPrintf(errlogFatal, diff --git a/src/devaaoStream.c b/src/devaaoStream.c index 6bc0796..dfc10d7 100644 --- a/src/devaaoStream.c +++ b/src/devaaoStream.c @@ -114,18 +114,23 @@ static long readData(dbCommon *record, format_t *format) break; case DBF_CHAR: case DBF_UCHAR: - memset(aao->bptr, 0, aao->nelm); aao->nord = 0; - if (streamScanfN(record, format, - (char *)aao->bptr, aao->nelm) == ERROR) + if ((lval = streamScanfN(record, format, + (char *)aao->bptr, aao->nelm)) == ERROR) { + memset(aao->bptr, 0, aao->nelm); return ERROR; } - ((char*)aao->bptr)[aao->nelm-1] = 0; - for (lval = aao->nelm-2; - lval >= 0 && ((char*)aao->bptr)[lval] == 0; - lval--); - aao->nord = lval+1; + if ((size_t)lval < aao->nelm) + { + memset(((char*)aao->bptr)+lval , 0, aao->nelm-lval); + lval++; + } + else + { + ((char*)aao->bptr)[aao->nelm-1] = 0; + } + aao->nord = lval; return OK; default: errlogSevPrintf(errlogFatal, diff --git a/src/devwaveformStream.c b/src/devwaveformStream.c index 7531355..b0a32f8 100644 --- a/src/devwaveformStream.c +++ b/src/devwaveformStream.c @@ -114,18 +114,23 @@ static long readData(dbCommon *record, format_t *format) break; case DBF_CHAR: case DBF_UCHAR: - memset(wf->bptr, 0, wf->nelm); wf->nord = 0; - if (streamScanfN(record, format, - (char *)wf->bptr, wf->nelm) == ERROR) + if ((lval = streamScanfN(record, format, + (char *)wf->bptr, wf->nelm)) == ERROR) { + memset(wf->bptr, 0, wf->nelm); return ERROR; } - ((char*)wf->bptr)[wf->nelm-1] = 0; - for (lval = wf->nelm-2; - lval >= 0 && ((char*)wf->bptr)[lval] == 0; - lval--); - wf->nord = lval+1; + if ((size_t)lval < wf->nelm) + { + memset(((char*)wf->bptr)+lval , 0, wf->nelm-lval); + lval++; + } + else + { + ((char*)wf->bptr)[wf->nelm-1] = 0; + } + wf->nord = lval; return OK; default: errlogSevPrintf(errlogFatal,