[G4:~/gnu/testgpc/adriaan] adriaan% cat unita.pas unit A; interface end.
[G4:~/gnu/testgpc/adriaan] adriaan% gpc -c unita.pas --ucsd-pascal unita.pas:2: error: units are an extension of Borland Pascal, traditional unita.pas:2: error: Macintosh Pascal
UCSD Pascal certainly supports units.
unita.pas:3: error: units without `implementation' part are an extension of unita.pas:3: error: traditional Macintosh Pascal
UCSD Pascal also supports units without 'implementation part', or at least Apple UCSD Pascal does.
Regards,
Adriaan van Os
Adriaan van Os wrote:
[G4:~/gnu/testgpc/adriaan] adriaan% cat unita.pas unit A; interface end.
[G4:~/gnu/testgpc/adriaan] adriaan% gpc -c unita.pas --ucsd-pascal unita.pas:2: error: units are an extension of Borland Pascal, traditional unita.pas:2: error: Macintosh Pascal
UCSD Pascal certainly supports units.
unita.pas:3: error: units without `implementation' part are an extension of unita.pas:3: error: traditional Macintosh Pascal
UCSD Pascal also supports units without 'implementation part', or at least Apple UCSD Pascal does.
Thanks, I'll change this. I don't have access to a UCSD Pascal compiler, so I can't check this myself. AFAIK, nobody has cared about this dialect for some time, so you might find more discrepancies. If you do, please report or, preferable, send a patch (it doesn't take more than changing a dialect macro in a place that's usually easily found by the initial text of the message).
BTW, the latter is interesting because it would be one of the (relatively few) UCSD features that BP doesn't share.
Frank
Frank Heckenbach wrote:
Adriaan van Os wrote:
UCSD Pascal also supports units without 'implementation part', or at least Apple UCSD Pascal does.
BTW, the latter is interesting because it would be one of the (relatively few) UCSD features that BP doesn't share.
Some more in Apple UCSD Pascal (just for the record)
1. A compilation can be a program, or one or more units separated with semicolons and ending with a period. 2. File type INTERACTIVE 3. Predefined file KEYBOARD 4. Bit-packing 5. INTEGER type can be modified by a length attribute 6. LONG INTEGER type, represented internally as a binary-coded decimal (BCD) number (up to 36 digits) 7. Built-in function PAGE 8. Built-in functions UNITREAD, UNITBUSY, UNITWAIT and UNITCLEAR 9. Built-in functions PWROFTEN and TREESEARCH 10. Built-in function SCAN 11. Optional OPTION parameter for the CLOSE procedure, with possible values NORMAL, LOCK, PURGE and CRUNCH 12. Segmentation compiler options 13. Regular versus Intrinsic Units 14. Extended comparisons of arrays and records 15. TURTLEGRAPHICS unit 16. PADDLE, BUTTON and TTLOUT routines in the APPLESTUFF unit 17. EXIT with parameter procedurename, programname or PROGRAM
Regards,
Adriaan van Os
Adriaan van Os wrote:
Some more in Apple UCSD Pascal (just for the record)
- A compilation can be a program, or one or more units separated with
semicolons and ending with a period.
Several units separated with semicolons? Strange. Kind of contradicts the meaning of "unit" (in the common meaning of the word) to me ...
- File type INTERACTIVE
What difference does it make?
- Predefined file KEYBOARD
GPC provides `Kbd' in the unit `Turbo3' (BP compatibility for Turbo Pascal 3.0 compatibility). Does it behave the same?
- Bit-packing
We don't set `--ignore-packed' in UCSD mode, so this should be the same in GPC.
- INTEGER type can be modified by a length attribute
Well, we have the `Size' attribute (probably different syntax, but the semantics might be the same?).
- LONG INTEGER type, represented internally as a binary-coded decimal
(BCD) number (up to 36 digits)
Nice. :-( I guess when GCC will support 128 bit integers, we can declare it as such (or the exact subrange), since the internal representation shouldn't matter.
- Built-in function PAGE
Is this the same as in standard Pascal (start new page where applicable)? Then I can just activate it in UCSD Pascal mode.
- Built-in functions UNITREAD, UNITBUSY, UNITWAIT and UNITCLEAR
- Built-in functions PWROFTEN and TREESEARCH
- Built-in function SCAN
What do they do? Can they be provided in a unit?
- Optional OPTION parameter for the CLOSE procedure, with possible
values NORMAL, LOCK, PURGE and CRUNCH
What do they mean?
- Segmentation compiler options
Well, we try to be backward-compatible to the directives of BP, but making directives dependent on the dialect would be even more confusing. So if they don't conflict with BP's, we can probably let GPC ignore them (like we do with BP directives that have no meaning in our environments) ...
- Regular versus Intrinsic Units
What's that?
- Extended comparisons of arrays and records
Field-by-field? Only `='/`<>'?
- TURTLEGRAPHICS unit
BP also has one (`Graph3'). It shouldn't be too hard to write one for GPC (based on `Graph' or `GRX') if someone is looking for a small job ...
- PADDLE, BUTTON and TTLOUT routines in the APPLESTUFF unit
These are probably system-specific and can be implemented in a system-specific GPC unit. Or perhaps mapped to more general input facilities (perhaps from GRX, if they apply to graphics) ...
- EXIT with parameter procedurename, programname or PROGRAM
I knew about this one. I don't really feel like supporting it (just two words: nonlocal gotos)-: ...
Frank
Frank Heckenbach wrote:
Adriaan van Os wrote:
Some more in Apple UCSD Pascal (just for the record)
- A compilation can be a program, or one or more units separated
with semicolons and ending with a period.
Several units separated with semicolons? Strange. Kind of contradicts the meaning of "unit" (in the common meaning of the word) to me ...
There will have been pragmatic reasons for it, way back in 1980. With 64 or 128 Kbyte memory you need a lot of segmentation and chaining, therefore small units. There was no --automake feature.
- File type INTERACTIVE
What difference does it make?
[1] Apple UCSD Pascal Language Reference Manual.
"If the file is not of type INTERACTIVE, RESET automatically performs a GET action -- that is, it loads the first record of the file into the file’s buffer variable and advances the file pointer to the second record. If the file is INTERACTIVE, no GET is performed; the buffer variable’s value is undefined and the file pointer points to the first record." [1, page 28]
"READ With a CHAR Variable.
For a CHAR variable, READ reads one character from the file and assigns that character to the variable. There are two special cases: Whenever the end-of-line character (ASCII 13) is READ, the value assigned to the CHAR variable is a space (ASCII 32), not a CR. Whenever EOF becomes true, the value assigned to the CHAR variable is not defined.
After the READ, the next READ or READLN will always start with the character immediately following the one just READ.
The workings of EOLN and EOF depend on whether the file is of type TEXT or INTERACTIVE. For a TEXT file, EOF is true when the last text character in the file has been READ. EOLN is true when the last text character on a line has been READ and whenever EOF is true. (A "text character" here means a character that is not the end-of-line character or the end-of-file character).
For an INTERACTIVE file, EOF is not true until the end-of-file character has been READ. EOLN is not true until the end-of-line character at the end of the line has been READ or until EOF is true." [1, page 34]
"The standard predeclared files INPUT and OUTPUT are INTERACTIVE files representing the console keyboard and screen; another predefined file called KEYBOARD also represents the keyboard." [1, page 11]
- Predefined file KEYBOARD
GPC provides `Kbd' in the unit `Turbo3' (BP compatibility for Turbo Pascal 3.0 compatibility). Does it behave the same?
"The difference between INPUT and KEYBOARD is that when INPUT is used to refer to the keyboard, the typed characters are automatically displayed on the screen; when KEYBOARD is used, the characters are not automatically displayed." [1, page 12]
- Bit-packing
We don't set `--ignore-packed' in UCSD mode, so this should be the same in GPC.
Yes, it is.
- INTEGER type can be modified by a length attribute
Well, we have the `Size' attribute (probably different syntax, but the semantics might be the same?).
The 'Size' attribute denotes the number of decimal digits (BCD), not the number of bits.
" TYPE BIGNUM = INTEGER[ 12] VAR FATS: INTEGER[ 25];
This defines BIGNUM as a type which can have any integer value requiring not more than 12 decimal digits. FATS can have any integer value requiring not more than 25 digits. The length attribute can be any unsigned INTEGER constant up to and including 36." [1, page 19].
- LONG INTEGER type, represented internally as a binary-coded
decimal (BCD) number (up to 36 digits)
Nice. :-( I guess when GCC will support 128 bit integers, we can declare it as such (or the exact subrange), since the internal representation shouldn't matter.
Because integer values are "discrete" numbers. In non-BCD floating point you have the problem that you cannot even represent something simple like 2 euro 13 exactly (which is a horror for accounting applications).
- Built-in function PAGE
Is this the same as in standard Pascal (start new page where applicable)? Then I can just activate it in UCSD Pascal mode.
I think so (if my understanding of it is right).
"The page procedure sends a top-of-form character (ASCII 12) to the file. The form is
PAGE( FILEID)
where FILEID is the identifier of an open file of type TEXT or INTERACTIVE." [1, page 39]
- Built-in functions UNITREAD, UNITBUSY, UNITWAIT and UNITCLEAR
The UNITxxx routines provide hardware-oriented low-level IO. "They allow a Pascal program to transfer a specified number of consecutive bytes between memory and a device. They are not controlled by filenames, directories, etc., but merely use device numbers and (for diskette drives) block numbers." [1, page 26]
Back in those good old times, there were no security issues, you simply had full control ! You could destroy everything or do wonderful things with it, like copying MS-DOS diskettes on an Apple IIgs !
procedure UNITREAD( UNITNUMBER, ARRAY, LENGTH [, [BLOCKNUMBER] [, MODE]] ) procedure UNITWRITE( UNITNUMBER, ARRAY, LENGTH [, [BLOCKNUMBER] [, MODE]] ) function UNITBUSY: boolean {always returns FALSE on the Apple II} procedure UNITCLEAR( UNITNUMBER)
If someone is interested, I can provide more details.
- Built-in functions PWROFTEN and TREESEARCH
PWROFTEN
"This function returns a real value which is 10 to a specified (integer) power. The form is
PWROFTEN( EXPONENT)
where EXPONENT is an integer value in the range 0..37. This function returns the value of 10 to the EXPONENT power." [1, page 45]
TREESEARCH
"This is a fast function for searching a binary tree that has a particular kind of structure. The form is
TREESEARCH( ROOTPTR, NODEPTR, NAME)
where ROOTPTR is a pointer to the root node of the tree to be searched, NODEPTR is a pointer variable to be updated by TREESEARCH, and NAME is the identifier of a PACKED ARRAY[ 1..8] OF CHAR which contains the 8-character name to be searched for in the tree.
The nodes of the binary tree are assumed to be linked records of the form
NODE = RECORD NAME: PACKED ARRAY{ 1..8] of CHAR; LEFTLINK, RIGHTLINK: ^NODE
...(* other fields can be anything *) ... END;
The type name and the field names are not important; TREESEARCH only assumes that the first eight bytes of the record contain an 8-character name and are followed by two pointers to other nodes.
It is also assumed that names are not duplicated within the tree and are assigned to nodes according to an alphabetical rule: for a given node, the name of the left subnode is alphabetically less than the name of the node, and the name of the right subnode is alphabetically greater than the name of the node. Finally, any links that do not point to other nodes should be NIL.
TREESEARCH can return any of three values:
0: The NAME passed to TREESEARCH has been found in the tree. NODEPTR now points to the node with the specified name.
1: The NAME is not in the tree. If it is added to the tree, it should be the right subnode of the node pointed to by NODEPTR. -1: The NAME is not in the tree. If it is added to the tree, it should be the left subnode of the node pointed to by NODEPTR.
The TREESEARCH function does not perform any type checking on the parameters passed to it." [1, page 49-50]
- Built-in function SCAN
"This function scans a range of memory bytes, looking for a one-character target. The target can be a specified character, or it can be any character that doesn't match the specified character. SCAN returns an integer value, which is the number of bytes scanned. the form is
SCAN( LIMIT, PEXPR, SOURCE)
where
LIMIT is an integer value which gives the maximum number of bytes to scan. If LIMIT is negative, SCAN will scan backward. If SCAN fails to find the specified target, it will return the value of LIMIT
PEXPR is a "partial expression" which specifies the target of the scan. PEXPR takes one of the following forms:
= CH <> CH
where CH stands for any expression that yields a result of type char.
SOURCE is a variable of any type except a file type. The first byte of the variable is the starting point of the scan.
SCAN terminates when it finds the target or when it has scanned LIMIT bytes. It then returns the number of bytes scanned. It the target is found at the starting point, the value returned will be zero. It LIMIT is negative, the scan will go backward and the value returned will also be negative." [1, page 51-52]
What do they do? Can they be provided in a unit?
No problem for PWROFTEN, TREESEARCH and SCAN.
<to be continued>
Adriaan van Os
Adriaan van Os wrote:
Frank Heckenbach wrote:
Adriaan van Os wrote:
Some more in Apple UCSD Pascal (just for the record)
- A compilation can be a program, or one or more units separated
with semicolons and ending with a period.
Several units separated with semicolons? Strange. Kind of contradicts the meaning of "unit" (in the common meaning of the word) to me ...
There will have been pragmatic reasons for it, way back in 1980. With 64 or 128 Kbyte memory you need a lot of segmentation and chaining, therefore small units. There was no --automake feature.
But why couldn't they be in separate files (or at least in one file without special syntax, i.e. `unit Foo ... end. unti Bar ... end.', like GPC used to allow)? Without automake, this should have been better, since one would have been able to compile just some of the units, not everything if everything is in one file.
(Or, actually, I think they should have separated implementation details like segmentation from the logical unit structure, i.e. allow segmentation on a smaller than unit basis.)
- File type INTERACTIVE
What difference does it make?
I suppose we can ignore the difference, since GPC does lazy input, anyway. So `type Interactive = Text;' might suffice.
- Predefined file KEYBOARD
GPC provides `Kbd' in the unit `Turbo3' (BP compatibility for Turbo Pascal 3.0 compatibility). Does it behave the same?
"The difference between INPUT and KEYBOARD is that when INPUT is used to refer to the keyboard, the typed characters are automatically displayed on the screen; when KEYBOARD is used, the characters are not automatically displayed." [1, page 12]
I take this as a yes.
- INTEGER type can be modified by a length attribute
Well, we have the `Size' attribute (probably different syntax, but the semantics might be the same?).
The 'Size' attribute denotes the number of decimal digits (BCD), not the number of bits.
" TYPE BIGNUM = INTEGER[ 12] VAR FATS: INTEGER[ 25];
This defines BIGNUM as a type which can have any integer value requiring not more than 12 decimal digits. FATS can have any integer value requiring not more than 25 digits. The length attribute can be any unsigned INTEGER constant up to and including 36." [1, page 19].
Again, if we have 128 bit integers someday, we could implement it (though binary, not BCD, but it shouldn't matter) -- though I don't like the syntax, of course ...
- LONG INTEGER type, represented internally as a binary-coded
decimal (BCD) number (up to 36 digits)
Nice. :-( I guess when GCC will support 128 bit integers, we can declare it as such (or the exact subrange), since the internal representation shouldn't matter.
Because integer values are "discrete" numbers. In non-BCD floating point you have the problem that you cannot even represent something simple like 2 euro 13 exactly (which is a horror for accounting applications).
I know, but that's nothing to do with BCD, just integer (or fixed point) vs. floating point. I always use standard (binary) integers for monetary amounts (in cents).
GPC supports 64 bit integers. This suffices for 10^17 Euro (or $) -- probably enough for most country's debts for the next few years. ;-)
So if that's the purpose, it might be enough to use LongestInt.
- Built-in functions UNITREAD, UNITBUSY, UNITWAIT and UNITCLEAR
The UNITxxx routines provide hardware-oriented low-level IO. "They allow a Pascal program to transfer a specified number of consecutive bytes between memory and a device. They are not controlled by filenames, directories, etc., but merely use device numbers and (for diskette drives) block numbers." [1, page 26]
Back in those good old times, there were no security issues, you simply had full control ! You could destroy everything or do wonderful things with it, like copying MS-DOS diskettes on an Apple IIgs !
procedure UNITREAD( UNITNUMBER, ARRAY, LENGTH [, [BLOCKNUMBER] [, MODE]] ) procedure UNITWRITE( UNITNUMBER, ARRAY, LENGTH [, [BLOCKNUMBER] [, MODE]] ) function UNITBUSY: boolean {always returns FALSE on the Apple II} procedure UNITCLEAR( UNITNUMBER)
If someone is interested, I can provide more details.
Well, under Unix they could be implemented by direct access to the devices (of course, this will work only for root or another special user with access permissions). Under Dos, anyway, and under Windows probably, too. So they could be done like the uglier routines of the BP-compatible `Dos' unit (probably also with appropriate conditionals).
SCAN( LIMIT, PEXPR, SOURCE)
PEXPR is a "partial expression" which specifies the target of the scan. PEXPR takes one of the following forms:
= CH <> CH
You mean `Scan (42, <> 'A', Foo)'???
<rant subject="syntax" level="200%"> ...
Oh dear, I'm quite shocked. Why do people make up such strange things? They could easily have made two separate routines (say `ScanEQ' and `ScanNE' -- this might be what can be implemented reasonably in GPC, with different syntax (*)) -- it would have taken them just one more predefined identifier instead of a completely irregular new syntax rule ...
What do they do? Can they be provided in a unit?
No problem for PWROFTEN, TREESEARCH
For TreeSearch with an untyped parameter and type-casting (which will be just as unsafe as the UCSD function).
(*) Just a thought. Perhaps the syntax could be handled with more-advanced preprocessor features, in particular string handling. Something like:
{$define Scan(A, B, C) {$if MacroIsPrefix (<>, MacroTrim (B))} ScanNE (A, MacroRemovePrefix (<>, MacroTrim (B)), C) {$else} ScanEQ (A, MacroRemovePrefix (=, MacroTrim (B)), C) {$endif} }
Such features are not present now, but it might be rather easy to add them to the new preprocessor. Of course, for this strange UCSD function, that's probably overkill, but that's not the only strange syntax we've seen recently.
Perhaps we'd have to see how far we'd get (and which preprocessor features would be required), but if it helps to keep a substantial amount of those strange syntaxes out of the actual compiler, I'd be inclined to strengthen the preprocessor (though I haven't advocated the use of macros in general) ...
Frank
On Tue, Jul 29, 2003 at 01:55:18AM +0200, Frank Heckenbach wrote:
- File type INTERACTIVE
What difference does it make?
I suppose we can ignore the difference, since GPC does lazy input, anyway. So `type Interactive = Text;' might suffice.
The first input character would be lost this way, since the program would start with a `get' thinking it retrives the first char, but actually getting the second one.
Emil
Emil Jerabek wrote:
On Tue, Jul 29, 2003 at 01:55:18AM +0200, Frank Heckenbach wrote:
- File type INTERACTIVE
What difference does it make?
I suppose we can ignore the difference, since GPC does lazy input, anyway. So `type Interactive = Text;' might suffice.
The first input character would be lost this way, since the program would start with a `get' thinking it retrives the first char, but actually getting the second one.
Oh, it works like this? :-( In GPC, also no `Get' is performed after `Reset', but the buffer is validated when it's referenced. (Which combines the apparent advantage of `Interactive', that it doesn't try to read too early, with compliance to the standard I/O semantics.)
It's tricky enough to combine standard and BP semantics as we try to (there are still bugs). Adding such another kind is not really a nice prospect ...
Frank
Frank Heckenbach wrote:
Emil Jerabek wrote:
The first input character would be lost this way, since the program would start with a `get' thinking it retrives the first char, but actually getting the second one.
Oh, it works like this? :-( In GPC, also no `Get' is performed after `Reset', but the buffer is validated when it's referenced. (Which combines the apparent advantage of `Interactive', that it doesn't try to read too early, with compliance to the standard I/O semantics.)
It's tricky enough to combine standard and BP semantics as we try to (there are still bugs). Adding such another kind is not really a nice prospect ...
We can simply add it to a list of known incompatibilities in a "Porting from UCSD Pascal" chapter in the gpc manual (which I intend to write when I have more time than now at this very moment).
Regards,
Adriaan van Os
On Mon, Aug 04, 2003 at 04:33:19AM +0200, Frank Heckenbach wrote:
Emil Jerabek wrote:
On Tue, Jul 29, 2003 at 01:55:18AM +0200, Frank Heckenbach wrote:
- File type INTERACTIVE
What difference does it make?
I suppose we can ignore the difference, since GPC does lazy input, anyway. So `type Interactive = Text;' might suffice.
The first input character would be lost this way, since the program would start with a `get' thinking it retrives the first char, but actually getting the second one.
Oh, it works like this? :-( In GPC, also no `Get' is performed after `Reset', but the buffer is validated when it's referenced. (Which combines the apparent advantage of `Interactive', that it doesn't try to read too early, with compliance to the standard I/O semantics.)
It's tricky enough to combine standard and BP semantics as we try to (there are still bugs). Adding such another kind is not really a nice prospect ...
Frank
Before you start worrying about supporting this feature: I've never worked with Macs, I was just inferring from the description of `Interactive' posted by Adriaan. Can somebody verify it is correct? (Well, TeX behaves this way, and Knuth's description of I/O in Pascal-H is indeed quite similar to the description of Apple UCSD.)
Emil
-- Frank Heckenbach, frank@g-n-u.de, http://fjf.gnu.de/, 7977168E GPC To-Do list, latest features, fixed bugs: http://www.gnu-pascal.de/todo.html GPC download signing key: 51FF C1F0 1A77 C6C2 4482 4DDC 117A 9773 7F88 1707
Emil Jerabek wrote:
On Mon, Aug 04, 2003 at 04:33:19AM +0200, Frank Heckenbach wrote:
Emil Jerabek wrote:
On Tue, Jul 29, 2003 at 01:55:18AM +0200, Frank Heckenbach wrote:
> 2. File type INTERACTIVE
What difference does it make?
I suppose we can ignore the difference, since GPC does lazy input, anyway. So `type Interactive = Text;' might suffice.
The first input character would be lost this way, since the program would start with a `get' thinking it retrives the first char, but actually getting the second one.
Oh, it works like this? :-( In GPC, also no `Get' is performed after `Reset', but the buffer is validated when it's referenced. (Which combines the apparent advantage of `Interactive', that it doesn't try to read too early, with compliance to the standard I/O semantics.)
It's tricky enough to combine standard and BP semantics as we try to (there are still bugs). Adding such another kind is not really a nice prospect ...
Frank
Before you start worrying about supporting this feature: I've never worked with Macs, I was just inferring from the description of `Interactive' posted by Adriaan.
Just to clear up a potential misunderstanding - Adriaan's postings in this thread is discussing the Apple UCSD Pascal compiler for the Apple II line of computers. For the Macintosh line of computers, a different Apple Pascal compiler (MPW Pascal) was used. Although the MPW Pascal language dialect supported some legacy Apple UCSD Pascal features, all but one of the 17 Apple UCSD Pascal items Adriaan posted a while back were pretty much completely unsupported. (The one that unaltered support continued on was the standard Pascal Page procedure.)
Gale Paeper gpaeper@empirenet.com
Gale Paeper wrote:
Emil Jerabek wrote:
On Mon, Aug 04, 2003 at 04:33:19AM +0200, Frank Heckenbach wrote:
Emil Jerabek wrote:
On Tue, Jul 29, 2003 at 01:55:18AM +0200, Frank Heckenbach wrote:
>> 2. File type INTERACTIVE > > What difference does it make?
I suppose we can ignore the difference, since GPC does lazy input, anyway. So `type Interactive = Text;' might suffice.
The first input character would be lost this way, since the program would start with a `get' thinking it retrives the first char, but actually getting the second one.
Oh, it works like this? :-( In GPC, also no `Get' is performed after `Reset', but the buffer is validated when it's referenced. (Which combines the apparent advantage of `Interactive', that it doesn't try to read too early, with compliance to the standard I/O semantics.)
It's tricky enough to combine standard and BP semantics as we try to (there are still bugs). Adding such another kind is not really a nice prospect ...
Before you start worrying about supporting this feature: I've never worked with Macs, I was just inferring from the description of `Interactive' posted by Adriaan.
Just to clear up a potential misunderstanding - Adriaan's postings in this thread is discussing the Apple UCSD Pascal compiler for the Apple II line of computers. For the Macintosh line of computers, a different Apple Pascal compiler (MPW Pascal) was used. Although the MPW Pascal language dialect supported some legacy Apple UCSD Pascal features, all but one of the 17 Apple UCSD Pascal items Adriaan posted a while back were pretty much completely unsupported. (The one that unaltered support continued on was the standard Pascal Page procedure.)
I'm aware that we're talking about UCSD, not Mac Pascal now.
BTW, would it solve the issue if we'd implicitly prepend a dummy character to each `Interactive' file on `Reset'? (If it's undefined, it wouldn't matter which character, perhaps a space, so it won't hurt too much when not ignored (e.g. when reading numbers).) And otherwise behave like `Text'? This might be more feasible ...
Frank
Gale Paeper wrote:
Emil Jerabek wrote:
Before you start worrying about supporting this feature: I've never worked with Macs, I was just inferring from the description of `Interactive' posted by Adriaan.
Just to clear up a potential misunderstanding - Adriaan's postings in this thread is discussing the Apple UCSD Pascal compiler for the Apple II line of computers. For the Macintosh line of computers, a different Apple Pascal compiler (MPW Pascal) was used. Although the MPW Pascal language dialect supported some legacy Apple UCSD Pascal features, all but one of the 17 Apple UCSD Pascal items Adriaan posted a while back were pretty much completely unsupported. (The one that unaltered support continued on was the standard Pascal Page procedure.)
There is another one in MPW, bit packing, it is also in GPC. The list of 17 items posted are those features in UCSD Pascal that didn't make it to BP, I recall ...
Frank Heckenbach wrote:
Adriaan van Os wrote:
BTW, the latter is interesting because it would be one of the (relatively few) UCSD features that BP doesn't share.
Some more in Apple UCSD Pascal (just for the record)
But thanks for the clarification. To clarify up another potential misunderstanding: UCSD Pascal did run on other systems than the Apple II, but I don't have any experience that (I think CBFalconer has), which is why I am refering to Apple UCSD Pascal.
By the way, what is a "legacy" feature ? Who issues the verdict and on what grounds ? Common opinion ? Some people, mostly not those with much technical skill, refer to Pascal itself as a "legacy" language ... We have to judge features, algorithms languages and design in general on merits, not on prejudice.
Regards,
Adriaan van Os
Adriaan van Os wrote:
Gale Paeper wrote:
Emil Jerabek wrote:
Before you start worrying about supporting this feature: I've never worked with Macs, I was just inferring from the description of `Interactive' posted by Adriaan.
Just to clear up a potential misunderstanding - Adriaan's postings in this thread is discussing the Apple UCSD Pascal compiler for the Apple II line of computers. For the Macintosh line of computers, a different Apple Pascal compiler (MPW Pascal) was used. Although the MPW Pascal language dialect supported some legacy Apple UCSD Pascal features, all but one of the 17 Apple UCSD Pascal items Adriaan posted a while back were pretty much completely unsupported. (The one that unaltered support continued on was the standard Pascal Page procedure.)
[snip]
By the way, what is a "legacy" feature ?
I don't know about other folks, but the definition for legacy that I use is the same one commonly found in English language dictionaries. A legacy feature is nothing more than a feature which was also present in a previous generation.
Who issues the verdict and on what grounds ? Common opinion ?
No opinion involved. Assuming, of course, there is sufficient factual evidence available to determine when the feature first occurred and what the ancestory relationship is.
Some people, mostly not those with much technical skill, refer to Pascal itself as a "legacy" language ... We have to judge features, algorithms languages and design in general on merits, not on prejudice.
Just because some folks always use legacy as a negative epithet doesn't mean it always is a negative epithet. Unless the nuances of context indictates it is being used in a negative epithetical sense, the word legacy describes nothing more than an ancestral relationship.
Gale Paeper gpaeper@empirenet.com
Frank Heckenbach wrote:
Adriaan van Os wrote:
Frank Heckenbach wrote:
Adriaan van Os wrote:
Some more in Apple UCSD Pascal (just for the record)
- A compilation can be a program, or one or more units separated
with semicolons and ending with a period.
Several units separated with semicolons? Strange. Kind of contradicts the meaning of "unit" (in the common meaning of the word) to me ...
There will have been pragmatic reasons for it, way back in 1980. With 64 or 128 Kbyte memory you need a lot of segmentation and chaining, therefore small units. There was no --automake feature.
But why couldn't they be in separate files (or at least in one file without special syntax, i.e. `unit Foo ... end. unti Bar ... end.', like GPC used to allow)? Without automake, this should have been better, since one would have been able to compile just some of the units, not everything if everything is in one file.
The basic idea in UCSD Pascal is that compilation is something that stops with a period. So, any units, comments or whatever may be after the period will not be compiled. This idea survived in traditional Macintosh Pascal compilers and in the GPC compiler argument --ignore-garbage-after-dot. Still, in UCSD Pascal you are free to put units in different files and compile them separately.
(Or, actually, I think they should have separated implementation details like segmentation from the logical unit structure, i.e. allow segmentation on a smaller than unit basis.)
I couldn't agree more, but look where we are twenty-four-years-later with a gcc back-end on platforms that do not support the section ("section-name") attribute ? A quarter century back in time !
- INTEGER type can be modified by a length attribute
Well, we have the `Size' attribute (probably different syntax, but the semantics might be the same?).
The 'Size' attribute denotes the number of decimal digits (BCD), not the number of bits.
<snip>
Again, if we have 128 bit integers someday, we could implement it (though binary, not BCD, but it shouldn't matter) -- though I don't like the syntax, of course ...
OK, if we have 128-bit integers someday, we can write ... attribute( decimals = 25) ?
- LONG INTEGER type, represented internally as a binary-coded
decimal (BCD) number (up to 36 digits)
Nice. :-( I guess when GCC will support 128 bit integers, we can declare it as such (or the exact subrange), since the internal representation shouldn't matter.
Because integer values are "discrete" numbers. In non-BCD floating point you have the problem that you cannot even represent something simple like 2 euro 13 exactly (which is a horror for accounting applications).
I know, but that's nothing to do with BCD, just integer (or fixed point) vs. floating point.
Well, in BCD floating-point 2 euro 13 can be represented exactly, in binary floating-point it can't.
I always use standard (binary) integers for monetary amounts (in cents).
GPC supports 64 bit integers. This suffices for 10^17 Euro (or $) -- probably enough for most country's debts for the next few years. ;-)
Yes, 64 bit integers are what I have missed in other compilers for that very reason.
SCAN( LIMIT, PEXPR, SOURCE)
You mean `Scan (42, <> 'A', Foo)'???
Quite amusing, isn't it ?
<rant subject="syntax" level="200%"> ...
Oh dear, I'm quite shocked. Why do people make up such strange things?
Well, it took evolution a million years (or so) to get from a dino to a Pascal programmer. In all those million years (or so) creativity has been a greater force than intelligence (otherwise no small dino's would have been born). That's the basic idea of evolution, unbound creativity limited by survival only, not by intelligence. You can't change the rules that easily, it has been with us for many million years. So, that's why it is so hard to be a real good programmer, it is against the unspelled creative forces of nature. You have to think with everything you do, think through the smallest detail and reject any bad idea. Besides, if you weren't very creative also, you wouldn't be a programmer.
What helps is a strong character - one that sternly says "you can't do that" - and a true sense of beauty - which makes you feel horrible if you do it anyway. Those who are not blessed with (besides their creativity) both a strong character and a real sense of beauty, need a "religion" that tells them from outside what to do and what not to do - look at all those C++ fanatics that truly believe the whole world changes as soon as they call a procedure a "method" and a parameter a "message" (or whatever). They *need* that believe.
(*) Just a thought.
Perhaps the syntax could be handled with more-advanced preprocessor features, in particular string handling. Something like:
{$define Scan(A, B, C) {$if MacroIsPrefix (<>, MacroTrim (B))} ScanNE (A, MacroRemovePrefix (<>, MacroTrim (B)), C) {$else} ScanEQ (A, MacroRemovePrefix (=, MacroTrim (B)), C) {$endif} }
But how do you propagate a "Scan" macro out of a UCSD compatibility unit ?
Such features are not present now, but it might be rather easy to add them to the new preprocessor. Of course, for this strange UCSD function, that's probably overkill, but that's not the only strange syntax we've seen recently. Perhaps we'd have to see how far we'd get (and which preprocessor features would be required), but if it helps to keep a substantial amount of those strange syntaxes out of the actual compiler, I'd be inclined to strengthen the preprocessor (though I haven't advocated the use of macros in general) ...
Certainly.
Regards,
Adriaan van Os
Adriaan van Os wrote:
(Or, actually, I think they should have separated implementation details like segmentation from the logical unit structure, i.e. allow segmentation on a smaller than unit basis.)
I couldn't agree more, but look where we are twenty-four-years-later with a gcc back-end on platforms that do not support the section ("section-name") attribute ?
Actually not quite the same. The attribute is an explicit mechanism (which a high-level programmer should not need to be concerned with), whereas UCSD would have needed implicit segmentation (which could be platform-dependent since it's an implementation issue).
- INTEGER type can be modified by a length attribute
Well, we have the `Size' attribute (probably different syntax, but the semantics might be the same?).
The 'Size' attribute denotes the number of decimal digits (BCD), not the number of bits.
<snip> > > Again, if we have 128 bit integers someday, we could implement it > (though binary, not BCD, but it shouldn't matter) -- though I don't > like the syntax, of course ...
OK, if we have 128-bit integers someday, we can write ... attribute( decimals = 25) ?
Or perhaps just `-(10 pow 25 - 1) .. 10 pow 25 - 1'.
- LONG INTEGER type, represented internally as a binary-coded
decimal (BCD) number (up to 36 digits)
Nice. :-( I guess when GCC will support 128 bit integers, we can declare it as such (or the exact subrange), since the internal representation shouldn't matter.
Because integer values are "discrete" numbers. In non-BCD floating point you have the problem that you cannot even represent something simple like 2 euro 13 exactly (which is a horror for accounting applications).
I know, but that's nothing to do with BCD, just integer (or fixed point) vs. floating point.
Well, in BCD floating-point 2 euro 13 can be represented exactly, in binary floating-point it can't.
My (non-floating ;-) point is that using floating point for currency amounts is silly, anyway.
SCAN( LIMIT, PEXPR, SOURCE)
You mean `Scan (42, <> 'A', Foo)'???
Quite amusing, isn't it ?
Yeah, let's invent some token combination that's not even allowed in C. ;-)
<rant subject="syntax" level="200%"> ...
Oh dear, I'm quite shocked. Why do people make up such strange things?
Well, it took evolution a million years (or so) to get from a dino to a Pascal programmer. In all those million years (or so) creativity has been a greater force than intelligence (otherwise no small dino's would have been born). That's the basic idea of evolution, unbound creativity limited by survival only, not by intelligence.
Yeah, survival. Fortunately, nature's evolution wasn't so much concerned with backward-compatibility. ;-)
You can't change the rules that easily, it has been with us for many million years. So, that's why it is so hard to be a real good programmer, it is against the unspelled creative forces of nature. You have to think with everything you do, think through the smallest detail and reject any bad idea. Besides, if you weren't very creative also, you wouldn't be a programmer.
What helps is a strong character - one that sternly says "you can't do that" - and a true sense of beauty - which makes you feel horrible if you do it anyway.
Nice description.
I also think it takes two -- one who makes the suggestions, and one who examins them very critically. I remember when I was just a user of GPC, I made some suggestions, some of which got implemented too easily -- which I later regretted when I had to remove or change them as a GPC developer ...
(*) Just a thought.
Perhaps the syntax could be handled with more-advanced preprocessor features, in particular string handling. Something like:
{$define Scan(A, B, C) {$if MacroIsPrefix (<>, MacroTrim (B))} ScanNE (A, MacroRemovePrefix (<>, MacroTrim (B)), C) {$else} ScanEQ (A, MacroRemovePrefix (=, MacroTrim (B)), C) {$endif} }
But how do you propagate a "Scan" macro out of a UCSD compatibility unit ?
Not possible in units. You could use an include file (Pascal declarations: units, macros: includes, might make some sense), and use `{$i}' instead of `uses' or `-include' instead of `--uses'.
Frank
In message 200307282355.BAA17434@goedel.fjf.gnu.de, Frank Heckenbach frank@g-n-u.de writes
Adriaan van Os wrote:
Frank Heckenbach wrote:
Adriaan van Os wrote:
Some more in Apple UCSD Pascal (just for the record)
- A compilation can be a program, or one or more units separated
with semicolons and ending with a period.
Several units separated with semicolons? Strange. Kind of contradicts the meaning of "unit" (in the common meaning of the word) to me ...
There will have been pragmatic reasons for it, way back in 1980. With 64 or 128 Kbyte memory you need a lot of segmentation and chaining, therefore small units. There was no --automake feature.
But why couldn't they be in separate files (or at least in one file without special syntax, i.e. `unit Foo ... end. unti Bar ... end.', like GPC used to allow)? Without automake, this should have been better, since one would have been able to compile just some of the units, not everything if everything is in one file.
My recollection is that the original UCSD operating system only supported volumes with a maximum of 77? files so there was some pressure to minimise the number of files.
Frank Heckenbach wrote:
Adriaan van Os wrote:
Frank Heckenbach wrote:
Adriaan van Os wrote:
Some more in Apple UCSD Pascal (just for the record)
SCAN( LIMIT, PEXPR, SOURCE)
PEXPR is a "partial expression" which specifies the target of the scan. PEXPR takes one of the following forms:
= CH <> CH
You mean `Scan (42, <> 'A', Foo)'???
<rant subject="syntax" level="200%"> ...
Oh dear, I'm quite shocked. Why do people make up such strange things? They could easily have made two separate routines (say `ScanEQ' and `ScanNE' -- this might be what can be implemented reasonably in GPC, with different syntax (*)) -- it would have taken them just one more predefined identifier instead of a completely irregular new syntax rule ...
I'm not sure where in the chain from Apple's UCSD Pascal to MPW Pascal the change was made, but in MPW Pascal `ScanEQ' and `ScanNE' is provided instead of Scan. (The parameter types for LIMIT and SOURCE are also slightly different and the PEXPR "partial expression" is replaced with an expression of type char.)
(*) Just a thought. Perhaps the syntax could be handled with more-advanced preprocessor features, in particular string handling. Something like:
{$define Scan(A, B, C) {$if MacroIsPrefix (<>, MacroTrim (B))} ScanNE (A, MacroRemovePrefix (<>, MacroTrim (B)), C) {$else} ScanEQ (A, MacroRemovePrefix (=, MacroTrim (B)), C) {$endif} }
How about:
{$define Scan(A, B, C) repeat var ScanExpression : string(4) value (#B); if (Length(ScanExpression) = 4) and_then (index(ScanExpression, '<>') = 1) then ScanNE((A),ScanExpression[4],(C)) else if (Length(ScanExpression) = 3) and_then (index(ScanExpression, '=') = 1) then ScanEQ((A),ScanExpression[3],(C)) else ParameterError; until true; }
Note: The above assumes the preprocessor treats #B like the C preprocessor does (i.e., string quotes the macro parameter) and that PEXPR parameter is required to be in the exact form that Adriaan cited - without quotes for CH. If the CH part is a quoted char constant, some adjustments are needed to take into accout the embedded quote characters. If the CH part can be any expression of char type, forget it - I don't think a macro hack is possible for that.
Gale Paeper gpaeper@mpirenet.com
Gale Paeper wrote:
Oh dear, I'm quite shocked. Why do people make up such strange things? They could easily have made two separate routines (say `ScanEQ' and `ScanNE' -- this might be what can be implemented reasonably in GPC, with different syntax (*)) -- it would have taken them just one more predefined identifier instead of a completely irregular new syntax rule ...
I'm not sure where in the chain from Apple's UCSD Pascal to MPW Pascal the change was made, but in MPW Pascal `ScanEQ' and `ScanNE' is provided instead of Scan.
Even the same names that I'd just made up? :-)
(*) Just a thought. Perhaps the syntax could be handled with more-advanced preprocessor features, in particular string handling. Something like:
{$define Scan(A, B, C) {$if MacroIsPrefix (<>, MacroTrim (B))} ScanNE (A, MacroRemovePrefix (<>, MacroTrim (B)), C) {$else} ScanEQ (A, MacroRemovePrefix (=, MacroTrim (B)), C) {$endif} }
How about:
{$define Scan(A, B, C) repeat
Scan in UCSD Pascal is a function, so a compatibility macro must be usable as a function.
var ScanExpression : string(4) value (#B); if (Length(ScanExpression) = 4) and_then (index(ScanExpression,
'<>') = 1) then ScanNE((A),ScanExpression[4],(C))
BTW, would these parentheses actually be necessary in Pascal? Sure, it won't hurt to add them, but without the infamous comma operator of C, I think there could be no confusion here, anyway.
else if (Length(ScanExpression) = 3) and_then (index(ScanExpression,
'=') = 1) then ScanEQ((A),ScanExpression[3],(C)) else ParameterError; until true;
`repeat ... until True'? (Without trailing `;', BTW.) Perhaps you've read/written too many C macros of the kind `do ... while (0)'.
In Pascal, however, `begin ... end' would seem simpler (in a statement context), wouldn't it? (One of my favourite arguments why semicolon as a separator is better, BTW. :-)
Note: The above assumes the preprocessor treats #B like the C preprocessor does (i.e., string quotes the macro parameter) and that PEXPR parameter is required to be in the exact form that Adriaan cited - without quotes for CH. If the CH part is a quoted char constant, some adjustments are needed to take into accout the embedded quote characters.
He wrote "where CH stands for any expression that yields a result of type char". This would seem to include a character literal, so this problem does occur.
Also, your suggestion would shift quite some work to runtime (string comparisons), and a parameter error wouldn't be detected until runtime. (I didn't check for it in my version, but it could be added and checked for at compile-time.)
If the CH part can be any expression of char type, forget it - I don't think a macro hack is possible for that.
Not without preprocessor string-handling capabilities I think (which we might want to add in the future) ...
Frank
Frank Heckenbach wrote:
Gale Paeper wrote:
Oh dear, I'm quite shocked. Why do people make up such strange things? They could easily have made two separate routines (say `ScanEQ' and `ScanNE' -- this might be what can be implemented reasonably in GPC, with different syntax (*)) -- it would have taken them just one more predefined identifier instead of a completely irregular new syntax rule ...
I'm not sure where in the chain from Apple's UCSD Pascal to MPW Pascal the change was made, but in MPW Pascal `ScanEQ' and `ScanNE' is provided instead of Scan.
Even the same names that I'd just made up? :-)
Yep. Although they're documented with a lower case spelling but that's irrelevant for Pascal.
[snip]
How about:
{$define Scan(A, B, C) repeat
Scan in UCSD Pascal is a function, so a compatibility macro must be usable as a function.
That B parameter is so demented that it causes mind rot. Completely forgot about the function aspects.
var ScanExpression : string(4) value (#B); if (Length(ScanExpression) = 4) and_then (index(ScanExpression,
'<>') = 1) then ScanNE((A),ScanExpression[4],(C))
BTW, would these parentheses actually be necessary in Pascal? Sure, it won't hurt to add them, but without the infamous comma operator of C, I think there could be no confusion here, anyway.
Probably not. Just a C macro rule of thumb bleeding over to Pascal usage.
else if (Length(ScanExpression) = 3) and_then (index(ScanExpression,
'=') = 1) then ScanEQ((A),ScanExpression[3],(C)) else ParameterError; until true;
`repeat ... until True'? (Without trailing `;', BTW.) Perhaps you've read/written too many C macros of the kind `do ... while (0)'.
In Pascal, however, `begin ... end' would seem simpler (in a statement context), wouldn't it? (One of my favourite arguments why semicolon as a separator is better, BTW. :-)
Been reading too many C macros.
[snip]
Also, your suggestion would shift quite some work to runtime (string comparisons), and a parameter error wouldn't be detected until runtime. (I didn't check for it in my version, but it could be added and checked for at compile-time.)
I was thinking that the only way a macro hack would work is if the B parameter was in a form where everything was compile-time constant expressions and all but one of ScanEQ , ScanNE, or ParameterError would get optimized away by the compiler.
In regards to ParameterError, that was more for completeness than anything else. At least to me, the only reason for this sort of macro hack is to aid in porting old, presumably correct code so there shouldn't be any errors to detect anyway (or at least one hopes so).
Adriaan van Os wrote:
The CH part can be an expression and it is quoted for char constants. I think it is (much) better to replace Scan by ScanEQ and ScanNE in the source code.
I agree. UCSD Scan is one of those things that is best left in the graveyard of bad ideas.
Gale Paeper gpaeper@empirenet.com
Gale Paeper wrote:
Frank Heckenbach wrote:
(*) Just a thought. Perhaps the syntax could be handled with more-advanced preprocessor features, in particular string handling. Something like:
{$define Scan(A, B, C) {$if MacroIsPrefix (<>, MacroTrim (B))} ScanNE (A, MacroRemovePrefix (<>, MacroTrim (B)), C) {$else} ScanEQ (A, MacroRemovePrefix (=, MacroTrim (B)), C) {$endif} }
How about:
{$define Scan(A, B, C) repeat var ScanExpression : string(4) value (#B); if (Length(ScanExpression) = 4) and_then (index(ScanExpression, '<>') = 1) then ScanNE((A),ScanExpression[4],(C)) else if (Length(ScanExpression) = 3) and_then (index(ScanExpression, '=') = 1) then ScanEQ((A),ScanExpression[3],(C)) else ParameterError; until true; }
Note: The above assumes the preprocessor treats #B like the C preprocessor does (i.e., string quotes the macro parameter) and that PEXPR parameter is required to be in the exact form that Adriaan cited
without quotes for CH. If the CH part is a quoted char constant, some adjustments are needed to take into accout the embedded quote characters. If the CH part can be any expression of char type, forget it - I don't think a macro hack is possible for that.
The CH part can be an expression and it is quoted for char constants. I think it is (much) better to replace Scan by ScanEQ and ScanNE in the source code. What would be helpful, of course, is a chapter in the manual "Porting from ..." as has already been done for Borland Pascal and partly for CodeWarrior/Think/MPW Pascal (see <www.microbizz.nl/gpcdiffs.html>).
Regards,
Adriaan van Os
Adriaan van Os wrote:
The CH part can be an expression and it is quoted for char constants. I think it is (much) better to replace Scan by ScanEQ and ScanNE in the source code. What would be helpful, of course, is a chapter in the manual "Porting from ..." as has already been done for Borland Pascal and partly for CodeWarrior/Think/MPW Pascal (see <www.microbizz.nl/gpcdiffs.html>).
Just write the chapter and send it to me. :-)
Frank