• No results found

Een filecabinet in Modula-2

N/A
N/A
Protected

Academic year: 2021

Share "Een filecabinet in Modula-2"

Copied!
26
0
0

Bezig met laden.... (Bekijk nu de volledige tekst)

Hele tekst

(1)

Een filecabinet in Modula-2

Citation for published version (APA):

Paulissen, G. J. L. M. (1988). Een filecabinet in Modula-2. (TH Eindhoven. Afd. Werktuigbouwkunde, Vakgroep Produktietechnologie : WPB; Vol. WPA0550). Technische Universiteit Eindhoven.

Document status and date: Gepubliceerd: 01/01/1988

Document Version:

Uitgevers PDF, ook bekend als Version of Record

Please check the document version of this publication:

• A submitted manuscript is the version of the article upon submission and before peer-review. There can be important differences between the submitted version and the official published version of record. People interested in the research are advised to contact the author for the final version of the publication, or visit the DOI to the publisher's website.

• The final author version and the galley proof are versions of the publication after peer review.

• The final published version features the final layout of the paper including the volume, issue and page numbers.

Link to publication

General rights

Copyright and moral rights for the publications made accessible in the public portal are retained by the authors and/or other copyright owners and it is a condition of accessing publications that users recognise and abide by the legal requirements associated with these rights. • Users may download and print one copy of any publication from the public portal for the purpose of private study or research. • You may not further distribute the material or use it for any profit-making activity or commercial gain

• You may freely distribute the URL identifying the publication in the public portal.

If the publication is distributed under the terms of Article 25fa of the Dutch Copyright Act, indicated by the “Taverne” license above, please follow below link for the End User Agreement:

www.tue.nl/taverne

Take down policy

If you believe that this document breaches copyright please contact us at:

(2)

Een filecabinet in Modula-2

G.J.L.M. Paulissen

WPA rapportnr. 0550

INF )

(3)

SAMENVATTING

De programmeertaal Modula-2 kent aIleen tekstfiles of binaire files.

Ret Modula-2 filecabinet zorgt ervoor dat ( representaties van )

recordfiles gecreeerd kunnen worden en dat daarop de

standaardoperaties ( records toevoegen, weglaten of veranderen en

recordfiles printen of copieren ) uitgevoerd kunnen worden.

Ret filecabinet bestaat uit 3 basismodules en 4 programmamodules.

De 3 basismodules zijn: Definitions ( definities van types en

procedures die afhangen van de implementatie van basistypes op de

gebruikte computer ), Safelo ( procedures voor invoer en uitvoer )

en Utilities ( procedures voor operaties op recordfiles ).

De 4 programmamodules zijn: Create ( creeren van recordfiles ),

Modify ( operaties op records in een recordfile ), Print ( voor output

van een recordfile ) en Copy ( copieren van recordfiles ).

ABSTRACT

In the programming language Modula-2 only text files or binary files are known. The Modula-2 filecabinet allows the user to create

( representations of ) recordfiles and to use the standard operations

on such recordfiles ( to store, delete or modify records and

to print or copy recordfiles ).

The filecabinet consists of 3 basic modules and 4 program modules.

The 3 basic modules are: Definitions ( definitions of types and

procedures which are dependent of the implemenation of basic types on

the computer used )f Safelo ( procedures for input and output ) and

Utilities ( procedures for operations on recordfiles ).

The 4 program modules are: Create ( to create recordfiles ) f

