Commit 5804a9a introduced a bug where having the foldtabs option disabled (normal) prevented optimizations of functions. Fix it for good (hopefully). While on it, rename the nofoldtabs option to warntabs, making it default, and use it to disable a warning when there are tabs in a string.
If the last line of the file didn't end in LF, and an error was reported right in that line, two characters would be missing from that line in the output. Fixed.
Changed my mind. This looks saner. Now, if the 'default:' label is missing, an error will be thrown by default. It has to be explicitly disabled if normal C-like behaviour is desired (namely to jump to the 'break' label if no condition is met).
In the absence of a 'default' label within a switch, FS falls through to the first CASE label (or to the code before the first CASE if there's any).
This commit adds an option, active by default for FS compatibility, that mimics this broken behaviour, as well as a warning in case the 'default' label is absent, which also triggers another warning when the option is active.
For example, this script reported the type mismatch in default:
key k=0;
default{timer(){}}
Now it's reported at the semicolon, which is as early as it can be identified and much more meaningful.
When a function folds to a string that contains a tab, e.g. llUnescapeURL("%09"), or to a list that contains a string that contains a tab, a warning is emitted unless the foldtabs option (which forces the optimization) is used. This option allows to quiet the warning without forcing the optimization.
Resolving some constant function calls may generate tabs, e.g. llUnescapeURL("%09"). That can't be pasted into a script, and a warning is emitted. The warning text was misleading, making one think that something went wrong when all that happened is that an optimization couldn't be applied. Rewrite the text of the warning to be clearer about what the problem is.
Identifiers can be equal if they belong to different syntactic scopes. That will allow better reuse and less creation of new identifiers, most notably as function and event parameter names.
The implementation would require a stack of counters where the current value is pushed when entering a new scope, and popped when exiting, rather than using a single counter for the whole program.