CompuServe Thread

#Baffled by Benchmark

39 messages in this thread
#96394From: Thomas HoladayDec 3, 1987 7:41 AM
I keep the Benchmark manuals next to my bed, read them on the subway, etc. but so much is so wierd! Why do I pass strings as Addresses? Is 'Address' another name for 'String'? Can't be! I can go Write("Hello"), Write() is looking for a string, but AddMenu() expects the menu name to be an Address. This is in SimpleMenus, yet! I had exactly the same sorts of trouble with TDI's M2 manuals; I'd read the definition modules and find only declarations, record structures, etc. but no verbs! It is beginning to dawn on me that in a multitasking universe, I should only be passing messages back and forth, and never actually command anything, and that's why there are no verbs, right? I came to Forth, Snobol4, and Modula-2 from what I thought was a strong background in UCSD Pascal. The first two supposedly exotic languages were a cakewalk compared to the supposedly derivative M2. I think Wirth blew it.
#96406From: Brian WaltonDec 3, 1987 10:35 AM
When you are asked to supply an adress, this address is used as a pointer to the string. You then put your string at that Address. In your AddMenu() instruction you give it an address also. This address id is used as a pointer to the Menu Structure that you have to create in order to give the system a description of your new menu. In multitasking one has to be a "Very nice programmer" and do everything with CALLS so that the system nknows whats going on. I found this idea of Structure's to be a great idea and make things easier to do. Hoped I helped. BRW……(-.-)
#96419From: Thomas HoladayDec 3, 1987 12:13 PM
Thank you for your help, Brian. How do I put a String at an Address? Isn't it already in my executable? If I have in my source code foo := "ABCD"; then somewhere in my object exists the hex sequence 41$ 42$ 43$ 44$ 00$ (null terminated string). Am I supposed to know where that piece of object got loaded? Or can I pass the Address of foo, and have this interpreted as the address of the string to which foo points? Strings are rogue elements in strongly typed languages. I guess passing Addresses instead of the strings themselves allows a routine to deal properly with strings regardless of length, without having to declare ARRAY [0 … 255] OF CHAR for all strings, even short one.
#96439From: Brian WaltonDec 3, 1987 5:14 PM
My problem with answering that question is that I do not program in Modula 2, I am more or less an assembly language programmer. I don't n [D I don't know anything about M2. Your example looks some how familiar, do you know if , say in the Wt write() routine if you could do something like " Write (foo) " or are you saying that IS EQUAL to ABCD. Actually I'm kind of stumbling along here because as I said I know nothing about M2. You are correct about address passing being easier than ARRAY's By passing the pointr you can randomely change your string, and as long as it ends in NULL it will get printed, in most cases. Sorry I could not help you more, I'm sure someone who is an M@ M2 er will respond to your message. Pi~{ m{ BRW……….<*_*>
#96485From: John DraperDec 3, 1987 9:02 PM
But Thomas, you put 'foo' in the program, so you know where it is. Well, maybe not in real numbers that you can pick up, squeeze, pinch, and rub, but at least that there is a variable named 'foo', and that it MUST be at some address. You tell the compiler where it is by passing 'ADDRESS(foo)'. You can, of course use 'here_is_where_my_string_is := (ADDRESS)foo', and then pass it as 'here_is_where_my_string_is'. Hmm… hope I have the right operator there, ADDRESS vs. ADR, that is. Regards, Larry.
#96488From: Lloyd W. Dull IIIDec 3, 1987 9:24 PM
Larry, I *think* you ment ADR. An example would be how you use the "Execute" command imported from AmigaDOS. error := Execute(ADR("dir"),0,0); This passes the ADDRESS of the string "dir" to Execute – which just happens to be looking for a first parameter of TYPE ADDRESS. Lloyd
#96519From: Thomas HoladayDec 3, 1987 11:15 PM
ADR() will give me the address of an inline literal? So I don't need dummy variables? Hooray!
#97004From: Lloyd W. Dull IIIDec 6, 1987 5:23 PM
Thomas, Yep. Kind of a round-about way of doing it, but it works just like the sample code I left. Lloyd
#96492From: Thomas HoladayDec 3, 1987 9:44 PM
Seems to me like I can do Foo := 'ABCD' DoSomethingWith(ADDR(Foo)) but it is not permitted to DoSomethingWith('ABCD') so if I want to pass a string to a procedure, I _must_ assign it to a variable, a dummy variable, and the variable's address. No 'Inline' constant strings.
#96504From: John DraperDec 3, 1987 10:13 PM
Thomas, That's essentially correct. The thing is (as you pointed out), strrings are a bit of a kludge in many high level compiled languages, and even in C. Take a look at the way you define strings as arrays of characters, and also at the way you can pass open arrays (no implicit bounds) to procedures. Regards, Larry.
#96599From: Steve AhlstromDec 4, 1987 11:38 AM
Maybe it's a kludge, but waht Thol described works perfectly in C.
#96651From: John DraperDec 4, 1987 8:58 PM
Steve, Yes it does, and it will bite you occasionally too. Regards, Larry.
#96780From: Steve AhlstromDec 5, 1987 1:09 PM
It may bite you but in 3-4 years of using C (Lattice on the PC, MegaMax, Mark Williams, and Alycon on the ST, Lattice and Aztec on the Amiga) it's behaved exactly as expected.
#96655From: Thomas HoladayDec 4, 1987 9:16 PM
[Icy tone] The goal in language design is not to come up with something that _works_ since any common assembler can do that, but with an intuitive structure that requires zero learning. Human languages (so-called Natural Languages) 'work fine' yet contain gross redundancy and inconsistency. De l'Go demonstrated that any properly designed computer language can, in principle, be both complete and consistent. This was in a codicil to his essential work 'The Largest Integer(s).'
#96667From: Richard BielakDec 4, 1987 10:13 PM
Ah, Tom..the critical phrase is "in principal". There are many problems solvable "in principal", but when the real world interferes the solution is less than obious. For example, Newton had "in principal" solved the problem of navigation form Earth to the Moon. But it took engineers few hundred years to work out the details….Richie 🙂
#96731From: D. J. BAUCHDec 5, 1987 4:36 AM
I suppose I am jumping to C's defense…but, how are strings a kludge in C? I have programmed in many HOLs, and when I came to C, I remember saying to myself "At last, a language with a decent concept of strings." (This was after COBOL, Pascal, a little FORTRAN, and ALGOL). From previous messages in this thread, it looks like Modula-2 is not quite as comfortable doing all kinds of things with strings as C. A C programmer is quite comfortable with the fact that the address of a string is the same as the address of the string's first character, since strings are just "array of char" or "pointer to char", these being interchangeable in C. In C: char *mystring; /* or char mystring[]; */ mystring = "Hello World"; myfunc(mystring); means: Assign the address of the start of the string "Hello World" to mystring Call myfunc with mystring (the address of aforementioned string) and myfunc("Hello World") means call myfunc with the address of "Hello World" Perhaps in Modula-2: mystring := "Hello World"; myfunc(/*whatever the appropriate stuff is*/ mystring); means call myfunc with the address of "Hello World", while myfunc("Hello World") means: Call myfunc, pushing 12 characters in "Hello World" onto the stack for processing by myfunc? Am I way off here? It should be obvious by now that I don't know Modula-2 from JOVIAL. 🙂
#96745From: Thomas HoladayDec 5, 1987 7:21 AM
I no qualms about passing the address of a variable. Variables are fine things that the compiler knows about from the VAR section and has set up a lovely table of names and addresses to lookup at that time, long before they are encountered in any Procedure. The program fragment DoSomething(ADR('D. J. Bauch loves C but is not going to marry it')) shows me passing the address of an inline constant, and since that address seems to be dependent on the state of the machine at load time, it makes me feel a little queezy.
#96864From: John DraperDec 5, 1987 8:54 PM
Thomas, It's the same for your VARs… there is no fixed position for them in memory and they will be plunked in there at an address dependent upon the state of the machine at load time as well. Queasy/ Naw… just the fun of relocating loaders. Regards, Larry.
#97076From: Steve FaiwiszewskiDec 6, 1987 11:27 PM
Why get queezy? On a relocating loader machine nothing is ever the same. None of your code, variables or even constant is guaranteed to load in the same place. But what's the big deal? It's the same on most "sufficiently advanced" computers? Still feel queezy? Take Drammamine! – Steve –
#97144From: Thomas HoladayDec 7, 1987 12:23 PM
What makes me queasy is passing the address of an un-declared constant. In a language which supports Declaration sections, I expect the compiler to be making up its address tables _there_. When I hit it with an undeclared in-line constant, I expect it to compile the constant into the code. I expect foo := 2 + 3 to be compile to machine instructions loading the immediate value 2 into one register and immediate value 3 into the other, summing them, and punching them into the address denoted 'foo.' I do _not_ expect the compiler to make up two dummy variables, store 2 and 3 in them, and then generate instructions to retrieve the contents of dummy1 and dummy2.
#97318From: Art SteinmetzDec 8, 1987 10:34 AM
Whoops! See message #97136. It's meant for you, not Richie. — Art
#96863From: John DraperDec 5, 1987 8:46 PM
In many high level languages, a string is an array of characters for which library routines are written to handle them in special ways. Sounds like a kludge to me. Look at other languages where strings are a specific data type, and you'l see what i mean. Regards, Larry.
#96974From: Richard Rae/SYSOPDec 6, 1987 2:27 PM
<Funny look on face> Why would you want a specific data type? Seems to me as if the ultimate language would treat all the data the same way; I.E., a character string is a single dimensioned array is a group of type BYTE with a pointer is… This isn't a poke to start an argument. I'm wondering what I'm overlooking. Rick
#96997From: John DraperDec 6, 1987 5:10 PM
Rick, I did not mention untyped languages, but the principle is the same. A string is a data type in an untyped language just as much as it is in say, BASIC or COMAL. It's just that it's a string when you treat it as a string, and something elsewhen you don't. Why would _I_ want a specific data type? Well, it beats the heck out of having to treat it as another data type and write rotuines to handle it as if it were really the type I wanted in the first place. Regards, Larry.
#97266From: Dave HaynieDec 8, 1987 12:27 AM
Some are more kludgy than others. In fact, built-in strings are often as bad as character arrays, as they share many of the failings. There are, in my experience, two basic types of string implementations; counted strings and terminated strings. C uses terminated strings; a string is a character pointer or array, it's composed of all characters up to the terminating NUL character. It can be any length, but can't contain the NUL character. The other kind is usually implemented in PASCAL and is the counted string, of which BCPL strings are a type. The counted string can contain all characters, and is basically a structure with a count and string field, the string field being an array of characters. Typically, Pascal string implementations are weak in that Pascal doesn't easily support variable sized arrays. So you allocate a string, and it takes up the maximum string length, no matter it's length. It also means that it's easy to find the length, but it probably takes longer to do any manipulation. Some BASICs have this problem. The BCPL problem is that the count field is a BYTE, so strings can't be over 255 characters long. C type strings can be any length, though the length has to be computed. They can very easily be dynamically created by program or statically allocated by compiler, as char * is a much more standard type than a thing like RECORD len : BYTE; str [1..magiclen] : ARRAY OF CHAR; END;. Of course, languages like BASIC tend to have everything built-in, as opposed to C, which has very little built in. BASIC strings, and to a greater degree ICON and SNOBOL strings, are dynamically allocated and transparent to the user. They also tend to be slow, and require some kind of garbage collection. C type strings with the standard C string library aren't dynamic, but it's rather simple to make them so, without changing any existing functions, with the addition of a few allocation, reallocation, and garbage collection functions. I've even seen this done in PASCAL, though not so cleanly. -Dave
#97075From: Steve FaiwiszewskiDec 6, 1987 11:26 PM
There's the whole problem! C does not differentiate between an array and a pointer. This is certainly untyped and "messy" (not to mention dangerous). Modula-2, in my opinion, has a better approach, but if you really want to, it can behave just like C. – Steve – s
#97278From: Dave HaynieDec 8, 1987 1:05 AM
That's how the non-C person looks at it. My personal viewpoint is that there really aren't any arrays in C. There is, however, this operator, "[x]", which will index and dereference a memory element given a proper pointer to that block of memory. -Dave
#97481From: Vic WagnerDec 9, 1987 3:39 AM
Dave, exactly like the ! operator in BCPL
#96587From: Steve FaiwiszewskiDec 4, 1987 9:48 AM
Come on Tom! I'm surprised by you! The requirements to pass some parameters as addresses has nothing to do with Modula-2 or any high level language (HLL for short), but it has to do with what the ROM Kernel routines want to see. In numerous instances these routines want to get a pointer (same as address) to a string or some other data structure. In Modula-2 you can find the address of any variable using the ADR function. So ADR(foo) gives you the address of 'foo'. According to the strict M2 language definition, if you want to pass a string to a RK routine by address you would have to do the following: foo := 'Hello There'; SomeRKroutine(ADR(foo)); But Benchmark relaxes that a bit and lets you do SomeRKroutine(ADR('Hello There')) (which is really kind of weird, but save you the trouble of creating another variable). One thing to watch out for is because of this relaxation of the language definition, you can pass the address of a constant to some routine which might think that this is a string that it can change, and you end up changing a constant(!!!!!). Watch out for this!! Anyway, Wirth did NOT blow it, and string handling is not so bad in Modula-2 (although it could have been better). One last thing: The manuals for TDI and Benchmark are mostly there to document the interface to the RK routines, and nothing else. They are certainly no substitute for the RKM and Intuition manuals or some good M2 books. Hope this helped – Steve – (Wheww)
#96645From: Thomas HoladayDec 4, 1987 7:56 PM
Ok, I've spent some more time with Volume One of the documentation/manuals, and sure enough, there's the ADR function in full glory ADR("Hello World") so Shame On Me. Still pretty counterintuitive. I mean, what is the compiler _doing_ there? [Enter reading the compiler's mind mode ] DoSomething(ADR("Hi Pal")) hmm that means I do a little inline constant here ok where am I STAB Hi Pal now put that in the register and Jump to Do Something.
#97068From: Steve FaiwiszewskiDec 6, 1987 11:07 PM
You're on the right track. In the pure language definition, constants are NOT variables. Therefore they cannot be modified and they do not (theoretically) take space and therefore don't have an address. Hovewever, reality IS different, and those string constant must be stored somewhere in the code (so you'r right about the in-line code bit). Therefore, Benchmark gives you the unorthodox ability to find the address of this constant and use that. By the way, passing parameters to procedure does NOT mean thos parameters must reside in registers; they can also (and usually are) passed on the stack. – Steve –
#96665From: Richard BielakDec 4, 1987 10:08 PM
Tom, the problems you are running into are due to the fact that Intuition was written in C. To a "C" program strings are accessed via pointers (loosely speaking) and Modula-2 must conform to C standard. An ADDRESS in Modula-2 is just like an ADDRESS in assembler. You know, the number assigned to each memory location. There is one more thing here…when you pass a string to a procedure that sets up a menu the string must exist after the procedure is done. So the string must be passed as VAR parameter. Now a you can't pass a constant (!) as a variable (!). So the way to get around this dilema is to pass the address of the constant….. …I don't think I'm explaining it to well…if you really have more questions, give me a call I'll be happy to tell you all you want to know….Richie
#96741From: Thomas HoladayDec 5, 1987 6:32 AM
Ahh, some light is dawning. When I pass a string to a menu, AmigaDOS sez "gee, the guy's already got that doggone thing somewhere in memory since it's living in his program, so why should I make another copy just to splatter onto the screen? I'll just use his original. A byte saved is a byte earned." Now here I was, a diskette full of menu titles, all set to begin a loop which would read the first title into a little buffer, set up a menu, read the next title into the buffer, set up another menu, until EOF; and _now_ I learn that this important application is _impossible._ Oh woe is me.
#97136From: Art SteinmetzDec 7, 1987 8:45 AM
What is impossible? You can read menu labels from a disk file and use them "on the fly." Passing constants is not mandatory. … VAR foo : SomeStringType; BEGIN MyMenuFileRead(foo); (* where foo is a string read from a file *) AddMenuItem(ADR(foo)); (* any other params. needed for this? *) (*etc.*) … That oughta be just groovy. — Art
#97435From: Thomas HoladayDec 8, 1987 11:50 PM
But, if I'm passing the _address_ of foo, and foo changes the next time I go through the loop and read in another name from disk, won't my menu change, too?
#97615From: Vic WagnerDec 10, 1987 4:27 AM
Thomas, Of course. The data for menus must be in chip ram whenever the menu can be activated. You cannot share buffer space for the text.
#97624From: Thomas HoladayDec 10, 1987 6:45 AM
So that means the loop: LoopTop Foo := NextMenuName(MenuFileName) SetupMenu(ADR(Foo)) GOTO LoopTop builds an infinite number of menues with the same, changing name.
#98103From: Steve FaiwiszewskiDec 12, 1987 9:59 PM
Sheesh!! The turnaround here is so fast that I've missed the beginning of this thread, and I was only away for 3 days!!! So I can't be sure what exactly you're talking about, but from the code fragment you posted it looks dangerous to me. The 'SetupMenu' and 'NextMenuName' calls don't look familiar to me. What do they do? Depending on how SetupMenu works, your code may or may not work properly. – Steve –
#98102From: Steve FaiwiszewskiDec 12, 1987 9:55 PM
I don't think that data for menus have to be in CHIP RAM. As far as I know only IMAGE data must reside there. – Steve –