Modify ( for operations on records in a recordfile ), Print ( for

(4)

TECHNISCHE UNIVERSITEIT EINDHOVEN Faculeit Werktuigbouwkunde Vakgroep WPA 23 februari 1988 Stage-opdracht Hoogleraar Begeleider Toelicbtina G.J. Paulissen

Prof.dr.ir. J.E. Rooda Ir. W.C. Boot

In sterk getypeerde programmeertalen, zoals Pascal en Modula-2, is het lastig programma's te schrijven, die gelijksoortige operaties op meer dan een datatype kunnen uitvoeren. Met name is dit ook een probleem bij het

gebruik van files, waarin de gegevens in de vorm van "r~cords" zijn

ondergebracht.

Daarom is in het verleden in de taal Modulair Pascal een zogenaamd "File Cabinet" geschreven. Dit bestaat uit een aantal modulen. Gezamelijk

voorzien deze in een structuur die toegang geeft tot de gegevens in files, zonder dat het type van de records in de vorm van een declaratie bekend hoeft te zijn. In plaats daarvan wordt de type informatie opgeslagen in een aparte file. Tevens is er een aantal modulen dat van deze structuur gebruik maakt om diverse operaties op de records in de file te implementeren, zoals bijvoorbeeld sorteren. Vegens de veel grotere beschikbaarheid Modula-2 is er behoefte ontstaan aan en soortgelijk pakket in deze taal.

Opdracht

Ontwerp en implementeer in Modula-2 de modulen die de basisstructuur vormen voor een "File Cabinet". Bekijk daarbij kritisch welke verbeteringen

mogelijk mogelijk zijn ten opzichte van het bestaande "File Cabinet". Demonstreer de werking door oak een of meer modulen te maken die, gebruik makend van deze basis, een gebruiker interactief met het "File Cabinet" laten werken.

Het verslag dient in elk geval een goede handleiding te bevatten voor het

gebruik van de geproduceerde basismodulen. Verslaa, etc.

Het memorandum "Afstuderen in de Produktietechniek" is bij de secretaresse verkrijgbaar.

Prof.dr.ir. J.E. Rooda Ir. W'.C. Boot

(5)

VOORWOORD

van het verslag besloeg, die de stage plus het schrijven

september 1987 tim maart 1988.

Prof.dr.ir J.E. Rooda

: Ir.

w.e.

Boot

De stage is uitgevoerd bij de vakgroep Automatisering van de Produktie van de afdeling Werktuigbouwkunde aan de Technische Universiteit te Eindhoven.

De periode duurde van Hoogleraar Begeleider

(6)

INHOUDSOPGAVE SAMENVATTING ABSTRACT OPDRACHTSOMSCHRIJVING VOORWOORD INHOUDSOPGAVE 1. INLEIDING 2. OPZET 2.1. Uitleg 2.2. Ontwerpbeslissingen 3. CONCLUSIES LITERATUURLIJST APPENDIX A: Definities APPENDIX B: DOCUMENTATIE B.1: Module Definitions B.2: Module SafeIo B.3: Module Utilities APPENDIX C: HASHED RECORDFILES APPENDIX D: VOORBEELD

APPENDIX E: AANPASSING VAN MODULE DEFINITIONS

BIJLAGE ( LISTING VAN DE MODULES )

o

o

1 2 3 4 5 5 7 10 11 13 15 15 16 18 21 22 24

(7)

1. INLEIDING

De stage-opdracht handelt over het omzetten van het Modulair Pascal

filecabinet, zoals dat op een PDP-II bij de Technische Universiteit

Twente is geimplementeerd, naar een soortgelijke versie in Modula-2.

In Pascal kunnen weI recordfiles gedeclareerd worden, maar na

afloop van het programma wordt essentiele informatie over het

recordtype vergeten. Nu is dat waarschijnlijk geen probleem als men bij

de volgende keer van het runnen van het programma dezelfde soort files gebruikt.

In Modula-2 zijn geen andere files mogelijk dan tekstfiles of

binaire files, zodat als je een recordfile wilt gebruiken je daar iets

voor moet vinden. Het Modula-2 filecabinet geeft hier een oplossing

voor en zorgt er verder voor dat een programma bij verschillende runs met verschillende soorten recordfiles kan werken.

De hoofdstukken 1 tim 3 geven een globaal overzicht van het Modula-2 filecabinet en het ontwerp ervan. Als men nog meer over de materie wil

weten, dan wordt verwezen naar de appendices A tim E. Dit geldt in het

(8)

2. OPZET

2.1. Uitleg

Een recordfile bestaat uit een serie records van hetzelfde type.

Een Modula-2 recordfile ( verder aan te duiden met recordfile )

is een representatie van een gewone recordfile.

Een record uit een Modula-2 recordfile ( verder aan te duiden met

record) is een representatie van een gewoon record en kan leeg, in

gebruik ( vol ) of verwijderd zijn.

Daar snelle toegang tot records vereist kan zijn, kunnen hashed

recordfiles ( zie APPENDIX C ) gedeclareerd worden.

De andere mogelijkheid is het declareren van een sequentiele recordfile.

Random access tot een recordfile is mogelijk.

De velden van records van een recordfile mogen van de volgende types zijn: - integer cardinal long integer long cardinal real string array[O .. N] OF integer array[O .. N] OF cardinal

array[O .. N] OF long integer

array[O .. N] OF long cardinal

array[O .. N] OF real Copy: - Print: - Create: - Modify: - SafeIo: - Utilities:

Bij de opzet van het Modula-2 filecabinet is geprobeerd om globaal de opzet van het Modulair Pascal filecabinet te volgen.

Er zijn drie basismodules en vier programmamodules gemaakt, waarvan de vier progammamodules zelfstandig executeerbaar zijn.

De modules zijn:

- Definitions: Bevat definities van typen ( zie APPENDIX A ) en

procedures die eventueel veranderd moeten worden als het

filecabinet gebruikt gaat worden ( zie APPENDIX E ).

Bevat procedures voor invoer en uitvoer.

Bevat procedures voor het werken met en bewerken van recordfiles.

Creeert een nieuwe recordfile. Als de nieuwe

recordfile een hashed recordfile is, dan wordt ook nog om het maximum aantal records gevraagd.

Met deze module kunnen records uit de opgevraagde recordfile veranderd of verwijderd worden en nieuwe records toegevoegd worden.

Maakt een file, waarin de inhoud van de opgevraagde

recordfile komt, om die later te kunnen uitprinten.

Maakt van de opgevraagde recordfile een copie.

De copie heeft dezelfde soort records als de opgevraagde recordfile, maar de data wordt niet gecopieerd.

Als de recordfile een hashed recordfile is, dan wordt ook om het maximum aantal records gevraagd.

(9)

De hierarchie van de modules is als volgt:

iDefinitions Safelo Utilitiesi

I I I I I I I I I

'V

fig. 1

(10)

2.2. Ontwerpbeslissingen

1. Voor het bijhouden van een variabel aantal gegevens in een array,

is een 'dynamisch array' een array met variabele grootte ) handig.

Doordat Modula-2 net zoals Modulair Pascal geen dynamische arrays

kent, is gekozen voor een constructie die er op lijkt. In plaats van

een array te declareren, wordt een pointer naar een array van 1K

elementen gedeclareerd en m.b.v. de procedure ALLOCATE kan een deel

van het array gealloceerd worden.

De maximale geheugenruimte voor een gedeclareerd array is

hoogstens 64 Kbyte. Het maximaal aantal elementen voor een array van

real-waarden ( grootste basistype op de gebruikte computer ) zou 8K

mogen zijn ( 64 Kbytes / 8 bytes

=

8K ).

Voor types als CARDINAL en INTEGER zou een groter maximum gekozen

kunnen worden, maar vanwege de uniformiteit is gekozen voor

een

maximum. De keuze voor het maximum is zuiver arbitrair zolang het maar groot genoeg is en ten hoogste 8K.

De consequentie hiervan is dat er geen arrays van meer dan lK

elementen gebruikt mogen worden, maar dat lijkt in de praktijk ook niet echt nodig.

I.p.v. een pointer naar een groot array, zou er ook gewerkt

kunnen worden met een lijst van records welke verbonden worden door

pointers ( 'linked list' ), maar door deze werkwijze is random

access niet mogelijk.

2. Daar Modulair Pascal exception handlers kent maar Modula-2 niet, is er voor gekozen in procedures waarin iets fout kan gaan een

extra VAR-parameter Res ( 6f Result ) bij te houden die het

resultaat van de uitvoering van de procedure bijhoudt.

Als na executie van zo'n procedure NOT Res ( 6f NOT Result) geldt,

