Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!tut.cis.ohio-state.edu!ucbvax!DIKU.DK!jensting From: jensting@DIKU.DK (Jens Tingleff) Newsgroups: comp.lang.modula2 Subject: Re: Clever way to deal with this? Message-ID: <9002151617.AA27873@skinfaxe.diku.dk> Date: 15 Feb 90 16:17:30 GMT References: <90043.054652MARK@UCF1VM.BITNET> Sender: daemon@ucbvax.BERKELEY.EDU Reply-To: Modula2 List Organization: The Internet Lines: 81 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