| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902 |
- #include "gpib_parser_casts.h"
- #include "gpib_parser_validators_numbers.h" // Validators for numbers
- #include "gpib_parser_chars.h" // Service characters definitions
- #include "gpib_parser_validators.h"
- #include "gpib_parser_numutils.h"
- #include "gpib_parser_strutils.h"
- #include <stdlib.h> // atoi
- #include "usb\utils.h" // s_memcpy()
- //------------------------------------------------------------------------------
- static char SCPIBuffer[ STRCACHE_BUFFER_SIZE ];
- //------------------------------------------------------------------------------
- // GPIB_StrChkFormat:
- // Checks the string @str limited by @length characters for matching to the format @mode.
- // In case all of the characters til the end of string (not far than @length characters) are
- // match to the format @mode, function returns TRUE. otherwise, it returns FALSE.
- BOOL GPIB_StrChkFormat( const char * str, int length, const eStringCheckMode_t mode )
- {
- // return FALSE in case @str is NULL, or @length is zero
- if( NULL == str || 0 >= length )
- return FALSE;
-
- // result by default is FALSE
- BOOL rval = FALSE;
- // Check til the end of string limited by @length
- // Every step decrement @length and increment @str
- for( (void)0; (length > 0); length --, str ++ )
- {
- // Check for the end-of-string
- // Check for the end-of-line
- if( IsEndOfString( *str ) || IsEndOfLine( *str ) )
- break; // If found, interrupt the processing and return the current result
-
- switch( mode )
- {
- case eSCM_DEC: rval = IsDemicalChar( *str ); break;
- case eSCM_HEX: rval = IsHexademicalChar( *str ); break;
- case eSCM_FLOAT: rval = IsFloatChar( *str ); break;
- case eSCM_EXP: rval = IsExponentialChar( *str ); break;
- case eSCM_BIN: rval = IsBinaryChar( *str ); break;
- case eSCM_MNEMONIC: rval = IsCharacter( *str ) || IsNumber( *str ); break;
- case eSCM_DIGIT: rval = IsDigit( *str ); break;
- }
-
- // In case of first unsuccessful result, break and return current result (false)
- if( !(rval) ) break;
- }
- return rval;
- }
- //---------------------------
- // @GPIB_StrCopyToCache:
- // Caches the given string @source into the internal buffer and returns the new pointer
- char * GPIB_StrCopyToCache( const char * source, size_t length )
- {
- char * dest;
- if( length+1 <= STRCACHE_BUFFER_SIZE )
- dest = &SCPIBuffer[0];
- else
- dest = NULL;
-
- if( !IsCorrectPointer (dest) )
- dest = NULL;
- else
- {
- s_memcpy( dest, source, length );
- strucase( dest, length - 1 );
- dest [ length ] = 0;
- }
-
- return dest;
- }
- // GPIB_GetStringEnd:
- // Searches for the end of the string @gpibstr until the end of @gpibstr is reached
- // or @length characters is processed
- // Note: the string must be quotted in single or double quotes.
- const char * GPIB_GetStringEnd( const char * gpibstr, size_t length )
- {
- // It is assumed the quotted string can not be shorter than 2 characters
- if( (NULL == gpibstr) || (2 > length) )
- return NULL;
-
- // detect the quotting mode: single or doulbe
- eQuoteMode_t qMode = eqmNone;
- if( IsSingleQuote( *gpibstr ) )
- {
- qMode = eqmSingle;
- }
- else
- if( IsDoubleQuote( *gpibstr ) )
- {
- qMode = eqmDouble;
- }
- else
- {
- return NULL;
- }
- const char * end = NULL; // end of the string pointer
-
- BOOL bQuoteOpened = FALSE;
-
- // for each of @length characters in the string
- for( const char * iter = gpibstr; iter != (gpibstr + length); ++iter )
- {
- // If the current parameter is end-of-line or end-of-string,
- // and the cycle is still counting, it means error condition,
- // due to @length is specified incorrectly.
- if( IsEndOfString( *iter ) || IsEndOfLine( *iter ) )
- {
- return NULL;
- }
-
- if( IsQuote(*iter,qMode) )
- {
- // If the quotted string opened (opening quote passed)
- if( bQuoteOpened )
- {
- // End-of-quotted string found
- end = ++iter;
- break;
- }
- else
- {
- // The quotted string opened
- bQuoteOpened = TRUE;
- }
- }
- }
-
- return end;
- }
- // GPIB_GetParameterEnd:
- // Searches for the end signature of the parameter in @string until the
- // end of @string string is reached or @length characters is processed.
- // The first "white" character is treated as an end signature.
- // Does not support SCPI DataBlock format.
- const char * GPIB_GetParameterEnd( const char * string, size_t length )
- {
- if( (NULL == string) || (0 == length) )
- return NULL;
-
- const char * end = (string + length); // end of the string pointer
-
- // for each of @length characters in the string
- for( const char * iter = string; iter != end; ++iter )
- {
- // If the current parameter is end-of-line, end-of-string or white-character
- // then it means the end of the parameter reached.
- if( IsEndOfString( *iter ) || IsEndOfLine( *iter ) || IsWhiteChar( *iter ) )
- {
- return iter;
- }
-
- // If the current parameter is an argument separator then
- // it means the end of the parameter reached.
- if( IsArgSeparatorChar( *iter ) )
- {
- return iter;
- }
- }
-
- // Neither end-of-line, end-of-string or white-character found.
- // The end of the parameter is out of string.
- return end;
- }
- // GPIB_StrChr:
- // Searches a character @chr in the string beginning from @str and limited by @end.
- // If the function faces a null-character or end-of-line condition, it stops searching.
- // Function returns the pointer to the found character in @str, or NULL if not found.
- const char * GPIB_StrChr( const char * str, const char chr, const char * end )
- {
- for( const char * iter = str; iter != end; ++iter )
- {
- // Check the limits
- if( IsEndOfString( *iter ) || IsEndOfLine( *iter ) )
- {
- // end-of-string condition: interrupt the searching
- // end-of-line condition: interrupt the searching
- break;
- }
-
- if( chr == *iter )
- {
- return iter;
- }
- }
-
- // not found
- return NULL;
- }
- // GPIB_StrLen:
- // Calculates the length of string.
- // The function assumes that the string ends with either end-of-line character
- // or end-of-string character.
- size_t GPIB_StrLen( const char * str )
- {
- if( NULL == str )
- return 0;
-
- for( const char * iter = str; (void)iter, !0; ++iter )
- {
- // Check the limits
- if( IsEndOfString( *iter ) || IsEndOfLine( *iter ) )
- {
- // end-of-string condition: end the searching
- // end-of-line condition: end the searching
- return SubPointers( iter, str );
- }
- }
-
- // never reachs this point
- return 0;
- }
- // GPIB_CheckHeader:
- // Check if the given @header is valid GPIB header.
- // Returns TRUE if it is, and FALSE otherwise.
- //BOOL GPIB_CheckHeader( const char * header )
- BOOL GPIB_CheckHeader( const char * header, const char * end )
- {
- if( NULL == header )
- return FALSE;
-
- // disallow the number in the beginning of @header
- if( IsNUMBER( *header ) )
- return FALSE;
-
- BOOL rval = TRUE;
-
- // allow one 'MANDATORY' signature (by default '*', e.g "*IDN?") in
- // the beginning of the string
- if( GPIB_CHAR_MANDATORY_IEEE488_SIGN == *header )
- {
- // skip only the first MANDATORY character
- ++ header;
- }
-
- for( const char * iter = header; (void)iter, !0; ++iter )
- {
- // Check the end condition
- if( iter == end )
- {
- (void)rval;
- break;
- }
-
- // Check the limits
- if( IsEndOfString( *iter ) || IsEndOfLine( *iter ) )
- {
- // end-of-string condition: interrupt validating
- // end-of-line condition: interrupt validating
- break;
- }
-
- // check if the character is valid for the GPIB header body
- if( ! IsValid_GPIBHeaderBodyChar( *iter ) )
- {
- // if at least one character is invalid, break and return FALSE
- rval = FALSE;
- break;
- }
- }
-
- return rval;
- }
- // GPIB_HeaderCompare:
- // Compares a couple of GPIB command headers.
- // Note: the comparation is case insensitive.
- // @headerTree - the original command header, including an optional command
- // signature (if required), e.g. optional "[SYSTem]" or mandatory "SYST"
- // @headerUser - actually entered command header
- // Note: for optional headers it is not required a paired ']' in the end of header.
- // Returns TRUE if headers are identical, and FALSE otherwise.
- BOOL GPIB_HeaderCompare( const char * headerTree, const char * headerUser )
- {
- BOOL bOptional = FALSE;
- BOOL bFirst = TRUE;
-
- //size_t strlen_Tree = GPIB_StrLen( headerTree );
- //size_t strlen_User = GPIB_StrLen( headerUser );
-
-
- if( IsOptionalHeader(headerTree) )
- {
-
- headerTree++;
- bOptional = TRUE;
- }
-
- const char * iter_tree;
- const char * iter_user;
-
- // For each character in the original string @headerTree and the
- // entered string @headerUser simultaneosly.
- for( iter_tree = headerTree, // iterator for original string
- iter_user = headerUser, // iterator for entered string
- bFirst = TRUE; // the first character sign
- (void)iter_tree, //
- (void)iter_user, //
- !0; // do this cycle forever
- ++iter_tree, // next character in the original string
- ++iter_user, // next character in the entered string
- bFirst = FALSE ) // reset @bFirst after the first character in the string
- {
- // Check the limits:
- // If the end of original string is faced.
- if( IsEndOfString( *iter_tree ) || IsEndOfLine( *iter_tree ) )
- {
- // and the end of the entered string is faced too
- if( IsEndOfString( *iter_user ) || IsEndOfLine( *iter_user ) )
- {
- // headers are identical due to all the characters til
- // the end of both strings are identical.
- return TRUE;
- }
- }
- else
- // The end of original string is NOT faced yet.
- {
- // But if the end of the entered string is faced
- if( IsEndOfString( *iter_user ) || IsEndOfLine( *iter_user ) )
- {
- // end of compare
- // strings mismatch
-
- // But wait, let's check for the optional header signature in
- // the end of original string (by default, ']')
- // Check if the header is optional
- if( bOptional )
- {
- // yes, it is optional
-
- // check if the next character in the original string is
- // a closing sign of optional header (by default, ']')
- if( GPIB_CHAR_OPTIONALHEADER_ENDSIGN == *iter_tree )
- {
- // yes, it is.
- // Actually, the headers are identical til the
- // closing sign.
-
- // ignore the rest part of original string, and
- // assume the headers are identical
- return TRUE;
- }
- }
-
- // No choice left: headers mismatch
- break;
- }
- }
-
- // Check for optional marker (by default, '[') in the beginning of the original string
- if( (bFirst) && (GPIB_CHAR_OPTIONALHEADER_SIGN == *iter_tree) )
- {
- // This header is a header of optional SCPI-subsystem
- bOptional = TRUE;
-
- // skip this character
- iter_tree++;
-
- // continue the comparation
- continue;
- }
-
- // characters mismatch
- // Note: comparation is case insensetive.
- if( tolower(*iter_tree) != tolower(*iter_user) )
- {
- // strings mismatch
- break;
- }
- }
-
- // headers mismatch
- return FALSE;
- }
- // GPIB_StringToNumber:
- // Converts the string into a number
- // @str - source string pointer
- // @chars - number of characters to be converted (can not be greater than 10)
- // @pReturn - pointer to the receiving variable, can be NULL
- // Result: TRUE in case of success, FALSE otherwise.
- // In case the given number is valid and @pReturn is NULL, function just return TRUE
- // This behaviour can be used to validate numbers without parsing.
- BOOL GPIB_StringToNumber( const char * str, size_t chars, int32_t * pReturn )
- {
- char buffer[ 11 ] = {0};
-
- if( chars > 10 )
- return FALSE; // too long string
-
- if( chars == 0 )
- return FALSE; // too short string
-
- // validate the string
-
- BOOL allow_sign = TRUE; // flag: allow the sign operator (plus/minus)
- BOOL allow_space = TRUE; // flag: allow the space
- BOOL allow_digit = TRUE; // flag: allow a digit
- BOOL digits = FALSE; // flag: digits detected
-
- for( const char * iter = str; iter != (str+chars); ++iter )
- {
- if( '\0' == *iter )
- break;
-
- // the space faced
- if( ' ' == *iter )
- {
- // if the space is allowed
- if( allow_space )
- {
- // if digits already faced
- if( digits )
- {
- // allow only spaces til the end
- allow_digit = FALSE;
- }
-
- continue;
- }
- else
- {
- return FALSE; // error: space is unexpected
- }
- }
-
- // the sign faced
- if( '+' == *iter || '-' == *iter )
- {
- if( allow_sign )
- {
- allow_sign = FALSE; // only one operator is allowed
- allow_space = FALSE; // disallow the space after the operator
- continue;
- }
-
- return FALSE; // error: extra sign operator
-
- }
- // a digit faced
- if( IsDigit( *iter ) )
- {
- if( allow_digit )
- {
- allow_sign = FALSE; // operator must be before any digit
- allow_space = TRUE; // allow any amount of spaces after last digit
- digits = TRUE; // digits faced
- continue;
- }
-
- return FALSE; // error: separated tokens detected
- }
-
- return FALSE; // error by default. the "continue" must prevent this return
- }
-
- // here: the string contains a valid number
-
- // if @pReturn is NULL, just return the result of validating
- if( NULL == pReturn )
- return TRUE;
-
- s_memcpy( buffer, str, chars );
- buffer[chars] = '\0'; // null terminator
-
- *pReturn = atoi( buffer );
-
- return TRUE;
- }
- // IsDataBlock:
- // The data transfer block validator: Binary transfer format (IEEE488.2)
- // Format: the data block consist of the following elements: '#', N, Z, DATA
- // '#' - data block signature character;
- // N - a demical digit, amount of digits in Z;
- // Z - a demical number (multi-digit), the size of binary bytes in DATA.
- // DATA - binary data bytes.
- // e.g. "#213Hello, world!"
- // N=2 - amount of digits in Z
- // Z=13 - amount of binary bytes (strlen(DATA)=13)
- // DATA = "Hello, world!"
- //
- // @begin - the string to validate
- // @length - the length of string @begin
- // @p_nsize - optional pointer which will be filled up with the datablock size in bytes
- // @pRetCode - optional pointer to store either the error variable to be filled with the
- // error code, or in case sucess the binary data payload size in bytes.
- // *pRetCode can be:
- // > (err_IsDataBlock_Success) - success (never returns);
- // > (err_IsDataBlock_NotFound) - datablock not found;
- // > (err_IsDataBlock_Invalid) - datablock found, but has invalid format
- // > (err_IsDataBlock_Trimmed) - datablock found, but it is trimmed
- // > (err_IsDataBlock_Huge) - datablock found, but it's too large
- // > the binary payload size
- //
- // Returns TRUE only if the datablock format is valid, all the parameter of datablock
- // are valid and do not violates any ranges.
- BOOL IsDataBlock( const char * begin, size_t length, size_t * p_nsize, int * pRetCode )
- {
- int error = 0;
- size_t N = 0;
- int32_t Z = 0;
- const char * iter = NULL;
-
- // at least 2 bytes required
- if( NULL == begin || 2 > length )
- {
- // invalid parameters
- // error: datablock not found
- error = err_IsDataBlock_NotFound;
-
- goto L_IsDataBlock_ERR;
- }
-
- // check the signature
- if( GPIB_CHAR_DATATABLE_SIGN != *begin )
- {
- // invalid: no signature
- // error: datablock not found
- error = err_IsDataBlock_NotFound;
-
- goto L_IsDataBlock_ERR;
- }
- iter = begin;
-
- { // decrease length and shift iterator: '#'
- length--;
- iter++;
- }
-
- if( !IsDemicalChar( *iter ) )
- {
- // invalid: "N" must be a demical digit (amount of characters in "Z")
- // error: datablock not found
- error = err_IsDataBlock_NotFound;
-
- goto L_IsDataBlock_ERR;
- }
-
- N = DecCharToNum( *iter ); // number of characters in "Z"
-
- { // decrease length and shift iterator: 'N'
- length--;
- iter++;
- }
-
- if( N == 0 )
- {
- // invalid: N can not be zero
- // error: datablock found with invalid format
- error = err_IsDataBlock_Invalid;
-
- goto L_IsDataBlock_ERR;
- }
-
- if( (length == 0) || (length < N) )
- {
- // empty data block
- // error: trimmed datablock found
- error = err_IsDataBlock_Trimmed;
-
- goto L_IsDataBlock_ERR;
- }
-
- // check the int32 overflow condition:
- // If N=9, it means Z is less than 1000000000
- // and there no necessary to provide any checks.
- // Lets choose this way.
- if( N > 9 )
- {
- // integer overflow
- // error: datablock is too large.
- error = err_IsDataBlock_Huge;
-
- goto L_IsDataBlock_ERR;
- }
-
- // validate "Z" - must be a demical digits
- if( !GPIB_StrChkFormat( iter, N, eSCM_DIGIT ) )
- {
- // invalid: invalid format of "Z"
- // error: datablock found with invalid format
- error = err_IsDataBlock_Invalid;
-
- goto L_IsDataBlock_ERR;
- }
-
- Z = 0;
-
- // Parse the number "Z"
- if( !GPIB_StringToNumber( iter, N, &Z ) )
- {
- // invalid number "Z"
- // error: datablock found with invalid format
- error = err_IsDataBlock_Invalid;
-
- goto L_IsDataBlock_ERR;
- }
-
- { // decrease length and shift iterator: 'Z'
- length-=N;
- iter+=N;
- }
-
- // check if the datablock fits into the given string
- if( Z > length )
- {
- // trimmed data block
- // error: trimmed datablock found
- error = err_IsDataBlock_Trimmed;
-
- goto L_IsDataBlock_ERR;
- }
- // Okay, it seems to be valid...
-
- { // decrease length and shift iterator: 'DATA'
- length-=Z;
- iter+=Z;
- }
-
- // if @p_nsize is specified
- if( NULL != p_nsize )
- *p_nsize = SubPointers( iter, begin ); // store the datablock size in bytes
-
- // store the binary data size into @error
- if( NULL != pRetCode ) *pRetCode = Z;
-
- return TRUE;
-
- L_IsDataBlock_ERR:
- if( NULL != pRetCode ) *pRetCode = error;
- return FALSE;
- }
- // #########################################################################
- // #########################################################################
- // #########################################################################
- // #########################################################################
- // #########################################################################
- // #########################################################################
- // #########################################################################
- // #########################################################################
- // #########################################################################
- //-----------------------------------
- /*
- char * s_strchrex( char * str, char chr, char * end )
- {
- register char * strp = str;
- char * ret = NULL;
- while(ret==NULL)
- { if((unsigned int)end <= (unsigned int)str) break;
- if(*strp==chr) ret = strp;
- strp++;
- }
- return ret;
- }
- */
- /*
- char * strterm( char * source, unsigned int length )
- {
- //<W><W><W>AAAA<W><W><0> -> <W><W><W>AAAA<0>
- while(!IsWhiteChar(*source) && length--)
- source++;
- if(length>0) *source = 0x00;
- return source;
- }
- */
- //-----------------------------------
- /*
- int strsep( char * source, unsigned int length )
- {
- int first = 0;
- //<W><W>BBBBB<W><W>AAAA<W><W><0> -> <W><W><W>AAAA<0>
- while(IsWhiteChar(*source) && length--) source++;
- first = length;
- while(!IsWhiteChar(*source) && length--)
- source++;
- if(length>0) *source = 0x00;
- return first;
- }
- */
- // ===================================== Ïðåîáðàçîâàíèå ÷èñåë â ñòðîêè ===========================
- // -----------------------
- //
- //
- //
- //
- //
- /*
- // ------------------- FloatsToString --------------
- //
- // Èñïîëüçîâàíèå:
- //
- // char buffer[32];
- // float f1,f2,f3,f4,f5,f6,f7,f8=3.142;
- // GPIB_PrintFloat( buffer, 32, 1000, 8, &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8 );
- // ^^^^ òî÷íîòü ïîñëå çàïÿòîé
- //
- // buffer=="0.000,0.000,0.000,0.000,0.000,0.000,0.000,3.142"
- unsigned int GPIB_PrintFloatEx( char * out, int buffersize, unsigned int accuracy, int count, float * f1, ...)
- {
- int l=0,c=0;
- unsigned char buffer[10] = {0};
- while( count-- && c<buffersize )
- {
- if(c){
- *(out+c) = ',';
- c++;}
- l = Float2StrEx( f1, buffer, 10, accuracy);
- s_memcpy( out+c, buffer, l );
- c+=l;
- f1++;
- }
- return c;
- }
- */
- /*
- unsigned int GPIB_PrintHex( char * out, int buffersize, int count, int * hex1, ...)
- {
- int c=0;
- while( count-- && c < buffersize )
- {
- if(c)
- c+= snprintf( out+c, buffersize-c, "," );
- c+= snprintf( out+c, buffersize-c, "%x", *hex1 );
- hex1++;
- }
- return c;
- }
- */
- // ---------------------------------------------------------------------------------------------
- /*
- unsigned int GPIB_PrintBin( char * out, int buffersize, int count, unsigned int bin, ...)
- {
- int c=0;
- unsigned int * bin1 = &bin;
- unsigned int mask;
- while( count-- && c < buffersize )
- {
- if(c)
- c+= snprintf( out+c, buffersize-c, "," );
- // -----------------------------
- if( (c < buffersize) ) *(out+c++) = '0';
- if( (c < buffersize) ) *(out+c++) = 'b';
- mask = 0x80000000; // 0b10000000000000000000000000000000
- while( mask && (c < buffersize) )
- {
- if( mask & *bin1 )
- *(out+c++) = '1';
- else
- *(out+c++) = '0';
- if( mask & (1<<0) )
- mask = 0x00000000;
- else
- mask>>=1;
- }
- // -----------------------------
- bin1++;
- }
- return c;
- }
- */
- /*
- // ------------ s_printf ----------------------------------
- // Ïîääåðæêà ñïåöèôèêàòîðîâ:
- // 0 %c - char
- // 1 %s - string
- // 2 %d - int
- // 3 %u - unsigned int
- // 4 %f - float (!)
- // 5 %x - hex
- // 6 %b - bin
- // 7 %o - oct
- // 8 %e - scientific number
- // -------------------------- ÇÍÀ×ÅÍÈß ÏÅÐÅÄÀÞÒÑß ÏÎ ÓÊÀÇÀÒÅËÞ !
- unsigned int s_nprintf( char * out, int buffersize, char * spec, /_* char , int , float , unsigned *_/... )
- {
- // Ïðè ïåðåäà÷å ïàðàìåòðîâ ÷åðåç ñòåê â ôóíêöèþ, êîòîðàÿ íå èìååò ôîðìàëüíûõ àðãóìåíòîâ
- // äåéñòâóåò ïðàâèëî ïðèâåäåíèÿ float->double. Double íà ñòåêå âûðâàíèâàåòñÿ ïî 8 áàéò
- //
- //
- char * pointer = (char*)(&spec)+sizeof(char*);
- unsigned int c = 0; // -- êîëè÷åñòâî âûâîäèìûõ â áóôåð ñèìâîëîâ
- unsigned int k = 0; // -- äëÿ öèêëà ïî ñïåöèôèêàòîðàì
- unsigned int z = 0; // -- äëÿ ïîèñêà ñïåöèôèêàòîðà
- int t = 0;
- char * s, * __s; // -- õðàíèò ñäâèã ïî spec
- int zmin = -1; // -- äëÿ ïîèñêà ñïåöèôèêàòîðà
- #define fc 9
- unsigned char specs[fc] = { 'c', 's', 'd', 'u', 'f', 'x', 'b', 'o', 'e' };
-
- while( c < buffersize && *spec && t!=-1)
- if(*spec == '%'){
- // ------------ îïðåäåëåíèå òèïà ------------
- for(k=0,t=-1,zmin=-1;k<=fc;k++)
- if( (__s= GPIB_StrChr( spec, specs[k], NULL)) || (__s= GPIB_StrChr( spec, 0x20 + specs[k], NULL))) // ucase support also
- {
- z=(unsigned int)__s - (unsigned int)spec;
- if(zmin > z || zmin ==-1)
- { zmin = z;
- t=k; // òèï
- s=__s; // îïðåäåëÿåò êîíåö ñïåöèôèêàòîðà
- }
- }
- //--------------------------------------------
- switch(t)
- {
- case 0: // %c
- // -- char ïðåîáðàçîâàí ê int
- c+=snprintf( out+c, buffersize-c, "%c", *((int *)pointer));
- pointer+=sizeof(unsigned int);
- spec = s+1;
- break;
- case 1: // %s
- c+=snprintf( out+c, buffersize-c, "%s", (char *)pointer);
- pointer+=sizeof(char*);
- spec = s+1;
- break;
- case 2: // %d
- c+=snprintf( out+c, buffersize-c, "%d", *((int *)pointer));
- pointer+=sizeof(int);
- spec = s+1;
- break;
- case 3: // %u
- c+=snprintf( out+c, buffersize-c, "%u", *((unsigned int *)pointer));
- pointer+=sizeof(unsigned int);
- spec = s+1;
- break;
- case 4: // %f
- // case 8: // %e
- if((int)pointer&0x07) pointer+= (int)pointer%8; // Ñòàíäàðòíîå ïðîäâèæåíèå òèïîâ. Åñëè ââîäèòü ôóíêöèþ áåç ôîðìàëüíûõ
- // ïàðàìåòðîâ, òî float áóäåò ïðåîáðàçîâàí ê double, char ê int è ò.ï.
- // double âåñèò 8 áàéò, ïîýòîìó íàäî ýòî ó÷èòûâàòü ïðè ïåðåäâèæåíèè óêàçàòåëÿ
- c+=snprintf( out+c, buffersize-c, "%lf", *((double *)pointer));
- pointer+=sizeof(double); // double!
- spec = s+1;
- break;
- case 5: // %x
- c+=snprintf( out+c, buffersize-c, "%x", *((unsigned int *)pointer));
- pointer+=sizeof(unsigned int);
- spec = s+1;
- break;
- case 6: // %b
- c+=GPIB_PrintBin( out+c, buffersize-c, 1, *((unsigned int*)pointer));
- pointer+=sizeof(unsigned int); // double!
- spec = s+1;
- break;
- case 7: // %o
- c+=snprintf( out+c, buffersize-c, "%o", *((unsigned int *)pointer));
- pointer+=sizeof(unsigned int);
- spec = s+1;
- break;
- case 8: // %e
- c+=snprintf( out+c, buffersize-c, "%e", *((double*)pointer));
- pointer+=sizeof(double);
- spec = s+1;
- break;
- default:
- if( t==-1) break;
- spec = s+1;
- }
- } else
- {snprintf( out+c, buffersize-c, "%c", *(spec++) ); c++;}
-
- return c;
- }
- */
|