dan is er een fout opgetreden in de procedure 6f in een van de

binnen die procedure aangeroepen procedures. Deze oplossing is niet zo mooi als het gebruik van exceptionhandlers, maar voldoet weI. 3. Voor de opslag van allerhande gegevens omtrent een recordfile

tijdens de runtime van een programma, is het wenselijk om een

centrale datastructuur te hebben. De centrale datastructuur is

FcFile, gedefinieerd in de module Definitions. FcFile bevat een veld Descr van type FcDescr, veld F van het type File, veld Buf van het type Buffer en als laatste het veld LastKey dat aIleen gebruikt

wordt bij hashed recordfiles. FcFile lijkt op de definitie van het

type FcFile in het Modulair Pascal filecabinet, aIleen heeft het

type FcFile in het Modula-2 filecabinet een extra veld Buf. Het veld Descr bevat informatie over de records zoals: de

recordgrootte in bytes, het type recordfile (sequentieel (Dir) of

hashed (Hash) ) en voor elk veld in een record een beschrijving van

dat veld.

Het veld F is een representatie van een binaire file of

tekstfile door Modula-2. De file in veld F ( en na afloop van een programma in het achtergrondgeheugen ) ziet er als voIgt uit:

I) Ret eerste stuk is een descriptorgedeelte met achtereenvolgens:

- Ret aantal velden.

- De recordgrootte ( record inclusief het onzichtbare veld ).

- Ret type recordfile.

- Beschrijving van de recordvelden.

II) Ret tweede stuk is het datagedeelte.

Hierdoor is het veld F een representatie van een recordfile, want

(11)

recordfile: aantal velden (=N) recordgrootte type recordfile beschrijving recordveld 1 beschrijving recordveld 2 beschrijving recordveld N data fig. 2

Ook bevat FcFile nog een veld Buf van het type Buffer, dat

gebruikt wordt voor het opslaan van een record. In het Modulair

Pascal filecabinet had FcFile niet zo'n veld doordat via fc.fA

( fc van het type FcFile en f van type FILE ) access tot een record

werd verkregen, maar in Modula-2 is dat niet mogelijk.

Daarom was er een aparte datastructuur ( van type Buffer ) nodig

en het was logisch om daar een veld in FcFile voor te gebruiken zodat het record waar de recordfile naar wijst in dezelfde

datastructuur ( van type FcFile ) zit als de recordfile zelf.

En als laatste bevat FcFile nog een veld LastKey dat wordt

gebruikt bij hashed recordfiles. Dit veld houdt de laatst berekende startpositie, berekend door de locale procedure calchashkey, voor het zoe ken naar een record in de recordfile bij.

4. Omdat informatie over een recordveld bijgehouden moet worden. is

gekozen voor een type Field dat hiervoor zorgt. Dit type Field is ongeveer hetzelfde als het type Field in het Modulair Pascal

filecabinet, want er was geen reden om het anders te doen.

De informatie over aIle recordvelden wordt opgeslagen in een 'dynamisch array'. Er moet gelden:

( maximum aantal recordvelden )

* (

grootte type Field )

=

( maximum aantal recordvelden )

*

18 bytes <= 64 Kbytes.

Voor het maximum aantal velden in een record is 1K gekozen en het actuele aantal staat in het veld NrOfFields van FcFile.

De keuze voor het maximum is arbitrair zolang het maar groot genoeg en ook weer niet te groot is.

Bet recordtype Field beschrijft een recordveld: het veld Ident

bevat de naam van het te beschrijven recordveld in hoogstens 12

karakters, het veld Type bevat het type recordveld ( een van de 11

reeds beschreven types ), het veld Start bevat de eerste bytepositie

van het recordveld binnen een filerecord en het veld Len bevat de lengte van het recordveld.

(12)

5. Bij het verwijderen van records en bij het gebruik van hashed recordfiles heeft het gebruik van een onzichtbaar eerste veld

voordelen. Want bij het verwijderen van records hoeft men dat veld

aIleen maar een speciale waarde te geven die staat voor verwijderd

en bij het gebruik van hashed recordfiles wordt de hashpositie ( de

uitkomst van de locale functie calchashkey ) van een in gebruik zijnd record in het eerste veld opgeslagen.

Elk record in een recordfile heeft een onzichtbaar eErste veld

( dummyveld ) van het type CARDINAL. Als de waarde daarvan 0 is, dan

is dat record nog nooit gebruikt ( le2g ). Als de waarde daarvan

65535 is, dan is het record ooit gebruikt maar nu niet in gebruik

( verwijderd ). Een waarde tussen 0 en 65535 geeft aan dat het

record in gebruik ( vol) is. De gebruiker merkt hier echter niets

van en het lijkt net of er met een gewone recordfile gewerkt wordt. Bij een sequentiele recordfile heeft elk vol record een unieke

waarde ( n.l. de positie in de f i l e ) in zijn dummyveld.

Het gevolg is dat een sequentiele recordfile hoogstens 65534 volle

records kan bevatten ( nl. records waarvan de waarde van het

onzichtbare veld loopt vanaf 1 tim 65534 ). Ook een hashed

recordfile kan hoogstens 65534 volle records bevatten, want het

maximum aantal records ( <= 65534 ) wordt bij de declaratie

gevraagd.

De keuze voor 0 en 65535 als speciale getallen en niet

bv. 10 en 19 heeft te maken rre~ de grenzen van het type CARDINAL op

de gebruikte computer ( nl. 0 en 65535 ) en de locale functie

