PRE-PROPOSAL: Source and Encoding keyword

Reinier Zwitserloot reinier at zwitserloot.com
Fri Mar 6 22:03:25 PST 2009


We have written up a proposal for adding a 'source' and 'encoding'  
keyword (alternatives to the -source and -encoding keywords on the  
command line; they work pretty much just as you expect). The keywords  
are context sensitive and must both appear before anything else other  
than comments to be parsed. In case the benefit isn't obvious: It is a  
great help when you are trying to port a big project to a new source  
language compatibility. Leaving half your sourcebase in v1.6 and the  
other half in v1.7 is pretty much impossible today, it's all-or- 
nothing. It should also be a much nicer solution to the 'assert in  
v1.4' dilemma, which I guess is going to happen to v1.7 as well, given  
that 'module' is most likely going to become a keyword. Finally, it  
makes java files a lot more portable; you no longer run into your  
strings looking weird when you move your Windows-1252 codefile java  
source to a mac, for example.

Before we finish it though, some open questions we'd like some  
feedback on:

A) Technically, starting a file with "source 1.4" is obviously silly;  
javac v1.4 doesn't know about the source keyword and would thus fail  
immediately. However, practically, its still useful. Example: if  
you've mostly converted a GWT project to GWT 1.5 (which uses java 1.5  
syntax), but have a few files remaining on GWT v1.4 (which uses java  
1.4 syntax), then tossing a "source 1.4;" in those older files  
eliminates all the generics warnings and serves as a reminder that you  
should still convert those at some point. However, it isn't -actually-  
compatible with a real javac 1.4. We're leaning to making "source  
1.6;"  (and below) legal even when using a javac v1.7 or above, but  
perhaps that's a bridge too far? We could go with magic comments but  
that seems like a very bad solution.

also:

Encoding is rather a hairy issue; javac will need to read the file to  
find the encoding, but to read a file, it needs to know about  
encoding! Fortunately, *every single* popular encoding on wikipedia's  
popular encoding list at:

http://en.wikipedia.org/wiki/Character_encoding#Popular_character_encodings

will encode "encoding own-name-in-that-encoding;" the same as ASCII  
would, except for KOI-7 and UTF-7, (both 7 bit encodings that I doubt  
anyone ever uses to program java).

Therefore, the proposal includes the following strategy to find the  
encoding statement in a java source file without knowing the encoding  
beforehand:

An entirely separate parser (the encoding parser) is run repeatedly  
until the right encoding is found. First it'll decode the input with  
ISO-8859-1. If that doesn't work, UTF-16 (assume BE if no BOM, as per  
the java standard), then as UTF-32 (BE if no BOM), then the current  
behaviour (-encoding parameter's value if any, otherwise platform  
default encoding). This separate parser works as follows:

1. Ignore any comments and whitespace.
3. Ignore the pattern (regexp-like-syntax, ): source\s+[^\s]+\s*; - if  
that pattern matches partially but is not correctly completed, that  
parser run exits without finding an encoding, immediately.
4. Find the pattern: encoding\s+([^\s]+)\s*; - if that pattern matches  
partially but is not correctly completed, that parser run exists  
without finding an encoding, immediately. If it does complete, the  
parser also exists immediately and returns the captured value.
5. If it finds anything else, stop immediately, returning no encoding  
found.

Once it's found something, the 'real' java parser will run using the  
found encoding (this overrides any -encoding on the command line).  
Note that the encoding parser stops quickly; For example, if it finds  
a stray \0 or e.g. the letter 'i' (perhaps the first letter of an  
import statement), it'll stop immediately.

If an encoding is encountered that was not found during the standard  
decoding strategy (ISO-8859-1, UTF-16, UTF-32), but worked only due to  
a platform default/command line encoding param, (e.g. a platform that  
defaults to UTF-16LE without a byte order mark) a warning explaining  
that the encoding statement isn't doing anything is generated. Of  
course, if the encoding doesn't match itself, you get an error  
(putting "encoding UTF-16;" into a UTF-8 encoded file for example). If  
there is no encoding statement, the 'real' java parser does what it  
does now: Use the -encoding parameter of javac, and if that wasn't  
present, the platform default.

However, there is 1 major and 1 minor problem with this approach:

B) This means javac will need to read every source file many times to  
compile it.

Worst case (no encoding keyword): 5 times.
Standard case if an encoding keyword: 2 times (3 times if UTF-16).

Fortunately all runs should stop quickly, due to the encoding parser's  
penchant to quit very early. Javacs out there will either stuff the  
entire source file into memory, or if not, disk cache should take care  
of it, but we can't prove beyond a doubt that this repeated parsing  
will have no significant impact on compile time. Is this a  
showstopper? Is the need to include a new (but small) parser into  
javac a showstopper?

C) Certain character sets, such as ISO-2022, can make the encoding  
statement unreadable with the standard strategy if a comment including  
non-ASCII characters precedes the encoding statement. These situations  
are very rare (in fact, I haven't managed to find an example), so is  
it okay to just ignore this issue? If you add the encoding statement  
after a bunch of comments that make it invisible, and then compile it  
with the right -encoding parameter, you WILL get a warning that the  
encoding statement isn't going to help a javac on another platform /  
without that encoding parameter to figure it out, so you just get the  
current status quo: your source file won't compile without an explicit  
-encoding parameter (or if that happens to be the platform default).  
Should this be mentioned in the proposal? Should the compiler (and the  
proposal) put effort into generating a useful warning message, such as  
figuring out if it WOULD parse correctly if the encoding statement is  
at the very top of the source file, vs. suggesting to recode in UTF-8?

and a final dilemma:

D) Should we separate the proposals for source and encoding keywords?  
The source keyword is more useful and a lot simpler overall than the  
encoding keyword, but they do sort of go together.

--Reinier Zwitserloot and Roel Spilker


More information about the coin-dev mailing list