Running gpc-20060325 on i486-pc-mingw32 (gcc-3.4.6), I wish to use an "asm" statement and the predefined identifiers "Cardinal" and "ParamCount" in an Extended Pascal program. However, the following program fails to compile:
{$ extended-pascal } {$ enable-keyword asm } {$ enable-predefined-identifier Cardinal } {$ enable-predefined-identifier ParamCount }
program Predefs;
var C : Cardinal; I : integer;
begin asm ('nop'); I := ParamCount; C := 1 end.
With "gpc -c predefs.pas", I get:
predefs.pas:1: warning: compiler directives are a UCSD Pascal extension predefs.pas: In main program: predefs.pas:12: error: `asm' is an extension of Borland Pascal, traditional predefs.pas:12: error: Macintosh Pascal predefs.pas:13: error: `ParamCount' is an extension of Borland Pascal
Note from the above that "Cardinal" is being enabled by the directives, whereas "ParamCount" and "asm" are not.
I get the same results if I specify the compiler switches on the command line (e.g., "--enable-keyword=asm", etc.) instead of within the program. I see the same behavior with gpc-20051116.
Is this a compiler bug, or am I doing something wrong?
-- Dave
J. David Bryan wrote:
Running gpc-20060325 on i486-pc-mingw32 (gcc-3.4.6), I wish to use an "asm" statement and the predefined identifiers "Cardinal" and "ParamCount" in an Extended Pascal program. However, the following program fails to compile:
{$ extended-pascal } {$ enable-keyword asm } {$ enable-predefined-identifier Cardinal } {$ enable-predefined-identifier ParamCount }
program Predefs;
var C : Cardinal; I : integer;
begin asm ('nop'); I := ParamCount; C := 1 end.
With "gpc -c predefs.pas", I get:
predefs.pas:1: warning: compiler directives are a UCSD Pascal extension predefs.pas: In main program: predefs.pas:12: error: `asm' is an extension of Borland Pascal, traditional predefs.pas:12: error: Macintosh Pascal predefs.pas:13: error: `ParamCount' is an extension of Borland Pascal
Note from the above that "Cardinal" is being enabled by the directives, whereas "ParamCount" and "asm" are not.
I get the same results if I specify the compiler switches on the command line (e.g., "--enable-keyword=asm", etc.) instead of within the program. I see the same behavior with gpc-20051116.
Is this a compiler bug, or am I doing something wrong?
1) GPC documentation of "--enable-keyword" probably could be improved. the "--enable-keyword" and "--disable-keyword" are _not_ intended to create a new dialect. Rather, they are intended as a help to avoid conflicts betwen identifiers and keywords: "--disable-keyword" makes sure that a given name is treated as identifier (avoiding a parse error or unwanted interpretation). "--enable-keyword" allows to get back keyword that was previously diabled. Currently there should be little (maybe even no) need to use "--disable-keyword" as intended: the parser is now much better at distinguising identifiers and keywords. "--disable-keyword" also works quite well to _restrict_ available language. However, "--enable-keyword" just causes GPC to recognize given keyword, but otherwise do not influence the accepted language. Since by default all keywords are allowed and dialect choice just rejects constucts outside given dialect, "--enable-keyword" in fact can not enable a new construct -- it can only turn on previously disabled keyword.
2) "--enable-predefined-identifier" is a relatively new addition to GPC. ATM it works like "--enable-keyword": it assigns to an identifer its predefined meaning, but do not affect other checks in the compiler. In particular, builtin routines remain effectively disabled (and "ParamCount" is a routine (function)). "Cardinal" works since it is a type.
I am not sure if we should change what GPC is doing. We probably could remove dialect check for builtin routines, but for keywords things are more tricky: a set of dialects in which a constuct is valid may be smaller then set of dialects in which keywords involved in the constuct are valid -- so we still need dialect checks. Also, a single keyword may be used in multiple constructs (and GPC extensions tends to re-use keywords if possible). So, I am not sure how useful would be ability to enable all constructs involwing given keyword.
On 21 Jul 2006 at 3:51, Waldek Hebisch wrote:
- GPC documentation of "--enable-keyword" probably could be improved.
the "--enable-keyword" and "--disable-keyword" are _not_ intended to create a new dialect.
I agree that the manual is confusing, because it says in Chapter 9:
A dialect option turns off all keywords that do not belong to this dialect. Besides, any keyword can be enabled and disabled with the compiler options '{$enable-keyword}' and '{$disable-keyword}'.
...which, to me, says that a general dialect option may be chosen and then selectively extended or restricted with enable/disable.
Rather, they are intended as a help to avoid conflicts betwen identifiers and keywords....
I understand.
However, "--enable-keyword" just causes GPC to recognize given keyword, but otherwise do not influence the accepted language. Since by default all keywords are allowed and dialect choice just rejects constucts outside given dialect, "--enable-keyword" in fact can not enable a new construct -- it can only turn on previously disabled keyword.
I am confused by this. In test program "fjf733e.pas", we have:
{$enable-keyword pow} {$classic-pascal}
program fjf733e (Output);
begin if 2 pow 3 = 8 then WriteLn ('OK') else WriteLn ('failed') end.
This works, but why does it work? "pow" is an operator, and "asm" is a statement keyword, but why does that matter? It appears to me that this changes the dialect from CP to CP-plus-pow-from-EP. I don't understand why:
{$enable-keyword pow}
works, but:
{$enable-keyword asm}
does not work. Shouldn't the above program give "error: `pow' is an extension of Extended Pascal"?
In particular, builtin routines remain effectively disabled (and "ParamCount" is a routine (function)). "Cardinal" works since it is a type.
This also is confusing. In the presence of a language restriction, some predefined identifiers may be enabled (types), but others (built-in routines) cannot. Some keywords ("pow", "attribute") may be enabled, but others ("asm") cannot.
I am not sure if we should change what GPC is doing.
I believe that gpc should either allow "enable" only if a prior "disable" has been done, or allow "enable" without restriction, or document the specific cases where "enable" is allowed. The first option would be your original intent. The second would be most flexible. The third would at least eliminate the confusion where some "enables" are allowed and others are not.
...for keywords things are more tricky: a set of dialects in which a constuct is valid may be smaller then set of dialects in which keywords involved in the constuct are valid so we still need dialect checks.
Are you thinking of cases such as "packed array" is CP, but "packed 0..3" is not? Or "a and b" is CP, but "a and 1" is not?
So, I am not sure how useful would be ability to enable all constructs involwing given keyword.
The reason I was trying to restrict the dialect and then enable certain keywords and predefined identifiers is that changing the dialect from EP to GP changes the semantics of some EP constructs. For instance, changing to GP means that strings are no longer padded for comparisons, so:
var s : packed array [1..6] of char; [...]
s := 'GPC'; if s = 'GPC' then ...
...fails. Also:
var i, j: integer; [...]
i := 1; j := 2; writeln (i, j);
prints "12". So I cannot simply write EP with a few extensions; I must also remember all of the semantic changes that go along with selecting GP.
There are two alternate ways I can accomplish this:
1. Choose the GP dialect and either program around the semantic changes ("if s = 'GPC ' then") or use compiler directives to restore EP semantics ("{$no-exact-compare-strings}").
2. Choose the EP dialect and bracket each extension with "{$gnu-pascal}" and "{$extended-pascal}".
But if I could choose EP and selectively enable the extensions, it would be simpler, and it would document at the start of the source file exactly what extensions were used.
Thank you for your detailed explanations.
-- Dave
J. David Bryan wrote:
On 21 Jul 2006 at 3:51, Waldek Hebisch wrote:
However, "--enable-keyword" just causes GPC to recognize given keyword, but otherwise do not influence the accepted language. Since by default all keywords are allowed and dialect choice just rejects constucts outside given dialect, "--enable-keyword" in fact can not enable a new construct -- it can only turn on previously disabled keyword.
I am confused by this. In test program "fjf733e.pas", we have:
{$enable-keyword pow} {$classic-pascal}
program fjf733e (Output);
begin if 2 pow 3 = 8 then WriteLn ('OK') else WriteLn ('failed') end.
This works, but why does it work? "pow" is an operator, and "asm" is a statement keyword, but why does that matter? It appears to me that this changes the dialect from CP to CP-plus-pow-from-EP. I don't understand why:
{$enable-keyword pow}
works, but:
{$enable-keyword asm}
does not work. Shouldn't the above program give "error: `pow' is an extension of Extended Pascal"?
To be more precise: "{$enable-keyword asm}" just causes `asm' to be recognized as the keyword. Other checks are unaffected by "enable-keyword". Apparently, for `pow' no more checks is used, by for `asm' an extera check was active.
In particular, builtin routines remain effectively disabled (and "ParamCount" is a routine (function)). "Cardinal" works since it is a type.
This also is confusing. In the presence of a language restriction, some predefined identifiers may be enabled (types), but others (built-in routines) cannot. Some keywords ("pow", "attribute") may be enabled, but others ("asm") cannot.
The following patch enables "asm" keyword and builtin procedures (but see below):
Index: predef.c =================================================================== RCS file: /mn/a8/cvsroot/gpc/p/predef.c,v retrieving revision 1.16 diff -u -p -r1.16 predef.c --- predef.c 7 Apr 2006 00:00:50 -0000 1.16 +++ predef.c 22 Jul 2006 20:14:48 -0000 @@ -1242,7 +1242,9 @@ build_predef_call (int r_num, tree apar) r_name = predef_table[i].idname; if (!r_name) r_name = predef_table[i].alias_name; gcc_assert (r_name); +#if 0 chk_dialect_name (r_name, predef_table[i].dialect); +#endif
if (r_num == p_Exit && apar) { Index: statements.c =================================================================== RCS file: /mn/a8/cvsroot/gpc/p/statements.c,v retrieving revision 1.10 diff -u -p -r1.10 statements.c --- statements.c 6 Apr 2006 04:58:33 -0000 1.10 +++ statements.c 22 Jul 2006 20:12:33 -0000 @@ -74,8 +74,10 @@ pascal_expand_asm_operands (tree string, { if (co->pascal_dialect & B_D_M_PASCAL) gpc_warning ("GPC and Borland Pascal have different `asm' syntax"); +#if 0 else chk_dialect ("`asm' is", B_D_M_PASCAL); +#endif }
string = combine_strings (string, 2);
I am not sure if we should change what GPC is doing.
I believe that gpc should either allow "enable" only if a prior "disable" has been done, or allow "enable" without restriction, or document the specific cases where "enable" is allowed. The first option would be your original intent. The second would be most flexible. The third would at least eliminate the confusion where some "enables" are allowed and others are not.
Let me explain some technical problems: on low level "enable" always "works". That is when GPC reads your program and the keyword is disabled GPC will read a name as oridinary identifier. Similarely for builtin names GPC will forget about builtin meaning (so the name probably will be reported as undefined). If the keyword is enabled GPC will treat it as a keyword (to be more precise: most keywords are recognized as a keyword only when the keyword is allowed by the grammar, otherwise are still treated as identifiers). However, GPC applies a large number of validity checks to the program, and the other checks still may reject the program.
As explained below it is not clear how (if) "enable-keyword" should interact with other checks. Even if one can find a resonable specification implementing it would probably require a lot of work -- personally I think it is not worth the effort.
I am reluctant to document existing behaviour, since it mostly reflects various implementation details which otherwise should be irrelevant for the user. Worse, GPC is constantly changing and such documentation would quicky be out of date or prevent some needed change.
I am tempted to say that the exact effect of enabling a keyword which otherwise would be disabled by dialect settings is explicitly undocumented. Typically I prefer to exactly specify meaning of the souce code. However, compiler options like "enable-keyword" are a tool to tweak around some specific problems. Moreover, the potential for error is limited since the effect (failure or success of the compilation) should be immediatly visble (of course, there is a problem with future compiler versions).
...for keywords things are more tricky: a set of dialects in which a constuct is valid may be smaller then set of dialects in which keywords involved in the constuct are valid so we still need dialect checks.
Are you thinking of cases such as "packed array" is CP, but "packed 0..3" is not? Or "a and b" is CP, but "a and 1" is not?
Yes.
So, I am not sure how useful would be ability to enable all constructs involwing given keyword.
The reason I was trying to restrict the dialect and then enable certain keywords and predefined identifiers is that changing the dialect from EP to GP changes the semantics of some EP constructs. For instance, changing to GP means that strings are no longer padded for comparisons, so:
var s : packed array [1..6] of char; [...]
s := 'GPC'; if s = 'GPC' then ...
...fails. Also:
var i, j: integer; [...]
i := 1; j := 2; writeln (i, j);
prints "12". So I cannot simply write EP with a few extensions; I must also remember all of the semantic changes that go along with selecting GP.
There are two alternate ways I can accomplish this:
Choose the GP dialect and either program around the semantic changes ("if s = 'GPC ' then") or use compiler directives to restore EP semantics ("{$no-exact-compare-strings}").
Choose the EP dialect and bracket each extension with "{$gnu-pascal}" and "{$extended-pascal}".
But if I could choose EP and selectively enable the extensions, it would be simpler, and it would document at the start of the source file exactly what extensions were used.
Yes, I understand your goal. But I am affraid that keyword-level control is too crude.
On 23 Jul 2006 at 4:31, Waldek Hebisch wrote:
If the keyword is enabled GPC will treat it as a keyword (to be more precise: most keywords are recognized as a keyword only when the keyword is allowed by the grammar, otherwise are still treated as identifiers). However, GPC applies a large number of validity checks to the program, and the other checks still may reject the program.
I understand now, thanks.
I am reluctant to document existing behaviour, since it mostly reflects various implementation details which otherwise should be irrelevant for the user.
OK, I accept that enable-keyword cannot be used to extend a dialect selectively (too bad, though :-). But then it should be documented in the manual that enable-keyword must only be used if a preceding disable-keyword was done (and the same for enable-predefined-identifier).
-- Dave
(I was out of town for some weeks, still catching up with the mails ...)
Waldek Hebisch wrote:
To be more precise: "{$enable-keyword asm}" just causes `asm' to be recognized as the keyword. Other checks are unaffected by "enable-keyword". Apparently, for `pow' no more checks is used,
Yes. As a (rough) rule of thumb from a user's point of view, things that could be implemented in (some dialect of) Pascal, except for their built-in identifier/keyword status, require no more checks, since they are actually implemented just this way internally. This includes "pow" (an operator as can be defined and overloaded according to OOE extensions that GPC supports) and of course all types such as "Cardinal".
Whereas most built-in routines are a bit different (often only in that they allow different parameter types, even if only, say, LongInt for maximum range and Integer for better performance when sufficient; so when GPC will allow overloaded routines, this may then apply to some built-in ones as well).
I am tempted to say that the exact effect of enabling a keyword which otherwise would be disabled by dialect settings is explicitly undocumented.
I agree.
There are two alternate ways I can accomplish this:
- Choose the GP dialect and either program around the semantic changes ("if s = 'GPC ' then") or use compiler directives to restore EP semantics ("{$no-exact-compare-strings}").
If you need this for a lot of source code, I'd probably recommend this. The lists of required options shouldn't be that long if you only want to avoid incompatible behaviour, and not exclude all unneeded extensions, as we try to not be incompatible to EP in GPC dialect unless EP's behaviour is ... well ... too strange (talk about string padding ;-).
- Choose the EP dialect and bracket each extension with "{$gnu-pascal}" and "{$extended-pascal}".
But if I could choose EP and selectively enable the extensions, it would be simpler, and it would document at the start of the source file exactly what extensions were used.
OTOH, if you need the extensions only for some routines (or can be encapsulated in a few), I'd probably go for that. Even if these routines are used in many programs later, you could put them in a module, and compile this module only (or even parts of it) with "{$gnu-pascal}".
Frank
On 2 Aug 2006 at 21:05, Frank Heckenbach wrote:
The lists of required options shouldn't be that long if you only want to avoid incompatible behaviour, and not exclude all unneeded extensions, as we try to not be incompatible to EP in GPC dialect unless EP's behaviour is ... well ... too strange (talk about string padding ;-).
Is there a list of the changes that the GP dialect option makes to defined EP behavior? Extensions are obvious, but semantic changes, such as string comparisons, are not.
OTOH, if you need the extensions only for some routines (or can be encapsulated in a few), ... you could put them in a module, and compile this module only (or even parts of it) with "{$gnu-pascal}".
Of the alternatives, I believe that this would produce the clearest code.
-- Dave
J. David Bryan wrote:
On 2 Aug 2006 at 21:05, Frank Heckenbach wrote:
The lists of required options shouldn't be that long if you only want to avoid incompatible behaviour, and not exclude all unneeded extensions, as we try to not be incompatible to EP in GPC dialect unless EP's behaviour is ... well ... too strange (talk about string padding ;-).
Is there a list of the changes that the GP dialect option makes to defined EP behavior? Extensions are obvious, but semantic changes, such as string comparisons, are not.
Not yet, but I guess we could collect one and put it in the manual. You might want to start, perhaps right here in this thread, collecting a list of issues you already know of, then others and I can later fill in what we find ...
Another subtle issue is that a compile-time division by zero or zero modulus is an error in GPC's default mode, but must not be in EP (GPC only gives a warning there). This may extend in the future to other checks done at runtime according to EP, but at compile-time when possible by GPC.
Given:
program comp (output);
var s : packed array [1..4] of char;
begin s := 'abc'; if s = 'abc' then writeln ('true') else writeln ('false') end.
...this will print "true" for EP and "false" for GP. But isn't the "if" statement always false in GP mode, regardless of the value of "s"? More generally, wouldn't every fixed-string equality comparison fail (or succeed) statically if the strings were of unequal length?
Yes.
If so, it would be helpful if GPC issued a warning in this case, e.g, "result of comparison is always false" (note that GCC does this in some cases, e.g., comparison of unsigned value >= 0).
Good idea. In fact, I made the warnings a bit more extensive (maybe overkill ...), see the test programs. Of course, they still can't catch all cases of unintentionally confusing padding and non-padding comparisons.
20060803: warn about some string comparisons that are always true or always false (dave7*.pas)
Frank
On 3 Aug 2006 at 21:21, Frank Heckenbach wrote:
Not yet, but I guess we could collect one and put it in the manual.
It would help. I spent an hour "debugging" the string comparison behavior change in a program I recently wrote, thinking, "This comparison test _must_ work...." I only began to understand by looking at the generated assembler, seeing the call to __p_EQ, looking that up in the RTS, recalling that there were --[no-]exact-compare-strings compiler options, running tests, and deducing that --gnu-pascal was invoking the option. Not at all obvious, I'm afraid.
You might want to start, perhaps right here in this thread, collecting a list of issues you already know of, then others and I can later fill in what we find ...
I have encountered two so far:
1. fixed-length strings are compared without blank padding
2. default field-width in write statements is 1.
In fact, I made the warnings a bit more extensive (maybe overkill ...), see the test programs.
Thanks for the patch.
-- Dave
J. David Bryan wrote:
On 3 Aug 2006 at 21:21, Frank Heckenbach wrote:
Not yet, but I guess we could collect one and put it in the manual.
It would help. I spent an hour "debugging" the string comparison behavior change in a program I recently wrote, thinking, "This comparison test _must_ work...."
I guess I spent at least as long when confronted with the EP behaviour (very surprising and unintuitive to me) for the first time ...
I only began to understand by looking at the generated assembler, seeing the call to __p_EQ, looking that up in the RTS, recalling that there were --[no-]exact-compare-strings compiler options, running tests, and deducing that --gnu-pascal was invoking the option. Not at all obvious, I'm afraid.
It's actually in the manual (Programming / Library Routines / String Operations), but I admit this section might not be hard to find when you don't know what exactly to look for ...
: `s1 = s2' : : `s1 <> s2' : : `s1 < s2' : : `s1 <= s2' : : `s1 > s2' : : `s1 >= s2' : Lexicographic comparisons of `s1' and `s2'. Returns a Boolean : result. The shorter string is blank padded to length of the longer : one, but only in `--extended-pascal' mode.
BTW, that "--gnu-pascal" implies this option can be seen in gpc-options.h. Not that I'd expect a GPC user to do this, but now we can look at this list for other potential incompatibilites (not extensions):
{ "-fgnu-pascal", 0 }, { "-fno-ignore-packed", "-fno-ignore-garbage-after-dot", "-fno-nonlocal-exit", "-fmacros", "-fno-mixed-comments", "-fdelphi-comments", "-fno-iso-gotos", "-fno-implicit-result", "-fno-case-value-checking", "-fshort-circuit", "-fread-base-specifier", "-fread-hex", "-fno-read-white-space", "-fwrite-clip-strings", "-fno-write-capital-exponent", "-fexact-compare-strings", "-fdouble-quoted-strings", "-fno-field-widths", "-fno-methods-always-virtual", "-fno-propagate-units", "-Wcast-align", "-Wobject-assignment", "-Wtyped-const", "-Wnear-far", "-Wunderscore", 0 }
These are the ones I see:
"-fmacros",
Well, GPC warns about compiler directives in EP mode, so EP comments that look like GPC compiler directives cannot define macros without warning. Macro definitions on the command-line have to be given explicitly, but if so, could change EP programs. Predefined macros should all start with an underscore, so cannot conflict with EP identifiers.
"-fno-mixed-comments",
This is, of course, incompatible:
program Foo (Output); begin Write ('This is '); { *) Write ('not '); (* } WriteLn ('EP incompatible'); end.
"-fshort-circuit",
This is sometimes thought an incompatibility, but in fact it's not. EP doesn't prescribe whether and in which order operands are evaluated, including, of course, Boolean operations. (But EP doesn't prescribe short-circuit evaluation, either, of course.)
"-fno-case-value-checking",
Though a strict extension, but at runtime, so it produces differently behaving programs. EP requires a "dynamic-violation" there, i.e. a runtime error which must be detected.
"-fread-base-specifier", "-fread-hex",
These seem similar as the previous one (increasing the set of allowed "Read" inputs at runtime), but here EP only requires an "error" for invalid input which an implementation may leave undetected, so it's not strictly incompatible.
- default field-width in write statements is 1.
This is also not actually EP-incompatible, just different from a "typical" behaviour of other EP compilers apparently (which GPC thus also does in EP mode). So if you want to write portable EP code, you cannot rely on any default width anyway.
: 6.10.3.1 WriteÂparameters : : [...] : : Write(f,e) shall be equivalent to the form write(f,e : TotalWidth), using a : default value for TotalWidth that depends on the type of e; for : integerÂtype, realÂtype, and BooleanÂtype, the default values shall be : implementationÂdefined.
Frank
On 6 Aug 2006 at 1:37, Frank Heckenbach wrote:
I guess I spent at least as long when confronted with the EP behaviour (very surprising and unintuitive to me) for the first time ...
I learned Pascal on several HP computer systems, and all of them had the extension that unequal-length strings were blank-padded for comparisons. So EP seems quite normal to me.
It's actually in the manual (Programming / Library Routines / String Operations)....
Indeed, so it is. I missed that.
BTW, that "--gnu-pascal" implies this option can be seen in gpc-options.h.
Thanks for pointing that out. Quite useful to know, actually.
These are the ones I see:
[...]
I'm less worried about behavior that would be invalid or undefined in EP than about behavior changes that occur when a valid EP program with valid EP input is compiled in GP mode. I expect GP mode to give me an enhanced version of Pascal, so allowing undefined case values, e.g., would not be surprising. What is surprising is finding that the program that worked when compiled in EP mode now fails with the same inputs in GP mode.
This is also not actually EP-incompatible, just different from a "typical" behaviour of other EP compilers.... [...] So if you want to write portable EP code, you cannot rely on any default width anyway.
Quite right, and I doubt many production programs use the default field widths. I generally use them, though, for debugging outputs. And while changing the default width to one doesn't stop a valid EP program from working, it is a bit confusing. My debug statement:
writeln ('file position/index are ', position (datafile), counter);
began to produce, in GP mode:
file position/index are 125365
instead of the EP mode:
file position/index are 1253 65
leading me at first to wonder how the file position got so far out of bounds. :-) Certainly this should not produce a warning in the compiler, but it would be helpful to have the manual detail somewhere the changes that occur when switching modes that might affect a valid program with valid inputs.
If all of the mode changes are made through option switches, then perhaps a table could be put in the "GPC Command Line Options" section, with options in rows and dialects in columns, to show which options are default for which dialects (essentially describing the settings in gpc-options.h). That would be easier, in my view, than trying to decipher the various "default in xxx" statements that now accompany most -- though not all -- of the option descriptions.
-- Dave
J. David Bryan wrote:
On 6 Aug 2006 at 1:37, Frank Heckenbach wrote:
I guess I spent at least as long when confronted with the EP behaviour (very surprising and unintuitive to me) for the first time ...
I learned Pascal on several HP computer systems, and all of them had the extension that unequal-length strings were blank-padded for comparisons. So EP seems quite normal to me.
I think it only makes sense for backward-compatibility with CP (which didn't have strings with a length field, except hand-made ones, and blank-padding was used instead, which I'd call a kludge already). When you often parse input lines or construct output lines from strings and want to control the spacing yourself instead of relying on default widths, trailing spaces make quite a difference. Anyway.
These are the ones I see:
[...]
I'm less worried about behavior that would be invalid or undefined in EP than about behavior changes that occur when a valid EP program with valid EP input is compiled in GP mode.
I think I mentioned only such.
I expect GP mode to give me an enhanced version of Pascal, so allowing undefined case values, e.g., would not be surprising.
Depends. If the EP program relied on aborting on an unmatched case value as it may validly do in EP since it's a dynamic-violation, not only an error (such an abort may not look to nice, but perhaps acceptable for a batch-style program), GPC's default behaviour would lead to unintended (and perhaps wildly wrong) behaviour.
leading me at first to wonder how the file position got so far out of bounds. :-) Certainly this should not produce a warning in the compiler, but it would be helpful to have the manual detail somewhere the changes that occur when switching modes that might affect a valid program with valid inputs.
OK. So far we have this thread. You might want to start collecting the relevant information, perhaps changing the formulations to fit manual style, and suggest where to insert it in the manual. And if you or someone else finds more such issues, please point them out.
If all of the mode changes are made through option switches,
No, not all. (That would mean adding another couple of dozen option switches ...)-:
then perhaps a table could be put in the "GPC Command Line Options" section, with options in rows and dialects in columns, to show which options are default for which dialects (essentially describing the settings in gpc-options.h). That would be easier, in my view, than trying to decipher the various "default in xxx" statements that now accompany most -- though not all -- of the option descriptions.
From gpc-options.h we could probably generate such a table
automatically with some effort, but as I said, it wouldn't capture all dialect differences ...
Frank
I wrote:
If so, it would be helpful if GPC issued a warning in this case, e.g, "result of comparison is always false" (note that GCC does this in some cases, e.g., comparison of unsigned value >= 0).
Good idea. In fact, I made the warnings a bit more extensive (maybe overkill ...), see the test programs. Of course, they still can't catch all cases of unintentionally confusing padding and non-padding comparisons.
Just a little correction to the messages.
Frank
I wrote:
I wrote:
If so, it would be helpful if GPC issued a warning in this case, e.g, "result of comparison is always false" (note that GCC does this in some cases, e.g., comparison of unsigned value >= 0).
Good idea. In fact, I made the warnings a bit more extensive (maybe overkill ...), see the test programs. Of course, they still can't catch all cases of unintentionally confusing padding and non-padding comparisons.
Just a little correction to the messages.
I think my previous patch is too noisy. Comparisons of two string constants shouldn't be warned (at least not by default). E.g., in my own code, I sometimes do things like that:
{ Configuration file }
const LogFileName = ''; { optional }
{ Main code }
if LogFileName <> '' then { ... }
This would warn whenever LogFileName is set because of the different lengths of the empty and a nonempty string. I think that's overkill.
So the following patch disables the warning for this case (and does another small internal cleanup).
Frank
On 2 Aug 2006 at 21:05, Frank Heckenbach wrote:
...we try to not be incompatible to EP in GPC dialect unless EP's behaviour is ... well ... too strange (talk about string padding ;-).
Given:
program comp (output);
var s : packed array [1..4] of char;
begin s := 'abc'; if s = 'abc' then writeln ('true') else writeln ('false') end.
...this will print "true" for EP and "false" for GP. But isn't the "if" statement always false in GP mode, regardless of the value of "s"? More generally, wouldn't every fixed-string equality comparison fail (or succeed) statically if the strings were of unequal length?
If so, it would be helpful if GPC issued a warning in this case, e.g, "result of comparison is always false" (note that GCC does this in some cases, e.g., comparison of unsigned value >= 0).
-- Dave