calchashkey ( die waarden aflevert vanaf 1 tim #recordplaatsen ) in

de procedure PosHash.

6. Omdat er geen reden was de maximale recordgrootte groter dan de

grootste CARDINAL ( 65535 op de gebruikte computer ) te kiezen, is

de recordgrootte ( opgeslagen in het veld Recordsize in Fc.Descr )

van het type CARDINAL en dus maximaal 65535. Het aantal velden dat de gebruiker opgeeft, wordt verminderd als de totale grootte groter dan 65535 is.

7. Omdat de gebruikte versie van Modula-2 geen long cardinals en geen

long integers kent, worden beide types afzonderlijk gerepresenteerd

door een recordtype met een Hi- en een Lo-veld. De waarde die door een record X van een van die twee recordtypes gerepresenteerd wordt,

is X.Hi*2A

(13)

3. CONCLUSIES

*

Verbeteringen t.o.v. het Modulair Pascal filecabinet:

- Een recordtype kan nu 1024 velden bevatten, tegen 25 in het

Pascal filecabinet.

- De beschrijving van het recordtype ( descriptor ) bevindt zich nu

in dezelfde file als waarin de data zich bevindt. In het Pascal

filecabinet bevonden de descriptors zich in een aparte file INDEX.FLC en de recordfiles zelf bevatten aIleen maar data.

Hierdoor kon o.a. het verwijderen en hernoemen van files niet door het Operating System geregeld worden, maar moest dat door aparte aparte modules gebeuren. Deze eenlaagse structuur van het Modula-2 filecabinet heeft een duidelijk voordeel boven de tweelaagse

stuctuur: er zijn minder procedures nodig.

- Door de opzet van Modula-2 ( o.a. scheiding modules in

definitiemodules en implementatiemodules ) en het gebruik van de hierboven beschreven eenlaagse structuur is het Modula-2

filecabinet overzichtelijker dan het Modulair Pascal filecabinet.

*

Het Modula-2 filecabinet heeft minder mogelijkheden dan het Modulair

Pascal filecabinet ( o.a. geen modules voor sorteren en concateneren

van recordfiles ), maar de basismodules bieden in principe dezelfde mogelijkheden als de de basismodules van het Pascal filecabinet.

*

Het Modula-2 filecabinet is geschikt om als interface te dienen.

De procedures die door de basismodules geexporteerd worden, kunnen

gebruikt worden in andere (programma-) modules.

*

Het Modula-2 filecabinet kan zonder veel aanpassingen op elke

(14)

LITERATUURLIJST

Wirth, N., 'Programming in Modula-2', Springer-Verlag, Berlijn, 1985

RoodaI J. E., Rossingh, T. J ., Bron, C., 'Pascal file-types and the

Modular Pascal File Cabinet', rapport nr. memo 38 ( Afd. der

Werktuigbouwkunde ), Technische Universiteit Twente, Enschede, 1984

Mulder, R.J., 'Supos', rapport nr. memo 44 ( Afd. der

Werktuigbouwkunde ), Technische Universiteit Twente, Enschede, 1985

DIA b.v., 'Het filcabsysteem', Datex, 's Hertogenbosch, 1987

Bron, C., 'Modular Pascal Language Definition' I memorandumnr. INF-82-10

( Onderafd. der Informatica), Technische Universiteit Twente,

(15)

APPENDIX A: Definities CONST MAX=1023; TYPE I16=INTEGER; U16=CARDINAL; 132=RECORD Lo:CARDINAL; Hi: INTEGER END; U32=RECORD Lo,Hi:CARDINAL END; STRINGPtr=POINTER TO STRING;

STRING=ARRAY[O .. MAX] OF CHAR;

ArrayOfI16Ptr=POINTER TO ArrayOf116;

ArrayOfI16=ARRAY[O .. MAX] OF 116;

ArrayOfU16Ptr=P01NTER TO ArrayOfU16;

ArrayOfU16=ARRAY[O .. MAX] OF U16;

ArrayOfI32Ptr=P01NTER TO ArrayOf132;

ArrayOfI~2=ARRAY[O.. MAX] OF 132;

ArrayOfU32Ptr=POrN~ERTO ArrayOfU32;

ArrayOfU32=ARRAY[O .. MAX] OF U32;

ArrayOfREALPtr=POINTER TO ArrayOfREAL;

ArrayOfREAL=ARRAY[O .. MAX] OF REAL;

FieldBuffer=RECORD CASE Kind:FieldType OF I16Field:I16Value:I16: U16Field:U16Value:U16: 132Field:I32Value:I321 U32Field:U32Value:U32: REALField:REALValue:REAL: STRINGField: STRINGValue:STRINGPtrI 116ArrayField:I16ArrayValue:ArrayOfI16Ptri U16ArrayField:U16ArrayValue:ArrayOfU16Ptrl 132ArrayField:I32ArrayValue:ArrayOfI32Ptr: U32ArrayField:U32ArrayValue:ArrayOfU32Ptrl REALArrayField:REALArrayValue:ArrayOfREALPtr END END; FieldBufferPtr=POINTER TO FieldBuffer;

FieldBufferArray=ARRAY[O .. MAX] OF FieldBufferPtr;

Buffer=POINTER TO FieldBufferArray; FieldType=(I16Field,U16Field,I32Field,U32Field,REALField, STRINGField,I16ArrayField,U16ArrayField, 132ArrayField,U32ArrayField,REALArrayField) ; FileType=(Dir,Hash) ; Field=RECORD Ident:ARRAY[O .. ll] OF CHAR; Type:FieldType; Start,Len:CARDINAL; END;

FieldArrayPtr=POINTER TO ARRAY[O .. MAX] OF Field;

(16)

FcFile=RECORD, NrOfFields:CARDINAL; Descr:FcDescr; Buf:Buffer; F:File; LastKey:CARDINAL END;

(17)

APPENDIX B: DOCUMENTATIE

Hieronder worden de procedures beschreven die geexporteerd worden uit de basismodules van het Modula-2 filecabinet.

B.1. Module Definitions

PROCEDURE ConvertI16 (In:ARRAY OF CHAR;VAR Out:I16;VAR Result:BOOLEAN); Converteert string In naar een overeenkomstige I16-waarde.

Postconditie: Result => de conversie is goed verlopen.

PROCEDURE ConvertU16 (In:ARRAY OF CHAR;VAR Out:U16;VAR Result:BOOLEAN); Converteert string In naar een overeenkomstige U16-waarde.

Postconditie: Result => de conversie is goed verlopen.

PROCEDURE ConvertI32 (In:ARRAY OF CHAR;VAR Out:I32;VAR Result:BOOLEAN); Converteert string In naar een overeenkomstige I32-waarde.

