MARK@UCF1VM.BITNET (Mark Woodruff) (02/12/90)
Anyone know of a clever way to express this in Modula-2? I have a data structure consisting of a cardinal value followed by a variable number of characters. The cardinal indicates how many characters follow. How would you express this in Modula-2? mark ------- Bitnet: MARK@UCF1VM.BITNET Internet: mark@mamab.FIDONET.ORG UUCP: uunet!tarpit!libcmp!mamab!mark Fidonet: mark at 1:363/9.0
HJ647C@GWUVM.BITNET (Pete Davis) (02/13/90)
Mark, it sounds like you're going to need to make it a variable length dynamic structure. You'd have to have routines to allocate variable sized spaces in memory, kind of the equivilent of Turbo Pascals GETMEM and FREEMEM. As I'm just starting to get into Modula-2, I can't give you anything real specific right now. Sorry. _Pete Davis BitNet: HJ647C at GWUVM FidoNet: Pete Davis @ 1:109/138
UK4H@DKAUNI2.BITNET ("JAE ", Juergen A. Erhard) (02/13/90)
mark wrote: { lines DO taste fine, ya know. } > I have a data structure consisting of a cardinal value followed by a > variable number of characters. The cardinal indicates how many characters > follow. > > How would you express this in Modula-2? How DO you express that in, say, C. Or some other language (not a 4GL, OC) What I like to know is: Are you porting a program from another language to M2, or did you devise such a struct out of thin air? Anyway you want it, M2 is not the ideal language for such a struct. Some way (a kludge, to be honest) would be: type mytype=record numOfChars:CARDINAL; chars:POINTER TO ARRAY <0..Max> OF CHAR; end; Two notes: 1. The idea behind the whole thing is to Storage.ALLOCATE() (or some such) as much memory as needed to hold all chars. This would mean you have to do all ALLOCATE'ING/DEALLOCATE'ING by 'hand'. 2. Set square brackets for < and > (I'm sittin' in front of a grubby old IBM 3278 (sucks!), and it doesn't give me no squares...) Also set Max and mytype to your choice... Another way (but still kludge, and in some way more, in another less awkward than the first) type mytype2=record numOfChars:CARDINAL; chars:ARRAY <0..Max> OF CHAR; end; Again, replace <,> and Max, mytype2... Note: This needs no great care, BUT (there's always a BUT to everything, it seems) it needs the same fixed amount of storage all the time, no matter how much of it is used. Of course, the latter is more of a kludge: it's nonsense. Except if you absolutely need it (some OS'es are sooo demanding...). Why? Well, M2 has (limited...) support for strings. But you can look up the string support of M2 in any good M2 reference... (guess I wasted enough net bandwidth already...) > mark > ------- > Internet: mark@mamab.FIDONET.ORG > UUCP: uunet!tarpit!libcmp!mamab!mark > Fidonet: mark at 1:363/9.0 -jae ======================================================================== Juergen A. Erhard eMail: uk4h@dkauni2.bitnet phone: (+49) 721/591602 "You know that it's monday when you wake up and it's tuesday." Garfield DISCLAIMER: none, I don't speak legalese.
MARK@UCF1VM.BITNET (Mark Woodruff) (02/13/90)
In article <"90-02-12-20:09:32.76*UK4H"@DKAUNI2.BITNET>, "JAE (Juergen A. Erhard)" <UK4H@DKAUNI2.BITNET> says: >mark wrote: >> I have a data structure consisting of a cardinal value followed by a >> variable number of characters. The cardinal indicates how many >> characters follow. >> >> How would you express this in Modula-2? >How DO you express that in, say, C. Or some other language (not a 4GL, >OC) Let's assume I want to print the characters in my buffer and that the number of characters run from one to MAX(CARDINAL): In 370 Assembly, I'd say: LH 2,COUNT LA 3,TEXT WRTERM (3),(R2) * BUFFER DSECT , COUNT DS H TEXT DS C In C, I'd say: struct { int count; char c; } buffer; for (i = 0; i <= count; i++) { putchar(&buffer.c+i); } In Smalltalk, I'd just create a class with count as an instance variable with byteIndexedInstanceVariables for the characters. In Modula-2, I said: TYPE BuffType = RECORD count: CARDINAL; text: CHAR; END; VAR buffer: BuffType; i: CARDINAL; charPtr: POINTER TO CHAR; BEGIN FOR i := 0 TO buffer.count DO charPtr := SYSTEM.ADDRESS(buffer.text)+i; InOut.Write(charPtr@) END; END; (note: I haven't actually tried to write this in assembly or C and I don't have my Modula-2 code at hand, so this is from memory) I'm not thrilled with this, but it's about the best equivalent to an equate or a pointer to a character I can get in Modula-2. >What I like to know is: Are you porting a program from another language >to M2, or did you devise such a struct out of thin air? I'm using this representation to represent buffers in an editor. The actual characters are fixed in length, but the length is entirely determined at run time. This arrangement is also the same as variable blocked records on standard labeled tapes. >Anyway you want it, M2 is not the ideal language for such a struct. >Some way (a kludge, to be honest) would be: > > type mytype=record > numOfChars:CARDINAL; > chars:POINTER TO ARRAY <0..Max> OF CHAR; > end; > >Two notes: > 1. The idea behind the whole thing is to Storage.ALLOCATE() (or some > such) as much memory as needed to hold all chars. This would mean > you have to do all ALLOCATE'ING/DEALLOCATE'ING by 'hand'. > 2. Set square brackets for < and > (I'm sittin' in front of a grubby > old IBM 3278 (sucks!), and it doesn't give me no squares...) > Also set Max and mytype to your choice... By the way, you can get brackets on almost any 3270 terminal by setting the right input and output translations. Send me mail if you want more info. > >Juergen A. Erhard mark ------- Bitnet: MARK@UCF1VM.BITNET Internet: mark@mamab.FIDONET.ORG UUCP: uunet!tarpit!libcmp!mamab!mark Fidonet: mark at 1:363/9.0
bailey%candide@GARGOYLE.UCHICAGO.EDU (Stephen Wilson Bailey) (02/13/90)
TYPE BufType = RECORD length: CARDINAL; data: ARRAY [0..MAX(CARDINAL)] OF CHAR; END; BufPtrType = POINTER TO BufType; VAR mybuf: BufPtrType; (* * Somewhere in this code you either malloc * the buffer, or cast something to it. *) . . . PrintBuffer(mybuf); . . . PROCEDURE PrintBuffer(bptr: BufPtrType); VAR curchar: CARDINAL; BEGIN FOR curchar := 0 TO bptr^.length DO Write(bptr^.data[i]); END; END; -------------------------------------- If you don't trust your compiler to optimize away the de-reference, using ``WITH bptr^ DO'' will usually force the issue ('though not always. Personally, I leave it up to the compiler). You're right, it isn't handled as well as it could be. The WRL Modula-2 includes a ``flexible array'' extension for just this purpose. I assume Modula-3 has a comparable notion. Steph
MARK@ECNCDC.BITNET (02/13/90)
I'm not sure this will work, because I have never tried it myself in a language like Modula-2, but I think that this (or very close to this) will take care of your problem for you: TYPE pRec = POINTER TO Rec; Rec = RECORD NumChars : CARDINAL; Chars : ARRAY [ 0..MAX( CARDINAL ) ] OF CHAR; END; VAR Data : pRec; Num : CARDINAL; BEGIN Num = { Some cardinal number }; ALLOCATE( pRec, SIZE( Num ) + Num ); (* assuming CHARs are 1 byte *) ... etc. You have to be careful not to do the following: 1) Don't have Rec as the type of any parameter, but always access it through the dereferencing of the pointer. 2) Don't rely on ANY Modula-2 string procedures, but always use NumChars for the integrity check. Hope this works for you, Mark Morrell Software Specialist Western Illinois University MARK @ ECNCDC
cmp8118@sys.uea.ac.uk (D.S. Cartwright) (02/13/90)
MARK@UCF1VM.BITNET (Mark Woodruff) writes: >Anyone know of a clever way to express this in Modula-2? >I have a data structure consisting of a cardinal value followed by a >variable number of characters. The cardinal indicates how many characters >follow. Well, how about some sort of RECORD structure thus : TYPE VarString : POINTER TO CHAR ; DataStructure : RECORD NoOfChars : CARDINAL ; Chars : VarString ; END (* RECORD *) ; You could then knock up some little routine to handle the creation and general all-round handling of the linked list of characters without too much hassle, and all should [!!!! }:^)] be hunky-dory. Dave C, SYS II, UEA, Norwich.
rxg3321@ultb.isc.rit.edu (R.X. Getter) (02/14/90)
In article <90043.054652MARK@UCF1VM.BITNET> Modula2 List <INFO-M2%UCF1VM.BITNET@PSUVM.PSU.EDU> writes: >Anyone know of a clever way to express this in Modula-2? > >I have a data structure consisting of a cardinal value followed by a >variable number of characters. The cardinal indicates how many characters >follow. you need a linked list of characters to handle this. TYPE string = RECORD numChars : CARDINAL; text : POINTER TO Node; END; Node = RECORD char : CHAR; next : POINTER TO Node; END; you will also need a bunch of utility procedures for manipulating this. also, the cardinal value isn't really needed unless you're using it as a reference. What are you doing? the only things I have ever seen which use a structure like this are basic interpreters. that's how they do strings. no sig yet, Robert Getter
TRL3@psuvm.psu.edu (Tim Larson) (02/14/90)
In article <90043.154337MARK@UCF1VM.BITNET>, MARK@UCF1VM.BITNET (Mark Woodruff) says: >In C, I'd say: > > struct > { > int count; > char c; > } buffer; > > for (i = 0; i <= count; i++) > { > putchar(&buffer.c+i); > } > >In Modula-2, I said: > > TYPE > BuffType = > RECORD > count: CARDINAL; > text: CHAR; > END; > > VAR > buffer: BuffType; > i: CARDINAL; > charPtr: POINTER TO CHAR; > > BEGIN > FOR i := 0 TO buffer.count DO > charPtr := SYSTEM.ADDRESS(buffer.text)+i; > InOut.Write(charPtr@) > END; > END; > >(note: I haven't actually tried to write this in assembly or C >and I don't have my Modula-2 code at hand, so this is from memory) > >I'm not thrilled with this, but it's about the best equivalent to >an equate or a pointer to a character I can get in Modula-2. > >I'm using this representation to represent buffers in an editor. >The actual characters are fixed in length, but the length is entirely >determined at run time. > Most Modula-2 systems won't like the address arithmetic, so it would be better to write TYPE BuffType = RECORD count: CARDINAL; text: ARRAY CARDINAL OF CHAR END; VAR buffer: BuffType; i: CARDINAL; charPtr: POINTER TO CHAR; BEGIN FOR i := 0 TO buffer.count DO charPtr := SYSTEM.ADR(buffer.text[i]); InOut.Write(charPtr:) END END; This is essentially what you wrote except for the use of ADR and the use of i as an index into buffer.text, which required a change in the type definition. This is according to PIM 3e Modula-2. I'm not sure what the upcoming standard will provide but I think JPI's M2 would be a little more succinct TYPE bufType = RECORD count: CARDINAL; text: ARRAY CARDINAL OF CHAR END; VAR buffer: bufType; i: CARDINAL; BEGIN FOR i := 0 TO buffer.count DO IO.WrChar (CHAR([ADR(buffer.text[i])]:)) END END ... Not a compelling reason to buy JPI's product, perhaps, but just a touch more elegant since it eliminates the need for the charPtr variable and probably speeds the compiled code up the tiniest fraction. In Modula-2, which relies on words more than symbols, you just will never get the bulk of this type of code down to C-size. On the other hand, it is more difficult to do something wrong and much easier to read. The other way to do this (if possible) is to null-terminate the string at location buffer.count+1 and simply use WriteString. TYPE bufType = RECORD count: CARDINAL; text: ARRAY CARDINAL OF CHAR END; VAR buffer: bufType; BEGIN IF buffer.count<MAX(CARDINAL) THEN buffer.text[buffer.count+1] := 0C END; InOut.WriteString (buffer.text) END ... Hope this adds something to the discussion. -Tim Larson trl3@psuvm.bitnet
jensting@DIKU.DK (Jens Tingleff) (02/16/90)
In comp.lang.modula2 you write: >Anyone know of a clever way to express this in Modula-2? >I have a data structure consisting of a cardinal value followed by a >variable number of characters. The cardinal indicates how many characters >follow. >How would you express this in Modula-2? >mark Well, I would use a C-like idea (phooey), and use pointers. Don't get me wrong, I prefer the strict checking of Modula-2 to the do-it-all-without-a-single-warning approach of C, but a job like this needs a little tricky code. Here goes (I Haven't tried it on a compiler incidently): The data structures are allocated using ALLOCATE explicitely. So, to get a pointer to an area with N chars, you do >VAR ptr : ADDRESS; >ALLOCATE(ptr, N + SIZE(CARDINAL)); (* Might need TSIZE *) To check the number of chars stored: >TYPE CardPtr = POINTER TO CARDINAL; >VAR nelems : CARDINAL; >nelems := CardPtr(ptr)^ ; To access the n'th char >TYPE CharPtr = POINTER TO CHAR; >VAR ch : CHAR; >ch := CharPtr(CARDINAL(ptr) + SIZE(CARDINAL) + n)^ ; This should work, as the ecplicit type transfer (but NOT size conversion) of `CharPtr()' and `CardPtr()' should put the type checking system to sleep. All this assumes that SIZE(CHAR) = 1, and that you don't hit any alignment problems. Off course all this is just a straight translation of the equivalent C code (which wouln't need the type transfers...). I used the >TYPE CharPtr = POINTER TO CHAR; VAR ptr : ADDRESS; ch : CHAR; > >BEGIN ptr := ....; > WHILE CharPtr(ptr)^ # 00C DO > ch := ptr^; > INC(CARDINAL(ptr)); > ........ to implement a C like StringCompare(), WHAM!! 30 % speed increase for dhrystone benchmark (on 8 bit CPM). The more civilised way is to make an upper limit for the number of chars, and then make a RECORD POINTER type, and NOT accessing more than the real number of chars.. . >CONST AllTheCharsINeed = 1000000; >TYPE VarSizeRec = RECORD cnt : CARDINAL; > elems : ARRAY [0 .. AllTheCharsINeed-1] > OF CHAR; > END; >TYPE VarRecPtr = POINTER TO VarSizeRec; >VAR ptr : VarRecPtr; > ALLOCATE(ptr, SIZE(CARDINAL) + N); (* N actual max. *) > ch := ptr^.elems[n]; (* Or whatever. *) The last has an arbitrary limit (get around this by stopping index check..). Anyway, I always think that if you need something as sticky as variable length, you're going to work hard to get it... . Jens
rxg3321@ultb.isc.rit.edu (R.X. Getter) (02/16/90)
In article <1294@sys.uea.ac.uk> cmp8118@sys.uea.ac.uk (D.S. Cartwright) writes: >MARK@UCF1VM.BITNET (Mark Woodruff) writes: > >Well, how about some sort of RECORD structure thus : > > TYPE > VarString : POINTER TO CHAR ; > > DataStructure : RECORD > NoOfChars : CARDINAL ; > Chars : VarString ; > END (* RECORD *) ; > > You could then knock up some little routine to handle the creation >and general all-round handling of the linked list of characters without too >much hassle, and all should [!!!! }:^)] be hunky-dory. > > Dave C, SYS II, UEA, Norwich. no, this won't work, you need VarString to be a pointer to a record, sometimes called node which contains a character and a pointer to a new node. then you can handle this as a linked list. The above will work in C, but not in modula2. try this: TYPE VarString = POINTER TO Node; Node = RECORD char : CHAR; next : VarString; END; (* node *) put this in with data structure, then be sure to set the terminating pointer to NIL and handle this like you would any linked list. don't forget to allocate memory with NEW() to get new nodes and deallocate it with DISPOSE() properly whenever you release a node. Robert Getter.
MARK@UCF1VM.BITNET (Mark Woodruff) (02/20/90)
Cute idea! I never thought of doing that. By putting an additional nul at the end of the buffer, you should be able to use all the standard Strings functions too! I knew there was a better way to work with these things than filling my code with SYSTEM.ADR() and SYSTEM.ADDRESS() calls. Thanks, mark
mac@HARRIS.CIS.KSU.EDU ("Myron A. Calhoun") (02/20/90)
In article <90050.112710MARK@UCF1VM.BITNET> you write: >Cute idea! I never thought of doing that. By putting an additional >nul at the end of the buffer, you should be able to use all the >standard Strings functions too! > >I knew there was a better way to work with these things than >filling my code with SYSTEM.ADR() and SYSTEM.ADDRESS() calls. I must have MISSED the clever way, although I did see (several weeks ago?) the original question. Can you email me a copy of the apparently-best solution? --Myron. -- #------------------------------------------------------------------------- # Myron A. Calhoun, Ph.D. E.E.; Associate Professor (913) 539-4448 home # INTERNET: mac@harris.cis.ksu.edu (129.130.10.2) 532-6350 work # UUCP: ...{rutgers, texbell}!ksuvax1!harry!mac 532-7004 fax # AT&T Mail: attmail!ksuvax1!mac