SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00013 DATA TYPE & COMPARE ROUTINES 1 05-28-9313:37ALL SWAG SUPPORT TEAM BIGARRAY.PAS IMPORT 11 {π>Do you know if the 64k Array limit still holds True when compilingπ>under protected mode in BP7?ππ>...The answer is yes, however the limit is 64K (or 65,521 Bytesπ>to be more exact ie: < 65,535 Bytes) per data element. (ie: Youπ>can create an Array of 1..N of 64K elements, using an Array ofπ>Pointers.)ππ>But you can do *that* in Real mode.ππ ...Yes, but try building something like this:π}πUsesπ Crt;ππTypeπ ar_64K = Array[1..65521] of Byte;π po_ar64K = ^ar_64K;π ar_Po64K = Array[1..200] of po_ar64K;ππVarπ by_Index : Byte;π Buffer : ar_Po64K;ππbeginπ ClrScr;π by_Index := 0;π While (MaxAvail > SizeOf(ar_64K)) doπ beginπ Inc(by_Index);π New(Buffer[by_Index]);π GotoXY(1,1);π ClrEol;π Write('Maximum Memory Available: ', MaxAvail);π Delay(300);π end;πend.π{π ...Using the DPMI HEAP (and calling the correct DPMI Functionπ to use your hard disk as virtual memory, unless you do haveπ 16Mb in your PC) you can allocate all 200 64K chunks of memory.π With the "Real mode" HEAP, you'd be lucky to be able to allocateπ 9 of these 64K chunks.ππ ...It also means that you can use this DPMI HEAP to run HUGE .EXE's,π as it can be used For either CODE or DATA. So you can forget aboutπ overlays, as you won't need them anymore.π}π 2 05-28-9313:37ALL SWAG SUPPORT TEAM BIGHEAP.PAS IMPORT 33 { ...Here is a demo Program that will read-in up to 15,000 Recordsπ onto the HEAP memory pool.π}ππ{$A+,B-,D+,E-,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V-,X-,Y-}π{$M 4096,0,655360}ππProgram Large_Array_Structure_Demo;ππTypeπ (* Type definitions. *)π st_8 = String[8];π inar_4 = Array[0..4] of Integer;ππ rc_zlog = Recordπ date : String[8];π userbaud : inar_4;π active : Integer;π calls : Integer;π newusers : Integer;π pubpost : Integer;π privpost : Integer;π netpost : Integer;π criterr : Integer;π uploads : Integer;π downloads : Integer;π uk : LongInt;π dk : LongIntπ end;ππConstπ (* Maximum number of Records to read-in. *)π co_rcMax = 15000;π (* Byte size of 1 Record. *)π co_rcSize = sizeof(rc_zlog);ππTypeπ (* Pointer of zlog Record Type. *)π porc_zlog = ^rc_zlog;π (* Array of 15,000 of zlog-Record Pointers. *)π poar_15K = Array[1..co_rcMax] of porc_zlog;ππVarπ (* Use to store "ioresult" value. *)π by_Error : Byte;π (* Loop control Variable. *)π wo_Index,π (* Total number of Records in the data File. *)π wo_RecTotal,π (* Number of Bytes read using "BlockRead" routine. *)π wo_BytesRead : Word;π (* Pointer to mark the bottom of the HEAP. *)π po_HeapBottom : Pointer;π (* Array of 15,000 zlog-Record Pointers. *)π poar_RcBuffer : poar_15K;π (* File Variable to be assigned to the data File. *)π fi_Data : File;ππbeginπ (* Try to open the data File. *)π assign(fi_Data, 'ZLOG.DAT');π {$I-}π reset(fi_Data, 1);π {$I+}π (* Check For File errors. *)π by_Error := ioresult;π if (by_Error <> 0) thenπ beginπ Writeln('Error ', by_Error, ' opening ZLOG.DAT File');π haltπ end;ππ (* Calculate the number of Records in data File. *)π wo_RecTotal := (Filesize(fi_Data) div co_rcSize);π (* Initialize loop control Variable. *)π wo_Index := 1;π (* Record the address of the HEAP "bottom". *)π mark(po_HeapBottom);π (* While free memory is greater than size of 1 Record *)π While (maxavail > co_rcSize)π (* And, not all Records have been read in... *)π and (wo_Index < wo_RecTotal)π (* And, less than maximum number of Records to read-in. *)π and (wo_Index < co_rcMax) doπ beginπ (* Allocate room For 1 Record on the HEAP. *)π new(poar_RcBuffer[wo_Index]);π (* Read 1 Record from data File into new HEAP Variable. *)π blockread(fi_Data, poar_RcBuffer[wo_Index]^, co_rcSize, wo_BytesRead);π (* Check For "BlockRead" error. *)π if (wo_BytesRead <> co_rcSize) thenπ beginπ Writeln('BLOCKREAD error!');π haltπ end;π (* Advance loop control Variable by 1. *)π inc(wo_Index)π end;π (* Close the data File. *)π close(fi_Data);π (* Display the amount of free HEAP memory left. *)π Writeln('Free HEAP memory = ', maxavail, ' Bytes');π (* Display the number of Records read onto the HEAP. *)π Writeln('Records placed on the HEAP = ', wo_Index);π (* Release all the HEAP memory used to store Records. *)π release(po_HeapBottom);π (* Display the amount of free HEAP memory left, again. *)π Writeln('Free HEAP memory = ', maxavail, ' Bytes');ππend.π 3 05-28-9313:37ALL SWAG SUPPORT TEAM BOOLS.PAS IMPORT 15 {π This is a small Unit I wrote when I got tired of writing great gobsπ of nested "if thens" or pages of parenthetic blobs.π With this Unit you can Write as many Boolean expressionsπ as you like as a block of Boolean.π True mode:π all interior expressions must be True For the block to be True.π if one interior expression is False then the block is False.π False mode:π all interior expressions must be False For the block to be False.π if one interior expression is True then the block is True.π Any ideas on enhancing it?π}πUsesπ Crt;ππConstπ AllBool : Boolean = True;π BoolMode : Boolean = True;ππVarπ S : String;ππProcedure SetBool(Mode : Boolean);πbeginπ AllBool := Mode;π BoolMode := Mode;πend;ππProcedure Bool(Expression : Boolean);πbeginπ if ((BoolMode) and (not Expression)) thenπ AllBool := False;π if ((not BoolMode) and (Expression)) thenπ AllBool := True;πend;ππbeginπ ClrScr;π S := '1 This is the best there is \.'; {init. String}π SetBool(True); {set checkmode For all True}π Bool( Length(s) > 4 ); {series of Boolean expressions}π Bool( s[3] in ['A'..'Z'] );π Bool( Ord(s[1]) - 48 < 10 );π Bool( Pos('This', s) > 0 );π Bool( s[Length(s)] = '.');π Bool( 2 + 3 = 5);π if AllBool thenπ Writeln('1. All expressions are True')π elseπ Writeln('1. At least one expression is False');ππ SetBool(False); {set checkmode For all False}π Bool( Length(s) > 44 ); {series of Boolean expressions}π Bool( s[3] in ['a'..'z'] );π Bool( Ord(s[1]) - 48 > 10 );π Bool( Pos('This', s) = 0 );π Bool( s[Length(s)] = 'g');π Bool( 2 + 3 = 4);π if not AllBool thenπ Writeln('2. All expressions are False')π elseπ Writeln('2. At least one expression is True');π Readln;πend.π 4 05-28-9313:37ALL SWAG SUPPORT TEAM COMPARE.PAS IMPORT 4 {πSEAN PALMERππgeneric compare Function...πmake sure to keep garbage out of Strings (by filling With #0πbefore storing the Strings) and you can compare ANY data With this.π}ππFunction equal(Var m1, m2; siz : Word) : Boolean; Assembler;πAsmπ push dsπ cldπ les di, m1π lds si, m2π mov cx, sizπ xor al, alπ repe cmpsbπ jne @Sπ inc alπ @S:π pop dsπend;π 5 05-28-9313:37ALL SWAG SUPPORT TEAM FUNCPARA.PAS IMPORT 7 This is legal syntax For Turbo/Borland Pascal v.6 and above:ππTypeπ MathFunc = Function (x:Real):Real;ππ Function MyFunc(x:Real):Real;π beginπ MyFunc:=2 * Sin(x) + Cos(x);π end;ππ Function YetAnother(x:Real):Real;π beginπ YetAnother:=Sqr(x) + x/2 + 1;π end;ππ Function AreaUnder(f:MathFunc; Lo, Hi:Real; Steps:Integer):Real;π Varπ sum,π x,π dx : Real;π i : Integer;π beginπ dx:=(Hi-Lo)/Steps;π sum:=0;π x:=Lo;π For i:=1 to Stepsπ do beginπ sum:=sum + f(x);π x:=x + dx;π end;π end;ππ beginπ Writeln(AreaUnder(MyFunc, 0, 2*PI, 360));π Writeln(AreaUnder(YetAnother, -1,1, 100));π end.ππ 6 05-28-9313:37ALL SWAG SUPPORT TEAM MULTITYP.PAS IMPORT 16 {π>Is is Possible to have a File of Two different Record Types?π>How would one do this? I have seen it done..ππFirst, don't Declare the Type of the File, just use a Type or File.ππDeclare Pointer Variables For each Type that the Record can be. if you wantπthe Record to hold a Value that says what the Record Type is, then device anπID scheme, and make sure the ID Variables are physically located at the sameπPosition in both Records.πππRead that data into a buffer Record With BlockRead. Assign the TypedπPointers to that buffer, and process away....π}ππTypeπ onerec = Record { Record size is 98 Bytes }π id : Byte; { We will set ID = 1 For onerec }π Username : String[80];π Phone : String[15];π end;π anotherrec = Record { Length is 163 Bytes }π id : Byte; {We will set ID = 2 For anotherrec }π ADDRESS1 : String[80];π ADDRESS2 : String[80];π end;ππVarπ ONE : ^ONEREC;π AnotHER : ^AnotHERREC;π Buffer : Array[1..163] of Char; { The size of the largest Record }π F : File;π NumRead : Word;π ID : Byte Absolute Buffer; { ID points to the first Char begin}πbeginπ Assign(F,'FileNAME');π Reset(F,SizeOf(Buffer));π One := @BUFFER;π AnotHER := @BUFFER;π BlockRead(F,BUFFER,SIZEof(BUFFER),NUMRead);π While NumRead > 0 Doπ beginπ Case ID ofπ 1 :π beginπ WriteLn('Record is of Type ONE');π WriteLn('USERNAME: ',ONE^.USERNAME);π WriteLn('Phone: ',ONE^.Phone);π end;π 2 :π beginπ WriteLn('Record is of Type AnotHER');π WriteLn('Address Line 1 = ',AnotHER^.ADDRESS1);π WriteLn('Address Line 2 = ',AnotHER^.ADDRESS2);π end;π elseπ WriteLn('Unidentified Record Type');π end; { of Case }π BlockRead(F,BUFFER,SIZEof(BUFFER),NUMRead);π end;π Close(F);πend.ππ 7 05-28-9313:37ALL SWAG SUPPORT TEAM SAVEDATA.PAS IMPORT 11 {π>I have a question about Typed Constants. By this I mean theπ>following declaration:π>π> Constπ> Example : Byte = 1;π>π>What are the advantages to this?ππ ...One of the advantages to using "Typed Constants", is that itπ allows you to initalize Variables at CompILE-TIME (ie: When youπ Compile your source-code into an .EXE), instead of RUN-TIME.π (ie: When your Program is actually running.)ππ ...Another advantage is that "Typed Constants" within Functions/π Procedures keep their data between calls.π}ππProcedure SaveData({input} Var DataBuffer : byar_Data);πConstπ bo_FileOpen : Boolean = False;πbeginπ if (bo_FileOpen = False) thenπ beginπ assign(fi_Data, st_DataName);π {$I-}π reset(fi_Data, 1);π {$I+}π Check_For_IO_Error;π bo_FileOpen := Trueπ end;π blockWrite(fi_Data, DataBuffer, sizeof(DataBuffer));π Check_For_IO_Errorπend;ππ{π ...The Procedure above would only open the data-File once,π and all Repeat calls to this Procedure would just Writeπ there data to the File. (ie: The Boolean "Typed-Constant"π bo_FileOpen would only be False the first time this routineπ executed. The next time this routine executed bo_FileOpenπ would be equal to True.)π}ππ 8 05-28-9313:37ALL SWAG SUPPORT TEAM TYPECAST.PAS IMPORT 24 (*π> Hi, I am a begginer Programer (I taught myself) and I am writing aπ> sort of "matching Program" my problem is: is there a way to give toπ> Variable two values of diffent Types (a Variable called X1 wouldπ> have one Char Type and hold a Integer value at the same time)?ππ Yes. There is more than one way to do this, using Turbo Pascal.ππ The most familiar way is by using the "Type-transfer" Functions:ππ orD() { transfer Char value to Word|Integer }π CHR() { transfer Word|Integer to Char "ππ Similar to this, there is also "Type-casting." to use this methodπ you just put the Variable to be changed inside of brackets thatπ specify the Type wanted (see example below).ππ A third way is to use "free unions," which look like Records. Again,π the example code, below, is the best way to show you.ππ Experiment With this example code. if you still have problemsπ after, show me an example of what you are trying to do ...π*)ππ(*******************************************************************)π Program Example; { Compiler: Turbo & Quick Pascal }π { Feb.17.1993, Greg Vigneault }ππ { Examples of Type-transfer, Type-cast, and free unions ... }ππ Type CharInt = Record { the free union }π Case Word ofπ 0 : ( Ch : Char );π 1 : ( Int : Integer );π end;ππ Var myVar :CharInt; { a free union Var }π bVar :Byte; { unsigned 8-bit }π cVar :Char; { a Character }π iVar :Integer; { signed 16-bit }π wVar :Word; { unsigned 16-bit }π beginπ { examples using "Type-transfer" Functions ... }ππ bVar := 65; WriteLn( bVar ); { Byte value }π cVar := CHR( bVar ); WriteLn( cVar ); { displays 'A' }π iVar := orD( cVar ); WriteLn( iVar ); { Char to Integer }ππ { examples using "Type-casting" ... }ππ cVar := Char( bVar ); WriteLn( cVar ); { cast Char to Byte }π bVar := Byte( cVar ); WriteLn( bVar ); { cast Byte to Char }π iVar := Integer( cVar ); WriteLn( iVar ); { Char to Integer }ππ { examples using a "free union" ... }ππ myVar.Ch := 'A'; { assign as Char }π WriteLn( myVar.Int ); { display Integer }π myVar.Int := 48; { assign Integer }π WriteLn( myVar.Ch ); { display Char '0' }ππ end {Example}.π(*******************************************************************)π 9 05-28-9313:37ALL SWAG SUPPORT TEAM TYPECST2.PAS IMPORT 8 > Yes LongInts are as you say from approx -2bil to +2bil. I'dπ > say what is happening here is that you are adding twoπ > Integers & assigning the result to a LongInt. Consider theπ > following :-ππ > Varπ > v1, v2 : Integer;π > Res : LongInt;ππ > beginπ > v1 := 30000;π > v2 := 30000;π > Res := v1 + v2;π > end;ππ > This will not give Res = 60000, because as Far as I am awareπ > TP only does Type promotion to the RHE Until the actualπ > assignment operation. What this means is that the sum of v1π > & v1 must yield an Integer since the largest Type to containπ > each is an Integer. Adding two Integer 30000 numbersπ > together caUses an overflow & ends up being a random-ishπ > number, usually negative. So what must be done here isπ > Typecasting. This should fix it :-ππ > Res := LongInt(v1) + LongInt(v2);π 10 05-28-9313:37ALL SWAG SUPPORT TEAM TYPEFILE.PAS IMPORT 8 ->> You could also open the File as unTyped :-), and use blockRead toπ ->> read big chunks Until you've read (recSize * number of Records beForeππ PW> Can I do this even if the File is a Typed File to begin with? Howπ PW> would I do it? Thanks For the info.πππYou can close it and reopen it, just use two Variables:ππ Varπ uf: File;π tf: File of gummi_bear;πππ beginπ assign(tf, 'TEST.FIL');π reset(tf);π .π . (* do whatever you need the Typed File For *)π .π close(tf);π assign(uf, 'TEST.FIL');π reset(uf, 1); (* tell runtime lib that rec size is one Byte *)π .π . (* now it's unTyped, you can use blockread to *)π . (* read an arbitrary number of Bytes *)π close(uf);π end;ππ 11 05-28-9313:37ALL SWAG SUPPORT TEAM UNTYPED.PAS IMPORT 9 {π> It would be Really nifty if it were possible to have InVar beπ> unTyped in the Function, so that the call would pass the Type,π> but I can't figure this one out.ππHere is a small sample of code that demonstrates how to do what (Iπthink) you're wanting to do:π}ππTypeπ TypeID = (tByte, tInt, tLong, tReal, tStr);ππProcedure MultiType(Var InVar; InType : TypeID);ππVarπ b : Byte Absolute InVar;π w : Integer Absolute InVar;π i : LongInt Absolute InVar;π r : Real Absolute InVar;π s : String Absolute InVar;ππbeginπ Case InType ofπ tByte : WriteLn('Byte = ',b);π tInt : WriteLn('Integer = ',w);π tLong : WriteLn('LongInt = ',i);π tReal : WriteLn('Real = ',r);π tStr : WriteLn('String = ',s);π else WriteLn('Unknown Type!');π end;πend;ππ{πof course, the above is just an example and it doesn't actuallyπdo anything useful, but you should be able to adapt it to suitπyour purposes.π}ππ 12 05-28-9313:37ALL SWAG SUPPORT TEAM VARARRAY.PAS IMPORT 8 {π> I'm trying to figure out a way to declair a Variable, such as anπ> Array, and I don't know the size Until I've loaded the Program.π> I've tried stuff like........π>π> Typeπ> Buf : Array[1..1000] of Char;π> Varπ> Buffer : ^Bufπ> beginπ> Getmem(Buffer,xxx)πππHere's how:π}ππ{$R-} { <-- essential For this trick }ππTypeπ tFlexArray = Array[1..1] of Integer;ππVarπ pFlexArray : ^tFlexArray;π NumofElements,i : Integer;ππbeginπ Write('How many elements do you want in the Array? ');π readln(NumofElements);π getmem(pFlexArray, (NumofElements * sizeof(Integer)));π For i := 1 to NumofElements doπ pFlexArray^[i] := i;ππ Write('Test which element? (Will contain same value as index) ');π readln(i);π Writeln('Element ',i,' contains ',pFlexArray^[i]);πend.π 13 05-28-9313:37ALL SWAG SUPPORT TEAM VARARRY2.PAS IMPORT 10 {π> I'm trying to figure out a way to declair a Variable, such as anπ> Array, and I don't know the size Until I've loaded the Program.π> I've tried stuff like........π> Typeπ> Buf : Array[1..1000] of Char;π> Varπ> Buffer : ^Bufπ> beginπ> Getmem(Buffer,xxx)π}ππTypeπ TElement = LongInt ; { Here use your own }ππConstπ MaxElement = 65500 div Sizeof(TElement) ;ππTypeπ TElementArray = Array[1..MaxElement] of TElement ;π PElementArray = ^TElementArray ;ππVarπ i : Word ;π Elms : PElementArray ;ππbeginπ Write('How many of ''em do you feel like using ? :') ;π ReadLn(i) ;π if i>MaxElement thenπ beginπ WriteLn('That''s more than I can hold, sorry...') ;π Halt(1) ;π end ;π GetMem(Elms, i*Sizeof(TElement)) ;ππ { Now, use Elms^[1] to Elms^[i] }ππ FreeMem(Elms, i*Sizeof(TElement)) ;πend.ππ{πPlease note that the previous allows you to keep range checking on, but thatπdoes not garanty you any security : access to an element which's index isπgreater than i would cause no RTE, but writing to it will quite mess up thingsπin memory...π}