Postconditie: Result => de conversie is goed verlopen.

PROCEDURE ConvertU32 (In:ARRAY OF CHAR;VAR Out:U32;VAR Result:BOOLEAN); Converteert string In naar een overeenkomstige U32-waarde.

Postconditie: Result => de conversie is goed verlopen.

PROCEDURE WriteI16(In:I16;Width:CARDINAL); Voor output van I16-waarden.

Width geeft minimum lengte van het te printen getal aan. PROCEDURE WriteU16 (In:U16;Width:CARDINAL) ;

Voor output van U16-waarden.

Width geeft minimum lengte van het te printen getal aan. PROCEDURE WriteI32(In:I32;Width:CARDINAL);

Voor output van I32-waarden.

Width geeft minimum lengte van het te printen getal aan. PROCEDURE WriteU32(In:U32;Width:CARDINAL);

Voor output van U32-waarden.

(18)

B.2. Module SafeIo

PROCEDURE ReadI16 (VAR OutI16:I16;Str:ARRAY OF CHAR};

Deze procedure leest een I16-waarde in. Str wordt op het beeldscherm

afgedrukt en behoort de I16-grenzen aan te geven. PROCEDURE ReadU16{VAR OutU16:U16;Str:ARRAY OF CHAR);

Deze procedure leest een U16-waarde in. Str wordt op het beeldscherm

afgedrukt en behoort de U16-grenzen aan te geven. PROCEDURE ReadI32{VAR OutI32:I32;Str:ARRAY OF CHAR};

Deze procedure leest een I32-waarde in. Str wordt op het beeldscherm

afgedrukt en behoort de I32-grenzen aan te geven. PROCEDURE ReadU32{VAR OutU32:U32;Str:ARRAY OF CHAR};

Deze procedure leest een U32-waarde in. Str wordt op het beeldscherm

afgedrukt en behoort de U32-grenzen aan te geven. PROCEDURE ReadREAL{VAR Real:REAL;Str:ARRAY OF CHAR);

Deze procedure leest een REAL-waarde in. Str wordt op het beeldscherm

afgedrukt en behoort de REAL-grenzen aan te geven. PROCEDURE ReadSTRING {String: STRINGPtr;Number:CARDINAL) ;

Deze procedure leest een string van Number karakters.

Preconditie: ALLOCATE{String,Number*TSIZE{CHAR)} moet succesvol

aangeroepen zijn. *

* TSIZE{x)

=

aantal bytes dat de computer gebruikt voor type x,

Available{z) => ALLOCATE(y,z) geeft aan pointer y z bytes geheugen

en dus is ALLOCATE(y,z) succesvol aangeroepen.

PROCEDURE ReadArrayOfI16 {I16Array:ArrayOfI16Ptr;Number:CARDINAL} ; Leest een array van I16-waarden met Number elementen.

Preconditie: ALLOCATE{I16ArraY,Number*TSIZE{I16)} moet succesvol aangeroepen zijn.

PROCEDURE ReadArrayOfU16 {U16Array:ArrayOfU16Ptr;Number:CARDINAL} ; Leest een array van U16-waarden met Number elementen.

