diff --git a/refdoc/chapters/special_functions.xml b/refdoc/chapters/special_functions.xml index bb991e37463b5dd84ee4f0db3dcd31757bbd024f..c1084a400927b11e92bb423855ed554b0e86a7e0 100644 --- a/refdoc/chapters/special_functions.xml +++ b/refdoc/chapters/special_functions.xml @@ -11,88 +11,7 @@ as special functions.</p> <p>Sscanf may look exactly like a normal function, but normal functions can not set the variables you send to it. The purpose of sscanf is to match one string against a format string and place the matching results -into a list of variables. The syntax looks like this:</p> - -<example> -int sscanf(string str, string fmt, lvalue ...) -</example> - -<p>The string <tt>str</tt> will be matched against the format string <tt>fmt</tt>. -<tt>fmt</tt> can contain strings -separated by special matching directives like %d,%s,%c and %f. Every % corresponds to one <tt>lvalue</tt>. -An lvalue is the name of a variable, a name of a local variable, an index -in an array, mapping or object. It is because of these lvalues that sscanf -can not be implemented as a normal function.</p> - -<p> -Whenever a percent character is found in the format string, a match is performed according -to the following table. -</p> - -<matrix> -<r><c>%b</c><c>Reads a binary integer ("0101" makes 5).</c></r> -<r><c>%d</c><c>Reads a decimal integer ("0101" makes 101).</c></r> -<r><c>%o</c><c>Reads an octal integer ("0101" makes 65).</c></r> -<r><c>%x</c><c>Reads a hexadecimal integer ("0101" makes 257).</c></r> -<r><c>%D</c><c>Reads an integer that is either octal (leading zero), -hexadecimal (leading 0x) or decimal. ("0101" makes 65).</c></r> -<r><c>%f</c><c>Reads a float ("0101" makes 101.0).</c></r> -<r><c>%c</c><c>Matches one char and returns it as an integer -("0101" makes 48, or '0', leaving "101").</c></r> -<r><c>%2c</c><c>Matches two chars and returns them as an integer -(short; "0101" makes 12337, leaving "01").</c></r> -<r><c>%4F</c><c>Matches four chars and returns them as a float (IEEE single precision).</c></r> -<r><c>%8F</c><c>Matches eigth chars and returns them as a float (IEEE double precision).</c></r> -<r><c>%s</c><c>Reads a string. If followed by %d, %s will - only read non-numerical characters. If followed by a %[], %s will only read - characters not present in the set. If followed by normal text, %s will match - all characters up to but not including the first occurrence of that text.</c></r> -<r><c>%5s</c><c>Reads a string of 5 characters (5 can of course be any number).</c></r> -<r><c>%[set]</c><c>Matches a string containing a given set of characters (those given inside the brackets). - %[^set] means any character except those inside brackets. Ranges of characters can be defined by using a - minus character between the first and the last character to be included in the range. Example: %[0-9H] means any number or 'H'. - Note that sets that includes the character - must have it first in the brackets to avoid having a range defined.</c></r> -<r><c>%{format%}</c><c>Repeatedly matches 'format' as many times as possible and assigns an array of arrays with the results to the lvalue.</c></r> -<r><c>%%</c><c>Match a single percent character.</c></r> -<r><c>%O</c><c>Match a Pike constant, such as string or integer (currently only integer, string and character constant is functional)</c></r> -</matrix> - -<p>If a * is put between the percent and the operator, the operator -will only match its argument, not assign any variables.</p> - -<p>Sscanf does not use backtracking. Sscanf simply looks at the format string -up to the next % and tries to match that with the string. It then proceeds -to look at the next part. If a part does not match, sscanf immediately -returns how many % were matched. If this happens, the lvalues for % that -were not matched will not be changed.</p> - -Let's look at a couple of examples. -<example> -// a will be assigned "oo" and 1 will be returned -sscanf("foo", "f%s", a); - -// a will be 4711 and b will be "bar", 2 will be returned -sscanf("4711bar", "%d%s", a, b); - -// a will be 4711, 2 will be returned -sscanf("bar4711foo", "%*s%d", a); - -// a will become "test" -sscanf(" \t test", "%*[ \t]%s", a); - -// Remove "the " from the beginning of a string -// If 'str' does not begin with "the " it will not be changed -sscanf(str, "the %s", str); -</example> - -<p>It is also possible to declare a variable directly in the sscanf call. -Another reason for sscanf not to be an ordinary function.</p> - -<example> -sscanf("abc def", "%s %s", string a, string b); -</example> - -<!-- Seealso sprintf, array_sscanf --> +into a list of variables. See <ref>sscanf</ref> for full documentation.</p> </section> diff --git a/src/opcodes.c b/src/opcodes.c index bab6a447df5f403efd7bc93d6e4df1640d9080d9..5bb172bb39d32d91fdd8b94521448381dfc04a7b 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: opcodes.c,v 1.152 2003/09/10 09:42:05 grubba Exp $ +|| $Id: opcodes.c,v 1.153 2003/09/11 12:21:59 jhs Exp $ */ #include "global.h" @@ -30,7 +30,7 @@ #define sp Pike_sp -RCSID("$Id: opcodes.c,v 1.152 2003/09/10 09:42:05 grubba Exp $"); +RCSID("$Id: opcodes.c,v 1.153 2003/09/11 12:21:59 jhs Exp $"); void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind) { @@ -2214,22 +2214,133 @@ static INT32 low_sscanf(struct pike_string *data, struct pike_string *format) /*! @decl int sscanf(string data, string format, mixed ... lvalues) *! - *! The purpose of sscanf is to match one string against a format string and - *! place the matching results into a list of variables. The list of @[lvalues] - *! are destructively modified (which is only possible because sscanf really is - *! an opcode, rather than a pike function) with the values extracted from the - *! @[data] according to the @[format] specification. Only the variables up to - *! the last matching directive of the format string are touched. + *! The purpose of sscanf is to match a string @[data] against a @[format] + *! string and place the matching results into a list of variables. The list + *! of @[lvalues] are destructively modified (which is only possible because + *! sscanf really is an opcode, rather than a pike function) with the values + *! extracted from the @[data] according to the @[format] specification. Only + *! the variables up to the last matching directive of the format string are + *! touched. *! - *! Refer to the @[chapter::sscanf] chapter for the complete list of directives - *! sscanf understands. + *! The @[format] string can contain strings separated by special matching + *! directives like @tt{%d@}, @tt{%s@} @tt{%c@} and @tt{%f@}. Every such + *! directive corresponds to one of the @[lvalues], in order they are listed. + *! An lvalue is the name of a variable, a name of a local variable, an index + *! in an array, mapping or object. It is because of these lvalues that sscanf + *! can not be implemented as a normal function. + *! + *! Whenever a percent character is found in the format string, a match is + *! performed, according to which operator and modifiers follow it: + *! + *! @string + *! @value "%b" + *! Reads a binary integer ("0101" makes 5) + *! @value "%d" + *! Reads a decimal integer ("0101" makes 101). + *! @value "%o" + *! Reads an octal integer ("0101" makes 65). + *! @value "%x" + *! Reads a hexadecimal integer ("0101" makes 257). + *! @value "%D" + *! Reads an integer that is either octal (leading zero), + *! hexadecimal (leading 0x) or decimal. ("0101" makes 65). + *! @value "%c" + *! Reads one character and returns it as an integer + *! ("0101" makes 48, or '0', leaving "101" for later directives). + *! Using the field width and endianness modifiers, you can decode + *! integers of any size and endianness. + *! @value "%f" + *! Reads a float ("0101" makes 101.0). + *! @value "%F" + *! Reads a float encoded according to the IEEE single precision binary + *! format ("0101" makes 6.45e-10, approximately). Given a field width + *! modifier of 8 (4 is the default), the data will be decoded according + *! to the IEEE double precision binary format instead. (You will however + *! still get a float, unless your pike was compiled with the configure + *! argument @tt{--with-double-precision@}.) + *! @value "%s" + *! Reads a string. If followed by %d, %s will only read non-numerical + *! characters. If followed by a %[], %s will only read characters not + *! present in the set. If followed by normal text, %s will match all + *! characters up to but not including the first occurrence of that text. + *! @value "%[set]" + *! Matches a string containing a given set of characters (those given + *! inside the brackets). %[^set] means any character except those inside + *! brackets. Ranges of characters can be defined by using a minus + *! character between the first and the last character to be included in + *! the range. Example: %[0-9H] means any number or 'H'. Note that sets + *! that includes the character - must have it first in the brackets to + *! avoid having a range defined. Sets including the character ']' must + *! list this first (even before -) too, for natural reasons. + *! @value "%{format%}" + *! Repeatedly matches 'format' as many times as possible and assigns an + *! array of arrays with the results to the lvalue. + *! @value "%O" + *! Match a Pike constant, such as string or integer (currently only + *! integer, string and character constants are functional). + *! @value "%%" + *! Match a single percent character (hence this is how you quote the % + *! character to just match, and not start an lvalue matcher directive). + *! @endstring + *! + *! Similar to @[sprintf], you may supply modifiers between the % character + *! and the operator, to slightly change its behaviour from the default: + *! + *! @string + *! @value "*" + *! The operator will only match its argument, without assigning any + *! variable. + *! @value "number" + *! You may define a field width by supplying a numeric modifier. This + *! means that the format should match that number of characters in the + *! input data; be it a @i{number@} characters long string, integer or + *! otherwise ("0101" using the format %2c would read an unsigned short + *! 12337, leaving the final "01" for later operators, for instance). + *! @value "-" + *! Supplying a minus sign toggles the decoding to read the data encoded + *! in little-endian byte order, rather than the default network + *! (big-endian) byte order. + *! @value "+" + *! Interpret the data as a signed entity. In other words, "%+1c" will + *! read "\0xFF" as -1 instead of 255, as "%1c" would have. + *! @endstring + *! + *! @note + *! Sscanf does not use backtracking. Sscanf simply looks at the format string + *! up to the next % and tries to match that with the string. It then proceeds + *! to look at the next part. If a part does not match, sscanf immediately + *! returns how many % were matched. If this happens, the lvalues for % that + *! were not matched will not be changed. + *! + *! @example + *! // a will be assigned "oo" and 1 will be returned + *! sscanf("foo", "f%s", a); + *! + *! // a will be 4711 and b will be "bar", 2 will be returned + *! sscanf("4711bar", "%d%s", a, b); + *! + *! // a will be 4711, 2 will be returned + *! sscanf("bar4711foo", "%*s%d", a); + *! + *! // a will become "test", 2 will be returned + *! sscanf(" \t test", "%*[ \t]%s", a); + *! + *! // Remove "the " from the beginning of a string + *! // If 'str' does not begin with "the " it will not be changed + *! sscanf(str, "the %s", str); + *! + *! // It is also possible to declare a variable directly in the sscanf call; + *! // another reason for sscanf not to be an ordinary function: + *! + *! sscanf("abc def", "%s %s", string a, string b); *! *! @returns *! The number of directives matched in the format string. Note that a string - *! directive (%s or %[]) always counts as a match, even when matching the - *! empty string. + *! directive (%s or %[]) counts as a match even when matching just the empty + *! string (which either may do). *! @seealso - *! @[array_sscanf()], @[chapter::sscanf] + *! @[sprintf], @[array_sscanf] + * @[parse_format] */ void o_sscanf(INT32 args) { @@ -2258,7 +2369,7 @@ void o_sscanf(INT32 args) int nonblock; if((nonblock=query_nonblocking(2))) set_nonblocking(2,0); - + fprintf(stderr,"- Matches: %ld\n",(long)i); if(nonblock) set_nonblocking(2,1);