Skip to content

Commit 3dff129

Browse files
author
Y_Less
committed
Improve some errors caused by using sscanf before including it.
1 parent 90f0e29 commit 3dff129

File tree

2 files changed

+61
-22
lines changed

2 files changed

+61
-22
lines changed

README.md

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ This will fail because `"hello"` is not a whole number (or indeed any type of nu
114114
* 11.35 [sscanf error: SSCANF_Leave has incorrect parameters.](#sscanf-error-sscanf_leave-has-incorrect-parameters)
115115
* 11.36 [sscanf error: SSCANF_SetPlayerName has incorrect parameters.](#sscanf-error-sscanf_setplayername-has-incorrect-parameters)
116116
* 11.37 [sscanf error: SSCANF_IsConnected has incorrect parameters.](#sscanf-error-sscanf_isconnected-has-incorrect-parameters)
117+
* 11.38 [fatal error 111: user error: sscanf already defined, or used before inclusion.](#fatal-error-111-user-error-sscanf-already-defined-or-used-before-inclusion)
118+
* 11.39 [error 004: function "sscanf" is not implemented](#error-004-function-sscanf-is-not-implemented)
119+
* 11.40 [error 004: function "sscanf" is not implemented - include <sscanf2> first.](#error-004-function-sscanf-is-not-implemented---include-sscanf2-first)
117120
* 12 [Future Plans](#future-plans)
118121
* 12.1 [Reserved Specifiers](#reserved-specifiers)
119122
* 12.2 [Alternates](#alternates)
@@ -1620,6 +1623,53 @@ A `k` specifier has been used, but the corresponding function could not be found
16201623

16211624
You edited something in the sscanf2 include - undo it or redownload it.
16221625

1626+
## `fatal error 111: user error: sscanf already defined, or used before inclusion.`
1627+
1628+
There are two ways to trigger this: The first is to have another copy of `sscanf` defined before you include the file. This used to be the only known way to trigger this error, so the error said:
1629+
1630+
> `sscanf (possibly the PAWN version) already defined.`
1631+
1632+
However, there is a second way to trigger it - using `sscanf` before including it. This used to be possible, but isn't any more as `sscanf` is now a macro that inserts additional data in to the call. So this will fail:
1633+
1634+
```pawn
1635+
#include <a_samp>
1636+
1637+
main()
1638+
{
1639+
sscanf("hi", "hi");sscanf (possibly the PAWN version) already defined.
1640+
}
1641+
1642+
#include <sscanf2>
1643+
```
1644+
1645+
To fix this, just include `<sscanf2>` before you use `sscanf`.
1646+
1647+
## `error 004: function "sscanf" is not implemented`
1648+
## `error 004: function "sscanf" is not implemented - include <sscanf2> first.`
1649+
1650+
These are the same error, the only difference being which compiler you use. Obviously the newer compiler gives the more useful (second) error which tells you how to solve this problem. Similar to [the previous error](#fatal-error-111-user-error-sscanf-already-defined-or-used-before-inclusion) this happens when `sscanf` is used before being included, but in a slightly different way:
1651+
1652+
```pawn
1653+
#include <a_samp>
1654+
1655+
main()
1656+
{
1657+
#if defined sscanf
1658+
sscanf("hi", "hi");
1659+
#endif
1660+
}
1661+
1662+
#include <sscanf2>
1663+
```
1664+
1665+
This code tries to be slightly clever, but fails. The correct way to check for sscanf inclusion is:
1666+
1667+
```pawn
1668+
#if !defined _INC_SSCANF
1669+
#error You need sscanf
1670+
#endif
1671+
```
1672+
16231673
## Future Plans
16241674

16251675
### Reserved Specifiers
@@ -1640,7 +1690,7 @@ jtvwy
16401690
* `y` is for "YID" - the YSI user ID. Don't use YSI? Tough.
16411691
* `v` I figure is for something to do with varargs, similar to `a` but for extra parameters.
16421692
* `j` no idea yet.
1643-
* `w` is the most important one to reserve - it is for extended specifiers. Since there are so few left it is important to establish future compatibility. Thus `w` is a prefix that indicates that the following specifier has an alternate meaning. So `i` is "integer" but `wi` is something else entirely (don't know what yet). This scheme does recurse endlessly so `wwi` and `wwwwwi` are also different. In this way we will never run out and can start adding support for more obscure items like iterators and jagged arrays (the original idea for `j`).
1693+
* `w` is the most important one to reserve - it is for extended specifiers. Since there are so few left it is important to establish future compatibility. Thus `w` is a prefix that indicates that the following specifier has an alternate meaning. So `i` is "integer" but `wi` is something else entirely (don't know what yet). This scheme does recurse endlessly so `wwi` and `wwwwwi` are also different. In this way we will never run out and can start adding support for more obscure items like iterators and jagged arrays (the original idea for `j`). There's also a suggestion for this as `words` - `w<5>` for five words, but I think that makes sense as an extension to `s`.
16441694

16451695
### Alternates
16461696

sscanf2.inc

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,7 @@ static stock SSCANF_VERSION_STRING[] = #SSCANF_VERSION_MAJOR "." #SSCANF_VERSION
181181
*
182182
* </remarks>
183183
*/
184-
static stock BCD(number)
185-
{
186-
return number;
187-
}
184+
forward BCD(number);
188185

189186
#define BCD(%0) (_:MORE_BCD:NO_MORE_BCD:%0.$0)
190187
#define MORE_BCD:NO_MORE_BCD:%0.%1$%2) MORE_BCD:NO_MORE_BCD:%1$(%2) << 8 | DO_BCD(%0))
@@ -222,11 +219,11 @@ stock const SSCANF_VERSION_BCD = SSCANF_VERSION;
222219
#define sscanf_%0\32; sscanf_
223220
#define SSCANF:%0(%1) forward sscanf_%0(%1);public sscanf_%0(%1)
224221

225-
// The check for `SSCANF_Option` ensures that this is the first compiler pass
226-
// and thus the check for `sscanf` only finds earlier definitions not our
227-
// later fake definition made purely for documentation purposes.
228-
#if defined sscanf && !defined SSCANF_Option
229-
#error sscanf (possibly the PAWN version) already defined.
222+
// The check for `SSCANF_GetClosestString` ensures that this is the first
223+
// compiler pass and thus the check for `sscanf` only finds earlier definitions
224+
// not our later fake definition made purely for documentation purposes.
225+
#if defined sscanf && !defined SSCANF_GetClosestString
226+
#error sscanf already defined, or used before inclusion.
230227
#endif
231228

232229
/**
@@ -391,10 +388,7 @@ native SSCANF_SetOption__(const name[], value) = SSCANF_Option;
391388
* value.
392389
* </remarks>
393390
*/
394-
static stock SSCANF_Option(const name[], value = -1)
395-
{
396-
return value;
397-
}
391+
forward SSCANF_Option(const name[], value = -1);
398392

399393
#define SSCANF_Option SSCANF_GetOption__
400394
#define SSCANF_GetOption__(%0,%1) SSCANF_SetOption__(%0,%1)
@@ -478,10 +472,8 @@ static stock SSCANF_Version(version[] = "", size = sizeof (version))
478472
* well for improved error messages.
479473
* </remarks>
480474
*/
481-
stock sscanf(const data[], const format[], {Float, _}:...)
482-
{
483-
return 0;
484-
}
475+
#pragma deprecated - include <sscanf2> first.
476+
forward sscanf(const data[], const format[], {Float, _}:...);
485477

486478
#if defined __PawnBuild
487479
#define sscanf( SSCANF__(__file,__line,
@@ -506,10 +498,7 @@ stock sscanf(const data[], const format[], {Float, _}:...)
506498
* number as well for improved error messages.
507499
* </remarks>
508500
*/
509-
stock unformat(const data[], const format[], {Float, _}:...)
510-
{
511-
return 0;
512-
}
501+
forward unformat(const data[], const format[], {Float, _}:...);
513502

514503
#if defined __PawnBuild
515504
#define unformat( SSCANF__(__file,__line,

0 commit comments

Comments
 (0)