Preconditie: ALLOCATE{U16Array,Number*TSIZE{U16» moet succesvol

aangeroepen zijn.

PROCEDURE ReadArrayOfI32 {I32Array:ArrayOfI32Ptr;Number:CARDINAL} ; Leest een array van I32-waarden met Number elementen.

Preconditie: ALLOCATE{I32Array,Number*TSIZE{I32}) moet succesvol aangeroepen zijn.

PROCEDURE ReadArrayOfU32 {U32Array:ArrayOfU32Ptr;Number:CARDINAL} ; Leest een array van U32-waarden met Number elementen.

Preconditie: ALLOCATE{U32ArraY,Number*TSIZE{U32}} moet succesvol aangeroepen zijn.

PROCEDURE ReadArrayOfREAL(REALArray:ArrayOfREALPtr; Number: CARDINAL) ;

Leest een array van REAL-waarden met Number elementen.

Preconditie: ALLOCATE(REALArraY,Number*TSIZE(REAL)} moet succesvol aangeroepen zijn.

(19)

PROCEDURE OneFileName(VAR Fn:ARRAY OF CHAR;VAR Res:BOOLEAN); Vraagt om een filenaam die vervolgens in Fn wordt opgeslagen.

Postconditie: Res => OneFileName is succesvol aangeroepen.

PROCEDURE TwoFileNames(VAR Fn1,Fn2:ARRAY OF CHAR;VAR Res:BOOLEAN); Vraagt om twee filenamen die vervolgens in Fn1 en Fn2 worden

opgeslagen.

Preconditie: SIZE(Fn1)=SIZE(Fn2). **

Postconditie: Res => TwoFileNames is succesvol aangeroepen.

* * : SIZE(x) is het aantal bytes nodig voor variabele x.

PROCEDURE ThreeFileNames(VAR Fn1 r Fn2,Fn3:ARRAY OF CHAR; VAR Res:BOOLEAN);

Vraagt om drie filenamen die vervolgens in Fn1 r Fn2 en Fn3 worden opgeslagen.

Preconditie: SIZE(Fn1)=SIZE(Fn2)=SIZE(Fn3).

Postconditie: Res => ThreeFileNames is succesvol aangeroepen. PROCEDURE EqualStrings(Strl:ARRAY OF CHAR;Str2:ARRAY OF CHAR;

Length:CARDINAL;VAR Equal:BOOLEAN); Deze procedure vergelijkt twee strings.

Preconditie: Het aantal elementen van zowel Str1 als Str2 is ten minste Length.

Postconditie: Equal = ( Ai : O<=i<Length : Str1[i]=Str2[i] ).

PROCEDURE TypeNumber(Str:ARRAY OF CHAR;Lwb,Upb:CARDINAL;Even:BOOLEAN; VAR Res:BOOLEAN) : CARDINAL;

Vraagt om een nummer tussen Lwb en Upb en als Even geldtrdan wordt

het nummer even gemaakt ( 1 groter ) als het nodig is. Str wordt op

het bee~~scherm geprint en behoort de grenzen aan te geven.

Postconditie: Res => TypeNumber i~ succesvol aangeroepen.

PROCEDURE MemoryError;

Geeft een foutmelding als er geconstateerd is dat de computer niet

genoeg geheugen meer heeft ( b.v. bij toekennen geheugenruimte aan

pointer) en breekt na een <RETURN> het programma af.

PROCEDURE Fill(VAR Str:ARRAY OF CHAR);

Als Str een karakter OC heeft r dan vult Fill Str op met spaties vanaf het eerste karakter OC.

Als Str geen karakter OC heeft r dan blijft Str onveranderd. PROCEDURE ClearScreen(Number:CARDINAL);

Maa}~t het scherm leeg en Number geeft aan hoelang er daarna gewacht

wordt.

PROCEDURE WaitForReturn;

(20)

B.3. Module Utilities

PROCEDURE CreateInfoHeader(VAR Fc:FcFile;New:BOOLEAN;

VAR FileContAllocated,Res:BOOLEAN);

Als New geldt dan vraagt deze procedure recordinfo ( de descriptor )

en initialiseert hij Fc. Als New niet geldt dan leest deze procedure de recordinfo van Fc.F en initialiseert Fc.

Preconditie: Fc.F's positie is de eerste byte van het descriptor-gedeelte.

Postconditie: Res en New => Fc.f is in de SetWrite-toestand,

Res en NOT New => Fc.F is in de SetModify-toestand, Res => Fc.F's positie is de eerste byte van het

data-gedeelte,

FileContAllocated = De pointer Fc.Descr.FileCont heeft geheugenruimte toegewezen gekregen. PROCEDURE WriteInfoHeader(VAR Fc:FcFile;VAR Res:BOOLEAN);

Schrijft recordinfo naar Fc.F.

Preconditie: Fc.F's positie is de eerste byte van het descriptor-gedeelte.

Postconditie: Res => Fc.F's positie is de eerste byte van het data-gedeelte,

Fc.F is in de Setwrite-toestand.

PROCEDURE Find(Fc:FcFile;Str:ARRAY OF CHAR; Index: CARDINAL;

VAR Found:BOOLEAN);

Preconditie: Index<=Fc.NrOfFields.

Postconditie:

Found => ( ~i : O<=i<Index :

( Aj : O<=j<12 : Fc.Descr.FileContA[i] .Ident[j]=Str[j] ).

PROCEDURE PrintFieldArray(Fc:FcFile);

Print info over de velden van een record.

PROCEDURE Clear(VAR Fc:FcFile;Number:CARDINAL;VAR Res:BOOLEAN); Preconditie: Fc.F is aan het einde van de file.

Postconditie: ( Res => Fc.F is uitgebreid met Number lege records,

Fc.F's positie is ( de eerste byte van het

dummyveld van ) het laatste record ), Fc.F is in de SetModify-toestand.

PROCEDURE CalcMaxPos(Fc:FcFile;VAR MaxPos:CARDINAL;VAR Res:BOOLEAN); Berekent het maximum aantal plaatsen voor records in Fc.F.

Preconditie: Fc.F is in de SetModify-toestand.

Postconditie: ( Res => Fc.F heeft MaxPos records),

(21)

PROCEDURE PosHash(VAR Fc:FcFile;Str:ARRAY OF CHAR; VAR Full,Res:BOOLEAN);

Preconditie: Fc.F is in de SetModify-toestand.

Postconditie: ( Res => Fc.F is een hashed recordfile,

als Fc.F een vol record met sleutel Str heeft dan wijst Fc.F naar dat record,

als Fc.F niet zo'n record heeft dan wijst Fc.F naar het eerste lege of verwijderde record

vanaf de positie berekend d.m.v. calchashkey,

Full = file Fc.F heeft alleen volle records), Fc.F is in de SetModify-toestand,

Fc.Buf en Fc.LastKey kunnen veranderd zijn. PROCEDURE Position(VAR Fc:FcFile;Recordposition:CARDINAL;

VAR Res:BOOLEAN);

Preconditie: Fc.F is in de SetModify-toestand.

Postconditie: ( Res => Recordposition>O,

Fc.F wijst naar record op plaats Recordposition ),

Fc.F is de SetModify-toestand.

PROCEDURE NPositionsFurther(VAR Fc:FcFile;VAR Highpos,Lowpos:CARDINAL; Number:CARDINAL;VAR Res:BOOLEAN);

Preconditie: Fc.F wijst naar het record op plaats X die

Highpos*2-16+Lowpos bytes van het begin van de recordfile af ligt ),

Fc.F is in de SetModify- of SetRead-toestand.

Postconditie: ( Res => Fc.F wijst naar het record op plaats

Number+X die Highpos*2-16+Lowpos bytes van het begin van de recordfile af ligt ),

als Fc.F ( sequentiele recordfile ) te klein was

( Number+X > MaxPos I I ) dan zijn er Number+X-MaxPos

lege records bijgemaakt dmv. Clear en is Fc.F in de

SetModify-toestand,

als Fc.F ( hashed recordfile ) te klein was

( Number+X > MaxPos I I ) dan geldt NOT Res en is Fc.F in

de SetModify-toestand,

als de recordfile niet te klein was dan is Fc.F in dezelfde toestand als voor de aanroep van de procedure.

I I : MaxPos na succesvolle aanroep van CalcMaxPos(Fc,MaxPos,Res).

PROCEDURE Get (VAR Fc:FcFile;VAR Res:BOOLEAN);

Preconditie: Fc.F is in de SetModify-toestand.

Postconditie: ( Res => Het record waar Fc.F naar wijst is in gebruik,

Fc.Buf is gevuld met de inhoud van het record waar Fc.F naar wijst,

Fc.F wijst naar hetzelfde record als voor de aanroep van Get ),

(22)

PROCEDURE Put{VAR Fc:FcFile;Pos:CARDINAL;VAR Res:BOOLEAN}; Preconditie: Fc.F is in de SetModify-toestand.

