G:/ScriptBasic/source/match.c

Go to the documentation of this file.
00001 /*
00002 FILE:   match.c
00003 HEADER: match.h
00004 
00005 --GNU LGPL
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2.1 of the License, or (at your option) any later version.
00010 
00011 This library is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 Lesser General Public License for more details.
00015 
00016 You should have received a copy of the GNU Lesser General Public
00017 License along with this library; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 TO_HEADER:
00021 
00022 #define JOKERNR 13
00023 
00024 #define NOJOKER     0
00025 #define SINGLEJOKER 1
00026 #define MULTIJOKER  3
00027 
00028 typedef struct _MatchSets {
00029   unsigned char SetType[JOKERNR];
00030   unsigned char set[JOKERNR][32];
00031   } MatchSets, *pMatchSets;
00032 
00033 */
00034 #include <ctype.h>
00035 #include <string.h>
00036 #include "match.h"
00037 #include "errcodes.h"
00038 
00039 /*POD
00040 @c Simple Pattern Matching
00041 
00042 =abstract
00043 A simple, non-regular expression pattern matching module mainly to perform
00044 file name pattern matching, like T<*.txt> or T<file0?.bin> and alikes.
00045 =end
00046 
00047 This is a simple and fast pattern matching algorithm.
00048 This can be used when the matching does not require
00049 regular expression complexity and the processign on 
00050 the other hand should be fast.
00051 
00052 There are two major tasks implemented here. One is to match a string against a pattern.
00053 The second is to create a replacement string. When a pattern is matched by a string an
00054 array of string values are created. Each contains a substring that matches a joker character.
00055 Combining this array and a format string a replacement string can be created.
00056 
00057 For example:
00058 
00059 =verbatim
00060 
00061 String = "mortal  combat"
00062 Pattern = "mo?tal co*"
00063 
00064 =noverbatim
00065 
00066 the joker characters are the ?, the space (matching one or more space) and the * character.
00067 They are matched by T<r>, two spaces and T<mbat>. If we use the format string
00068 
00069 =verbatim
00070 Format string = "$1u$2"
00071 =noverbatim
00072 
00073 we get the result string T<rumbat>. The format string can contain T<$n> placeholders
00074 where T<n> starts with 1 and is replaced by the actual value of the n-th joker character.
00075 
00076 
00077 CUT*/
00078 
00079 #define ESCAPE_CHARACTER '~'
00080 
00081 /* the characters that can be joker character */
00082 static char JokerCharacter[] = "*#$@?&%!+/|<>";
00083 
00084 #define F 0xFF
00085 #define E 0xFE
00086 static MatchSets DefaultMatchSets = {
00087 /*  *           #           $           @           ? */
00088     { MULTIJOKER, MULTIJOKER, MULTIJOKER, MULTIJOKER, SINGLEJOKER, 
00089 /*  &        %        !        +        /        |        <        > */
00090       NOJOKER, NOJOKER, NOJOKER, NOJOKER, NOJOKER, NOJOKER, NOJOKER, NOJOKER },
00091      /*                            1  1  1  1  1  1  1  1  1  1  2  2  2  2  2  2  2  2  2  2  3  3  3 */
00092     {/* 1  2  3  4  5  6  7  8  9  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5  6  7  8  9  0  1  2 */
00093 
00094 /*      0  8  16 24 32 40 48 56 64 72 80 88 96 104
00095 */
00096 /***/ { F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F} ,
00097 /*#*/ { 0, 0, 0, 0, 0, 0, F, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00098 /*$*/ { 0, 0, 0, 0, 0, 0, F, 3, E, F, F, 7, E, F, F, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00099 /*@*/ { 0, 0, 0, 0, 0, 0, 0, 0, E, F, F, 7, E, F, F, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00100 /*?*/ { F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F} ,
00101 /*&*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00102 /*%*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00103  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00104 /*+*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00105 /*/*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00106 /*|*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00107 /*<*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ,
00108 /*>*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
00109     }
00110   };
00111 #undef F
00112 #undef E
00113 
00114 /*POD
00115 =H match_index
00116 @c Return the joker index of the character
00117 
00118 There are a few characters that can be used as joker character. These are
00119 
00120 =verbatim
00121 *#$@?&%!+/|<>
00122 =noverbatim
00123 
00124 T<match_index> returns the serial number of the character.
00125 /*FUNCTION*/
00126 unsigned long match_index(char ch
00127 ){
00128 /*noverbatim
00129 CUT*/
00130   int i;
00131   for( i = 0 ; JokerCharacter[i] ; i++ )
00132     if( JokerCharacter[i] == ch )return i+1;
00133 
00134   return 0;
00135   }
00136 
00137 static unsigned char *MultiJokerSet(pMatchSets pMS, char ch){
00138   int i;
00139 
00140   if( ! (i = match_index(ch)) )return NULL;
00141   i--;
00142   if( pMS->SetType[i] == MULTIJOKER )return pMS->set[i];
00143   return NULL;
00144   }
00145 
00146 static unsigned char *SingleJokerSet(pMatchSets pMS, char ch){
00147   int i;
00148 
00149   if( !(i = match_index(ch)) )return NULL;
00150   i--;
00151   if( pMS->SetType[i] == SINGLEJOKER )return pMS->set[i];
00152   return NULL;
00153   }
00154 
00155 static int JokerMatch(unsigned char *set, unsigned char ch){
00156   int index,offset;
00157 
00158   index = ch >> 3;
00159   offset = ch & 7;
00160   index = set[index];
00161   index >>= offset;
00162   return index;
00163   }
00164 /*POD
00165 =H InitSets
00166 @c Initialize a set collection
00167 
00168 Call this function to initialize a set collection. The argument should point to
00169 a T<MatchSets> structure and the function fills in the default values.
00170 
00171 /*FUNCTION*/
00172 void match_InitSets(pMatchSets pMS
00173   ){
00174 /*noverbatim
00175 CUT*/
00176   memcpy((void *)pMS,(void *)&DefaultMatchSets,sizeof(DefaultMatchSets));
00177   }
00178 
00179 /*POD
00180 =H ModifySet
00181 @c Modify a joker set
00182 
00183 This function can be used to modify a joker set. The first argument T<pMS> points to the
00184 joker set collection. The second argument T<JokerCharacter> specifies the joker character
00185 for which the set has to be modified.
00186 
00187 The argument T<nChars> and T<pch> give the characters that are to be modified in the set.
00188 T<nChars> is the number of characters in the character array pointed by T<pch>.
00189 
00190 The last argument T<fAction> specifies what to do. The following constants can be used in
00191 logical OR.
00192 
00193 =verbatim
00194 TO_HEADER:
00195 
00196 #define MATCH_ADDC 0x0001 //add characters to the set
00197 #define MATCH_REMC 0x0002 //remove characters from the set
00198 #define MATCH_INVC 0x0004 //invert the character
00199 #define MATCH_SNOJ 0x0008 //set becomes no-joker
00200 #define MATCH_SSIJ 0x0010 //set becomes single joker
00201 #define MATCH_SMUJ 0x0020 //set becomes multiple joker
00202 #define MATCH_NULS 0x0040 //nullify the set
00203 #define MATCH_FULS 0x0080 //fullify the set
00204 
00205 */
00206 /*noverbatim
00207 
00208 The function first checks if it has to modify the state of the joker character. If
00209 any of the bits T<MATCH_SNOJ>, T<MATCH_SSIJ> or T<MATCH_SMUJ> is set in the field
00210 T<fAction> the type of the set is modified.
00211 
00212 If more than one bit of these is set then result is undefined. Current implementation
00213 checks these bits in a specific order, but later versions may change.
00214 
00215 If the bit T<MATCH_NULS> is set all the characters are removed from the set. If
00216 the bit T<MATCH_FULS> is set all characters are put into the set.
00217 
00218 If more than one bit of these is set then result is undefined. Current implementation
00219 checks these bits in a specific order, but later versions may change.
00220 
00221 T<MATCH_NULS> or T<MATCH_FULS> can be used in a single call to initialize the set before
00222 adding or removing the specific characters.
00223 
00224 The bits T<MATCH_ADDC>, T<MATCH_REMC> and T<MATCH_INVC> can be used to add characters to the set,
00225 remove characters from the set or to invert character membership. The characters are taken
00226 from the character array pointed by the function argument T<pch>.
00227 
00228 If more than one bit of these is set then result is undefined. Current implementation
00229 checks these bits in a specific order, but later versions may change.
00230 
00231 If none of these bits is set the value of the pointer T<pch> is ignored.
00232 
00233 It is no problem if a character is already in the set and is added or if it is not member of the set
00234 and is removed. Although it has no practical importance the array pointed by T<pch> may contain a
00235 character many times.
00236 
00237 /*FUNCTION*/
00238 void match_ModifySet(pMatchSets pMS,
00239                      char JokerCharacter,
00240                      int nChars,
00241                      unsigned char *pch,
00242                      int fAction
00243   ){
00244 /*noverbatim
00245 CUT*/
00246   int i,index,offset;
00247   unsigned char *set,mask;
00248 
00249   i = match_index(JokerCharacter);
00250   if( i == 0 )return;
00251   i--;
00252   if( fAction & MATCH_SNOJ )pMS->SetType[i] = NOJOKER;
00253   if( fAction & MATCH_SSIJ )pMS->SetType[i] = SINGLEJOKER;
00254   if( fAction & MATCH_SMUJ )pMS->SetType[i] = MULTIJOKER;
00255 
00256   set = pMS->set[i];
00257   if( fAction & MATCH_NULS )
00258     for( i=0 ; i<32 ; i++ )set[i] = 0;
00259   if( fAction & MATCH_FULS )
00260     for( i=0 ; i<32 ; i++ )set[i] = 0xFF;
00261 
00262   if( fAction & (MATCH_ADDC|MATCH_REMC) )
00263     while( nChars-- ){
00264       mask = 1;
00265       index = (*pch) >> 3;
00266       offset = (*pch) & 7;
00267       mask <<= offset;
00268       if( fAction & MATCH_ADDC )set[index] |= mask;
00269       if( fAction & MATCH_INVC )set[index] ^= mask;
00270       if( fAction & MATCH_REMC ){
00271         mask = ~mask;
00272         set[index] &= mask;
00273         }
00274       pch++;
00275       }
00276   return;
00277   }
00278 
00279 /*POD
00280 =H match
00281 @c Match pattern to string
00282 FUNCTION:
00283 
00284 T<match> checks if pszString matches the pattern pszPattern.
00285 pszPattern is a string containing joker characters. These are:
00286 
00287 =verbatim
00288  * matches one or more any character
00289  # matches one or more digit
00290  $ matches one or more alphanumeric character
00291  @ matches one or more alpha character
00292    (space) matches one or more spaces
00293  ? matches a single character
00294 =noverbatim
00295 
00296  T<~x> matches T<x> even if T<x> is pattern matching character or tilde
00297 
00298  T<x> matches character T<x> unless it is a joker character
00299 
00300 RETURN VALUE:
00301 
00302 The function returns zero if no error occures and returns an error code
00303 in case some of the memory buffer does not have enough space. (Either
00304 pszBuffer or ParameterArray)
00305 
00306 PARAMETERS:
00307 
00308 T<pszPattern> IN
00309 the pattern to match
00310 
00311 --
00312 
00313 T<cbPattern> IN
00314 the number of characters in the pattern
00315 
00316 --
00317 
00318 T<pszString> IN 
00319 the string which is compared to the pattern
00320 
00321 --
00322 
00323 T<cbString> IN
00324 the number of characters in the string
00325 
00326 --
00327 
00328 T<ParameterArray> OUT
00329 is an uninitialized character pointer array. Upon return
00330 T<ParameterArray[i]> points the string that matches the
00331 T<i>-th joker character.
00332 
00333 --
00334 
00335 T<pcbParameterArray> OUT
00336 is an uninititalized T<unsigned long> array. Upon return
00337 T<pcbParameterArray[i]> contains the length of the
00338 output parameter T<ParameterArray[i]>.
00339 
00340 --
00341 
00342 T<pszBuffer> OUT
00343 should point to a buffer. The size of the buffer
00344 should be specified by cbBufferSize. A size equal
00345 
00346 =verbatim
00347              cbString
00348 =noverbatim
00349 is a safe size. The actual strings matching the joker characters
00350 will get into this buffer zero terminated one after the other:
00351 
00352 --
00353 
00354 T<cArraySize> IN
00355 number of elements in the array T<ParameterArray>
00356 
00357 --
00358 
00359 T<cbBufferSize> IN
00360 size of the buffer pointed by pszBuffer
00361 
00362 --
00363 
00364 T<fCase> IN
00365 pattern matching is performed case sensitive if this value if TRUE.
00366 
00367 --
00368 
00369 T<iResult> OUT
00370 TRUE if T<pszString> matches the pattern T<pszPattern>.
00371 FALSE otherwise.
00372 
00373 NOTE:
00374 
00375 T<pszPattern> and T<pszString> are NOT changed.
00376 
00377 If the function returns non-zero (error code) none of the output
00378 variables can be reliably used.
00379 /*FUNCTION*/
00380 int match_match(char *pszPattern,
00381                 unsigned long cbPattern,
00382                 char *pszString,
00383                 unsigned long cbString,
00384                 char **ParameterArray,
00385                 unsigned long *pcbParameterArray,
00386                 char *pszBuffer,
00387                 int cArraySize,
00388                 int cbBufferSize,
00389                 int fCase,
00390                 pMatchSets pThisMatchSets,
00391                 int *iResult
00392   ){
00393 /*noverbatim
00394 CUT*/
00395   char cA,cB;
00396   int ErrorCode;
00397   unsigned char *set;
00398 
00399   if( pThisMatchSets == NULL )pThisMatchSets = &DefaultMatchSets;
00400 
00401   *iResult = 0;/* note that iResult is set to 1 directly before success return */
00402   while( 1 ){
00403 
00404     if( ! cbString ){
00405       *iResult = ! cbPattern;
00406       return MATCH_ERROR_SUCCESS;
00407       }
00408 
00409     if( set=MultiJokerSet(pThisMatchSets,*pszPattern) ){
00410       if( ! cbString )return MATCH_ERROR_SUCCESS; /* nothing to match by the joker character */
00411       if( cArraySize == 0 )return MATCH_ERROR_ARRAY_SHORT;
00412       if( cbBufferSize < 1 )return MATCH_ERROR_BUFFER_SHORT; /* we have at least one character */
00413       /* check that the first character matches the joker */
00414       cA = *pszString;
00415       if( !fCase && islower(cA) )cA = toupper(cA);
00416       if( ! JokerMatch(set,cA) )return MATCH_ERROR_SUCCESS;
00417 
00418       /* handle the first character that matched the joker */
00419       *ParameterArray = pszBuffer;
00420       *pszBuffer++ = *pszString++;
00421       cbString--;
00422       cbBufferSize--;
00423       *pcbParameterArray = 1; /* the first character is put into the ParameterArray */
00424       //if( ! cbBufferSize )return STRING_MATCH_BUFFER_SHORT;
00425       while( (ErrorCode=match_match(pszPattern+1,
00426                                     cbPattern-1,
00427                                     pszString,
00428                                     cbString,
00429                                     ParameterArray+1,
00430                                     pcbParameterArray+1,
00431                                     pszBuffer,             /* while there is no error and does not match */
00432                                     cArraySize-1,
00433                                     cbBufferSize,
00434                                     fCase,
00435                                     pThisMatchSets,
00436                                     iResult)
00437              ) == MATCH_ERROR_SUCCESS
00438                  &&
00439              !*iResult ){
00440         if( ! cbString )return MATCH_ERROR_SUCCESS;
00441         cA = *pszString;
00442         if( !fCase && islower(cA) )cA = toupper(cA);
00443         if( ! JokerMatch(set,cA) )return MATCH_ERROR_SUCCESS;
00444         *pszBuffer++ = *pszString++;
00445         cbBufferSize --;
00446         cbString--;
00447         (*pcbParameterArray)++;
00448         if( ! cbBufferSize )return MATCH_ERROR_BUFFER_SHORT;
00449         }
00450       *iResult = 1;
00451       return MATCH_ERROR_SUCCESS;
00452       }
00453 
00454     /* ~x is just x no matter what x is */
00455     if( *pszPattern == ESCAPE_CHARACTER ){
00456       pszPattern ++;
00457       cbPattern--;
00458       if( ! cbPattern )return MATCH_ERROR_SYNTAX_ERROR;
00459 
00460       if( ! fCase ){
00461         cA = *pszPattern;
00462         cB = *pszString;
00463         if( islower(cA) )cA = toupper(cA);
00464         if( islower(cB) )cB = toupper(cB);
00465         if( cA != cB )return MATCH_ERROR_SUCCESS;
00466         }else{
00467         if( *pszPattern != *pszString )return MATCH_ERROR_SUCCESS;
00468         }
00469       }else{
00470 
00471       if( set=SingleJokerSet(pThisMatchSets,*pszPattern) ){
00472         cA = *pszString;
00473         if( !fCase && islower(cA) )cA = toupper(cA);
00474         if( ! JokerMatch(set,cA) )return MATCH_ERROR_SUCCESS;
00475         *ParameterArray++ = pszBuffer;
00476         *pszBuffer++ = *pszString;
00477         cbBufferSize--;
00478         *pcbParameterArray++ = 1;
00479         }
00480       else if( *pszPattern == ' ' ){
00481         if( ! isspace(*pszString) )return MATCH_ERROR_SUCCESS;
00482         while( cbString && isspace( *pszString ) ){
00483           pszString ++;
00484           cbString --;
00485           }
00486         pszString--;
00487         cbString++;
00488         }else{
00489         /* Normal character. */
00490         if( ! fCase ){
00491           cA = *pszPattern;
00492           cB = *pszString;
00493           if( islower(cA) )cA = toupper(cA);
00494           if( islower(cB) )cB = toupper(cB);
00495           if( cA != cB )return MATCH_ERROR_SUCCESS;
00496           }else{
00497           if( *pszPattern != *pszString )return MATCH_ERROR_SUCCESS;
00498           }
00499         }
00500       }
00501     pszPattern++; pszString++;
00502     cbPattern--; cbString--;
00503     }/* end of 'while(1)' */
00504   }
00505 
00506 /*POD
00507 =H count
00508 @c Count the joker characters in a pattern
00509 
00510 This function counts the number of jokers in the string and returns it.
00511 This function should be used to calculate the safe length of the pszBuffer
00512 given as a parameter to match.
00513 /*FUNCTION*/
00514 int match_count(char *pszPattern,
00515                 unsigned long cbPattern
00516   ){
00517 /*noverbatim
00518 CUT*/
00519   int iCounter = 0;
00520 
00521   while( cbPattern ){
00522     if( match_index(*pszPattern) )iCounter++;
00523     if( *pszPattern == ESCAPE_CHARACTER ){
00524       pszPattern++;
00525       cbPattern--;
00526       if( ! cbPattern )return iCounter;
00527       }
00528     pszPattern++;
00529     cbPattern--;
00530     }
00531   return iCounter;
00532   }
00533 
00534 /*POD
00535 =H parameter
00536 @c Fill parameters into format string
00537 
00538 This function takes a format string and a string array and
00539 copies the format string replacing T<$0>, T<$1> ... T<$n> values with
00540 the appropriate string values given in the array pointed by
00541 ParameterArray.
00542 
00543 RETURN VALUE:
00544 
00545 The function returns zero if no error occures and returns an error code
00546 in case some of the memory buffer does not have enough space or invalid
00547 parameter is referenced.
00548 
00549 PARAMETERS:
00550 T<pszFormat> IN
00551 The format string containing the $i placeholders.
00552 
00553 --
00554 
00555 T<cbFormat> IN
00556 The number of characters in the format string
00557 
00558 --
00559 
00560 T<ParameterArray> IN
00561 string array so that T<ParameterArray[i]> is to be inserted in place of the T<$i> placeholders
00562 
00563 --
00564 
00565 T<pcbParameterArray> IN
00566 array of T<unsigned long> values. T<pcbParameterArray[i]> gives the length of the i-th string parameter.
00567 
00568 --
00569 
00570 T<pszBuffer> OUT
00571 buffer to put the result
00572 
00573 --
00574 
00575 T<cArraySize> IN
00576 Number of parameters given in the ParameterArray
00577 
00578 --
00579 
00580 T<pcbBufferSize> IN/OUT
00581 Available bytes in buffer pointed by T<pszBuffer>. Upon return it contains the number of characters
00582 that were placed in the buffer.
00583 
00584 --
00585 
00586 NOTE:
00587 
00588 If the function returns non-zero (error code) none of the output
00589 variables can be reliably used.
00590 /*FUNCTION*/
00591 int match_parameter(char *pszFormat,
00592                     unsigned long cbFormat,
00593                     char **ParameterArray,
00594                     unsigned long *pcbParameterArray,
00595                     char *pszBuffer,
00596                     int cArraySize,
00597                     unsigned long *pcbBufferSize
00598   ){
00599 /*noverbatim
00600 CUT*/
00601   int index;
00602   char *s;
00603   unsigned long ulParamSize,ulResultSize;
00604 
00605   ulResultSize = 0;
00606   while( cbFormat ){
00607     if( *pszFormat == '$' ){
00608 
00609       /***            CONVERT $$ to $            ***/
00610       /***                                       ***/
00611       pszFormat++;
00612       cbFormat --;
00613       if( cbFormat && *pszFormat == '$' ){/* $$ is converted to single $ */
00614         *pszBuffer++ = *pszFormat++;
00615         cbFormat--;
00616         (*pcbBufferSize)--;
00617         ulResultSize;
00618         if( *pcbBufferSize < 1 )return MATCH_ERROR_BUFFER_SHORT;
00619 
00620         }else{
00621 
00622       /***            CONVERT $n to parameter    ***/
00623       /***                                       ***/
00624         if( cbFormat && isdigit( *pszFormat ) ){
00625           index = 0;
00626           while( cbFormat && isdigit( *pszFormat ) ){
00627             index = 10*index + *pszFormat - '0';
00628             pszFormat++;
00629             cbFormat--;
00630             }
00631 /*          if( index == 0 )return MATCH_ERROR_INDEX_OUT_OF_RANGE;
00632             index --; /* convert $i to zero based */
00633           if( index >= cArraySize )return MATCH_ERROR_INDEX_OUT_OF_RANGE;
00634           s = ParameterArray[index];
00635           ulParamSize = pcbParameterArray[index];
00636           while( ulParamSize ){
00637             if( *pcbBufferSize < 1 )return MATCH_ERROR_BUFFER_SHORT;
00638             *pszBuffer++ = *s++;
00639             (*pcbBufferSize)--;
00640             ulResultSize++;
00641             ulParamSize--;
00642             }
00643           }else{
00644 
00645       /***            $ w/o number is just a $   ***/
00646       /***                                       ***/
00647           *pszBuffer++ = '$';
00648           (*pcbBufferSize)--;
00649           ulResultSize++;
00650           if( *pcbBufferSize < 1 )return MATCH_ERROR_BUFFER_SHORT;
00651           }
00652         }
00653 
00654       }else{
00655 
00656       /***            copy character             ***/
00657       /***                                       ***/
00658       if( *pcbBufferSize < 1 )return MATCH_ERROR_BUFFER_SHORT;
00659       *pszBuffer++ = *pszFormat++;
00660       (*pcbBufferSize)--;
00661       ulResultSize++;
00662       cbFormat--;
00663       }
00664     }
00665   *pcbBufferSize = ulResultSize;
00666   return MATCH_ERROR_SUCCESS;
00667   }
00668 
00669 /*POD
00670 =H size
00671 @c Calculate the neccessary buffer size
00672 
00673 Calculate the size of the output. The IN/OUT parameter T<cbBufferSize>
00674 is increased by the number of needed characters.
00675 
00676 The return value is zero if no error occured or the error code.
00677 
00678 NOTE: cbBuffer size should be initialized to 0 if you want to get the
00679 size of the buffer needed.
00680 /*FUNCTION*/
00681 int match_size(char *pszFormat,
00682                unsigned long cbFormat,
00683                unsigned long *pcbParameterArray,
00684                int cArraySize,
00685                int *cbBufferSize
00686   ){
00687 /*noverbatim
00688 CUT*/
00689   int index;
00690 
00691   while( cbFormat ){
00692     if( *pszFormat == '$' ){
00693       pszFormat++;
00694       cbFormat--;
00695       if( cbFormat && *pszFormat == '$' ){/* $$ is converted to single $ */
00696         pszFormat++;
00697         cbFormat--;
00698         (*cbBufferSize)++;
00699 
00700         }else{
00701 
00702       /***            CONVERT $n to parameter    ***/
00703       /***                                       ***/
00704         if( cbFormat && isdigit( *pszFormat ) ){
00705           index = 0;
00706           while( cbFormat && isdigit( *pszFormat ) ){
00707             index = 10*index + *pszFormat - '0';
00708             pszFormat++;
00709             cbFormat--;
00710             }
00711 /*          if( index == 0 )return MATCH_ERROR_INDEX_OUT_OF_RANGE;
00712           index--;*/
00713           if( index >= cArraySize )return MATCH_ERROR_INDEX_OUT_OF_RANGE;
00714           (*cbBufferSize) += pcbParameterArray[index];
00715           }else{
00716 
00717       /***            $ w/o number is just a $   ***/
00718       /***                                       ***/
00719           cbBufferSize ++;
00720           }
00721         }
00722 
00723       }else{
00724 
00725       /***            copy character             ***/
00726       /***                                       ***/
00727       pszFormat++;
00728       cbFormat--;
00729       (*cbBufferSize)++;
00730       }
00731     }
00732   return MATCH_ERROR_SUCCESS;
00733   }
00734 

Generated on Sun Mar 12 23:56:31 2006 for ScriptBasic by  doxygen 1.4.6-NO