Postconditie: { Res => 1<=Pos<=65534,

het record waar Fc.F naar wijst heeft de inhoud van Fc.Buf gekregen,

het dummyveld heeft de waarde van Pos gekregen, Fc.F wijst naar hetzelfde record als voor de aanroep van Put },

Fc.F is in de SetModify-toestand. PROCEDURE PrintRec{Fc:FcFile;Pos:CARDINAL};

Print de inhoud van Fc.Buf.

Als Fc.F een sequentiele recordfile is, dan is Pos de index van het te printen record binnen de recordfile.

PROCEDURE FcLookup(VAR Fc:FcFile;Fn:ARRAY OF CHAR;New:BOOLEAN;

VAR FileContAllocated,BufAllocated,Res:BOOLEAN}; Opent file Fc.F met naam Fn en als dat goed is verlopen dan wordt

CreatelnfoHeader aangeroepen en als daarna deze procedure succesvol is

uitgevoerd dan wordt Fc.Buf geinitialiseerd d.m.v. Allocate {Fc,Res}.

Postconditie: Res => FcLookup is succesvol aangeroepen, Res en New => Fc.F.new { file Fn is nieuw }, Res en NOT New => NOT Fc.F.new,

FileContAllocated = Fc.Descr.FileCont heeft genoeg geheugenruimte toegewezen gekregen d.m.v. ALLOCATE,

BufAllocated = Allocate{Fc,Res} is succesvol

aangeroepen. PROCEDURE FcClose{VAR Fe:FcFile;

FileContAllocated,BufAllocated:BOOLEAN} ;

Sluit de file Fc.F en dealloceert Fe.Buf's en Fc.Descr.FileCont's geheugenruimte als daarvoor geheugen was gealloceerd.

Preconditie: FcLookup moet aangeroepen zijn,

FileContAllocated

=

Fc.Descr.FileCont heeft

geheugenruimte toegewezen gekregen,

BufAllocated = Allocate{Fc,Res} is succesvol aangeroepen.

PROCEDURE Allocate{VAR Fc:FcFile;VAR Res:BOOLEAN}; Alloceert voor Fe.Buf geheugenruimte.

Postconditie: Res => Allocate is succesvol aangeroepen. PROCEDURE DeAllocate{VAR Fc:FcFile};

Dealloceert de geheugenruimte die gebruikt werd voor Fc.Buf. Preconditie: Allocate moet succesvol aangeroepen zijn.

(23)

APPENDIX C: HASHED RECORDFILES

Hashed recordfiles zijn recordfiles waarin records gevonden worden

d.m.v. een unieke sleutel. De positie van een record in zo'n recordfile

is afhankelijk van de sleutel van het record.

De sleutel van een record zorgt er in de meeste gevallen voor dat een record sneller gevonden wordt dan met sequentieel zoeken.

Er zijn een paar restricties voor hashed recordfiles:

- Het eerste veld moet van het stringtype zijn en dient als sleutel.

- Het maximum aantal records moet opgegeven worden bij de creatie

van een hashed recordfile en kan daarna niet meer veranderd worden. Er is een limiet van 65534. De hashed recordfile word dan

geinitialiseerd met het opgegeven maximum aantal lege records

Om toegang tot een record met een gegeven sleutel te krijgen, moet

de recordfile gepositioneerd worden op het record met de gegeven

sleutel. De aanroep PosHash(Fc,Str,Full,Res) zorgt ervoor dat als Fc.F

een vol record met sleutel Str heeft dat dan na afloop Fc.F naar dat

record wijst en als Fc.F niet zo'n record heeft, wijst Fc.F naar het

eerste lege of verwijderde record vanaf de positie berekend d.m.v. de

locale functie calchashkey.

De werking van PosHash is als voIgt: d.m.v. de sleutelstring wordt

een hashpositie in de recordfile berekend, welke wordt gebruikt

als de startpositie bij het circulair zoeken ( het zoeken gaat sneller

als er redelijk veel ongebruikte plaatsen zijn ). .

Als een in gebruik zijnd record wordt tegengekomen, dan is de

waarde in het dummyveld de berekende hashpositie van dat record. Dit

zorgt voor het sneller kunnen vergelijken van sleutels. Want als de hashpositie van het gezochte record niet overeenkomt met de hashpositie

van het gevonden record, dan is er geen reden om de sleutels met elkaar

te vergelijken! Als de hashposities weI overeenkomen, worden de

sleutels met elkaar vergeleken.

Als bij het zoeken een leeg record wordt tegengekomen, dan wordt

het zoeken gestaakt: een record met de gegeven sleutel zal niet meer

gevonden worden, want een vorige aanroep van PosHash met dezelfde

file en sleutel zou hier of eerder gestopt zijn. En als het record dan

aan de file toegevoegd zou zijn ( d.m.v. Put (Fc,LastKeY,Res) ) dan was

de huidige aanroep van PosHash eerder gestopt op de plaats van dat

record 6f zou het record hier niet leeg zijn, dus is er nog geen record

met dezelfde sleutel aan de recordfile toegevoegd.

Als een verwijderd record wordt tegengekomen, dan kan het gezochte

record voorbij die plaats gevonden worden: het is mogelijk dat het

gezochte record op plaats X aan de recordfile is toegevoegd en dat daarna een record tussen de startpositie en plaats X is verwijderd.

Het circulair zoeken stopt als een vol record met dezelfde sleutel of een leeg record wordt tegengekomen of als de recordfile aIleen maar volle records heeft.

(24)

APPENDIX D: VOORBEELD

Het onderstaande printprogramma slaat de inhoud van een op te geven

recordfile op in een outputfile, die dan vervolgens geprint kan worden

d.m.v. een commando aan het Operating System.

MODULE Print;

FROM Utilities IMPORT FcLookup,FcClose,Get,PrintRec,CalcMaxPos, CreateInfoHeader,Position;

FROM FileSystem IMPORT GetPos,SetPos,SetModify,Response,ReadNBytes; FROM SafeIo IMPORT ClearScreen,OneFileName,WaitForReturn;

FROM Definitions IMPORT FcFile;

FROM InOut IMPORT OpenOutput,CloseOutput,Done,WriteString,WriteLn; FROM SYSTEM IMPORT ADR,TSIZE;

VAR FC:FcFile;HIGHPOS,LOWPOS,MAXPOS,I,BYTES,DUMMY:CARDINAL; FN:ARRAY[O ..ll] OF CHAR;FILECONTALLOCATED,BUFALLOCATED,RES:BOOLEAN; BEGIN WITH FC DO WITH Descr DO LOOP ClearScreen(O) ; OneFileName(FN,RES) ;

(* Geef de naam van de recordfile. *)

IF NOT RES THEN EXIT END;

FcLookup(FC,FN,FALSE,FILECONTALLOCATED,BUFALLOCATED,RES); IF RES

THEN

(* FC.F is geopend met naam FN en de descriptor is gelezen *)

(* en FC. Buf is geini tialiseerd. *)

CalcMaxPos(FC,MAXPOS,RES); IF NOT RES THEN EXIT END;

(* Er zijn MAXPOS records in recordfile FN. *)

OpenOutput('TXT') ;

(* Een naam voor de outputfile is gevraagd met uitbreiding *)

(* '.TXT' en de outputfile is geopend. *)

WriteString('CONTENTS OF FILE) ;WriteString(FN); Wri teString (' : ' ) ;

WriteLn;WriteLn;WriteLn;

IF NOT Done THEN RES:=FALSE;EXIT END;

1:=1;

WHILE I<=MAXPOS DO

(* Invariant: Kijk voor elk record of hij in gebruik is *)

(* en als dat zo is dan wordt hij opgeslaan *)

(* in de outputfile. *)

Position(FC,I,RES);

IF NOT RES THEN EXIT END;

(* FC.F wijst naar record I. *)

GetPos(F,HIGHPOS,LOWPOS) ;

IF F.res<>done THEN RES:=FALSE;EXIT END;

(* HIGHPOS en LOWPOS geven de positie van Fc.F aan. *)

ReadNBytes(F,ADR(DUMMY) ,TSIZE(CARDINAL) ,BYTES); IF F.res<>done THEN RES:=FALSE;EXIT END;

(* De positie van Fc.F is TSIZE(CARDINAL) bytes verder. *)

(* DUMMY is de waarde van het dummyveld. *)

SetPos(F,HIGHPOS,LOWPOS) ;

IF F.res<>done THEN RES:=FALSE;EXIT END;

(* Fc.F wijst weer naar ( het begin van) record I. *)

(25)

THEN

(* record is vol. *)

Get(FC,RES) ;

IF NOT RES THEN EXIT END; PrintRec(FC,I) END; INC (I) ; END; CloseOutput; (* Outputfile is nu gesloten. *) EXIT ELSE RES:=FALSE;EXIT END;

END; (* Einde van LOOP. *)

IF NOT RES THEN

WriteString('An error has been made: a new file will be ');

WriteLn;

WriteString('deleted and an old file will be closed ');

ELSE

WriteString( 'File is closed now'); END;

FcClose(FC,FILECONTALLOCATED,BUFALLOCATED) ;

(* Een juiste recordfile is nu gesloten. *)

WaitForReturn; END;

END; END Print.

(26)

APPENDIX E: AANPASSING VAN MODULE DEFINITIONS

Als het filecabinet gaat draaien dan kan het nodig zijn dat de module Definitions veranderd dient te worden.

De gebruikte implementatie is: Modula-2/86 release 2.00. Hieronder het

aantal bytes per type op de, bij de stage, gebruikte computer:

type CHAR INTEGER CARDINAL I16 U16 I32 U32 REAL aantal bytes 1 2 2 2 2 4 4 8

Alleen de variabelen MAX en de types 116, U16, I32 en U32 mogen

veranderd worden. Als andere types veranderd worden dan moeten

alle modules gecontroleerd en veranderd worden wat een heidens karwei

is! Als het filecabinet gaat werken op een computer met hetzelfde

aantal bytes voor de types CHAR,INTEGER,CARDINAL en REAL dan hoeft er niets veranderd te worden. Het aantal bytes voor type I16,U16,I32 en U32 mag niet veranderen.

De constante MAX moet eventueel zo veranderd worden dat geldt:

(MAX+l)*TSIZE(REAL) <= grootste waarde van type CARDINAL.

Tevens moet gelden: ( maximum aantal velden )*TSIZE(Field) <= grootste

waarde van type CARDINAL.

De types en procedures die in ieder geval bekeken dienen te worden

zijn: I16, U16, I32, U32, ConvertI16, ConvertU16, ConvertI32,

Referenties

GERELATEERDE DOCUMENTEN

van de verdachte, omdat deze door het slachtoffer veelal meteen als dader wordt aangemerkt en of de toekenning van rechten aan het slachtoffer ongewenste gevolgen kan hebben voor de

Voor sommige instrumenten zijn voldoende alternatieven – zo hoeft een beperkt aantal mondelinge vragen in de meeste gevallen niet te betekenen dat raadsleden niet aan hun

In the context of the experimental framework used in this study, we inoculated two groups of Sardinian sheep with either blood from a BTV-infected animal [BTV-8 NET2007(blood) ] or

Although it is possible to estimate the number of true positives and negatives and the number of false positives and negatives for every rejection level using microarray data

De percentages laten zien dat het aantal jongeren in jeugdzorg uit een- en tweeoudergezinnen elkaar niet heel veel ontlopen: 42% van de groei van het aantal personen in de

Vijftien jaar geleden verloor Marc Vande Gucht zijn dochter Joke door zelfdoding.. ‘We hebben haar elke dag op ons netvlies, en dat is

Lager onderwijs niet afgewerkt 22 Lager onderwijs afgewerkt 25 Lager secundair onderwijs afgewerkt 28 Hoger secundair onderwijs afgewerkt 20 Hoger onderwijs afgewerkt 5?.

– Bron van info voor school → feedback voor nieuwe initiatieven en