JPI-Topspeed-Modula 2 User manual.txt 364 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268
  1. 
  2. lenueiAi sjasn
  3. TopSpeed Modula-2
  4. For IBM® Personal Computers and Compatibles
  5. User’s Manual
  6. Jensen & Partners International
  7. LICENSE STATEMENT
  8. Jensen & Partners International hereby grants you a non-exclusive license to use the TopSpeed Modula-2 compiler and libraries. You may use the software on any computer, provided that the software cannot possibly be used on more than one computer at the same time. You may make copies of the software for the sole purpose of loading it into the computer on which you wish to use it, or for keeping a maximum of two backup copies.
  9. WARRANTY
  10. Jensen & Farmers International warrants the enclosed diskettes to be accurate copies of the master disks, and will replace any defective copies free of charge for a period of 60 days after purchase.
  11. Jensen & Farmers International hereby explicitly disclaims all other warranties whether ex­press or implied, including without limitation, the implied warranties of merchantability and fitness for any particular purpose. Jensen & Farmers International shall have no liability for consequential, incidental, exemplary or special damages, including lost profits.
  12. Jensen & Partners International reserves the right to change the product at any time, without prior notice.
  13. TECHNICAL SUPPORT
  14. To qualify for technical support fill in and mail the enclosed registration card.
  15. TopSpeed™ is a trademark of Jensen & Partners International.
  16. IBM® is a registered trademark of the International Business Machines Corporation.
  17. Microsoft® is a registered trademark of Microsoft Corporation.
  18. WordStar® is a registered trademark of MicroPro International Corporation.
  19. Turbo Pascal® is a registered trademark of Borland International, Inc.
  20. Copyright © 1988 by Jensen & Partners International. All rights reserved.
  21. Printed in the United States of America.
  22. Contents
  23. 1 Introduction 1
  24. The TopSpeed Modula-2 Package 1
  25. How to Use This Book 2
  26. Typographic Conventions 2
  27. Structure 2
  28. 2 Features of the TopSpeed Modula-2 System 5
  29. Modules 5
  30. Separate Compilation 6
  31. Automatic Librarian 6
  32. Smart Linking 7
  33. Definition Parts Always Recompiled 7
  34. Automatic Make Facility 7
  35. Advanced Data Structures 8
  36. Full Segment Control 8
  37. Type Checking 8
  38. Procedures 8
  39. Powerful Control Statements 9
  40. Multitasking 9
  41. Program Control 9
  42. Programming Environment 9
  43. Debugging 10
  44. 3 Getting Started 11
  45. Summary of Distribution Disks 11
  46. Running on a Hard Disk System 12
  47. Running on a System with Two Floppy Disks 12
  48. Running on a System Using 3| Inch Disks 13
  49. How to Continue 13
  50. If You Are Patient 13
  51. If You Dislike Reading Manuals 13
  52. 4 Modula-2 Case Studies 15
  53. Hello 16
  54. iv Contents
  55. Pythagoras 18
  56. The FOR Statement 18
  57. Exercise 19
  58. Music 20
  59. Data Types 20
  60. Constant Declarations 21
  61. Procedures 21
  62. Strong Typing 22
  63. Library Routines 22
  64. Anagram 22
  65. More About Procedures and Parameters 24
  66. Variable and value parameters 24
  67. More About Loops 25
  68. Creating Modules 25
  69. Creating a Definition File 26
  70. Creating an Implementation File 26
  71. Open Array Parameters 27
  72. Puzzle 27
  73. Function Procedures 29
  74. Subrange Declarations 29
  75. More on Types 29
  76. Graphics 30
  77. Using Library Routines 32
  78. RECORD Types 32
  79. Sorting 33
  80. Command Line Arguments in the TopSpeed Modula-2 Environment 34
  81. Heapsort and Quicksort 36
  82. Implementing Quicksort 36
  83. Procedure Parameters 37
  84. Nested Procedures 38
  85. Recursion and the Compiler 38
  86. Calculator 38
  87. Enumeration Data Types 41
  88. Variant Records 42
  89. CASE Statements 42
  90. 5 The TopSpeed Modula-2 Environment 45
  91. TopSpeed Modula-2: Features 45
  92. Starting Up the Environment 47
  93. The Help System 47
  94. Help Lines 47
  95. The Menu System 48
  96. Moving Around Menus 48
  97. ShortCut Keys 50
  98. Windows in the Environment 51
  99. Zoom/Unzoom 52
  100. User Dialog Windows 52
  101. Single Line Input 52
  102. Multiple Line Input 53
  103. File Selection Window 53
  104. The File Menu 55
  105. Load File 55
  106. Pick File 56
  107. Save File 57
  108. All Save 57
  109. Main Module 57
  110. Change Dir 57
  111. Files Dir 57
  112. DOS Shell 58
  113. Execute 58
  114. Quit 58
  115. The Editor 59
  116. The Editor Menu System 59
  117. Pop Up Menus 59
  118. Loading a File 60
  119. Saving a File 61
  120. Maximum File Sizes 62
  121. Removing a File from an Editor Window 62
  122. Moving Between Editor Windows 62
  123. Editor Commands 62
  124. Insertion and Deletion 63
  125. Cursor Movement 63
  126. Block Commands 64
  127. Editor Options 65
  128. Search and Replace 66
  129. Other Editor Commands 66
  130. Compiling and Running Programs 67
  131. Compiling 67
  132. Compilation Errors 68
  133. The Main Module 69
  134. Making a Program 69
  135. Running Programs 70
  136. Run-Time Errors 70
  137. Linking a Program 71
  138. Linker Errors 72
  139. The Options Menu 73
  140. Compiler Options 73
  141. B - Defaults for Run-Time Checks 73
  142. D - Generate Debug Information 73
  143. E - Stop On First Error 73
  144. F - Filename Check 73
  145. J - Suppress Libraries 73
  146. N - Line Numbers 73
  147. V - Volatile Variables 74
  148. Linker Options 74
  149. M - Map File 74
  150. I - Initialize Segments 74
  151. S - Detailed Segment Map 74
  152. C - Case Sensitive Link 74
  153. W - Suppress Warnings 74
  154. T - Trace References 74
  155. Run Options 74
  156. C - Command Line 75
  157. A - Auto Make 75
  158. T - Timed Run 75
  159. F - Find Error 75
  160. Editor Options 75
  161. A - Auto Save Files 75
  162. F - Default Filenames 75
  163. E - Default Extensions 76
  164. N - Number Of Backups 76
  165. T - Top Scroll Zone 76
  166. B - Bottom Scroll Zone 76
  167. Setup Options 76
  168. C - CGA Snow Check 76
  169. B - BIOS Scrolling 76
  170. H - High Background 76
  171. X - Solid Cursor 76
  172. R - Load Redirection File 77
  173. L - Load Options/Windows 77
  174. S - Save Options/Windows 77
  175. Make All 77
  176. The Information Window 77
  177. The Redirection File 77
  178. The Batch Compiler and Linker 78
  179. Customizing the Menu 79
  180. Changing the Main Menu Type 80
  181. Changing Menu Text 80
  182. Changing the Menu Tree 81
  183. Changing ShortCut Keys 81
  184. External DOS Commands 82
  185. The Editor Keys and Menus 82
  186. Changing Help Lines 83
  187. Menu Definition File Format 83
  188. Menu Directives 83
  189. Menu Type 83
  190. Editor Section 84
  191. Help Lines 84
  192. ShortCut Key Definition 85
  193. Submenu Title 85
  194. Comment 85
  195. Menu Line Definition 86
  196. Menu Actions 87
  197. Pre-Defined Actions 87
  198. Global Actions 87
  199. Editor Actions 88
  200. External Commands 88
  201. External Command Parameters 89
  202. Key Sequences 89
  203. Changing Windows 90
  204. Repositioning Windows 90
  205. Resizing Windows 91
  206. Recoloring Windows 91
  207. Customizing the Error Messages 92
  208. 6 The Language 95
  209. Textual Topics 96
  210. Tokens 96
  211. Syntax 98
  212. Declarations and Visibility 99
  213. Types 100
  214. Numeric Types 100
  215. CARDINAL Types 100
  216. INTEGER Types 101
  217. REAL Types 101
  218. Ordinal Types 101
  219. CHAR Type 101
  220. Enumeration Types 101
  221. Subrange Types 102
  222. Set Types 102
  223. Array Types 103
  224. Record Types 103
  225. Pointer Types 104
  226. Type Compatibility 105
  227. Objects and Values 106
  228. Constants 106
  229. Set Values 107
  230. Designators 108
  231. Expressions 109
  232. Statements Ill
  233. Assignment Statement Ill
  234. IF Statement 112
  235. CASE Statement 112
  236. WHILE Statement 113
  237. REPEAT Statement 113
  238. LOOP and exit Statements 113
  239. FOR Statement 114
  240. WITH Statement 114
  241. GOTO Statement 115
  242. Procedures 115
  243. Bodies 116
  244. Calling Procedures 118
  245. Procedure Types 119
  246. Predefined Procedures 120
  247. Predefined Function Procedures 120
  248. Predefined Proper Procedures 121
  249. Modules 121
  250. Server Modules 122
  251. Importing 123
  252. Local module 124
  253. Sources for Language Examples 124
  254. 7 The Compiler 127
  255. The OBJ-file 127
  256. Data Representation 128
  257. Calling Conventions 130
  258. The Stack Frame 130
  259. Parameter Passing 131
  260. Function Results 132
  261. Options (on Command Line) 132
  262. Directives (in Source Text) 134
  263. Interface to Other Languages 136
  264. Controlling Run-Time Program Structure 137
  265. Segments, Groups and Classes 137
  266. Addressing Items 139
  267. Naming Conventions 139
  268. 8087 Support 140
  269. Interrupt Handlers 140
  270. 8 The TopSpeed Modula-2 Library 143
  271. Introduction 143
  272. Library Overview 144
  273. SYSTEM 144
  274. AsmLib 144
  275. MATHLIB 144
  276. Str 144
  277. Lib 145
  278. Storage 145
  279. Process 145
  280. Graph 146
  281. FIO 146
  282. IO 146
  283. Window 147
  284. FloatExc 147
  285. ProcTrace 147
  286. How to Use the Library Reference 148
  287. MODULE Str 148
  288. General String Procedures 149
  289. Conversion Procedures 153
  290. MODULE Lib 156
  291. Sorting 157
  292. Random Number Generation 158
  293. Environment Procedures 159
  294. Memory Block Operations 160
  295. DOS Procedures 164
  296. Address Arithmetic 166
  297. Long Jumps 168
  298. Error Handling 169
  299. Miscellaneous 171
  300. MODULE IO 173
  301. Global Variables in IO 173
  302. Formatted Output 174
  303. Formatted Input 177
  304. Basic Input Procedures 180
  305. Redirection 180
  306. MODULE FIO 182
  307. Global Variables in FIO 182
  308. File Handling 183
  309. Formatted Output 188
  310. Formatted Input 192
  311. Directory Handling 194
  312. MODULE Storage 197
  313. Global Variables in Storage 197
  314. Main Heap Procedures 197
  315. General Heap Procedures 199
  316. MODULE SYSTEM 202
  317. Low-level Processes 203
  318. Module Priorities in TopSpeed Modula-2 203
  319. Miscellaneous 208
  320. MODULE MATHLIB 211
  321. Error Handling 211
  322. Conversion Procedures 215
  323. 8087 Procedures 216
  324. MODULE FloatExc 217
  325. MODULE ProcTrace 218
  326. MODULE Process 220
  327. Scheduler 221
  328. Signals 222
  329. Miscellaneous 224
  330. MODULE Graph 226
  331. Global Constants 226
  332. Graphics Procedures 228
  333. Initialization Procedures 231
  334. MODULE Window 232
  335. Window Constants and Types 232
  336. Window Management 233
  337. Coordinate Handling 238
  338. Window Output Procedures 240
  339. Multi-Process Support 242
  340. Palette Windows 243
  341. Procedure List 246
  342. Index 249
  343. Introduction
  344. The TopSpeed Modula-2 Package
  345. Welcome to the world of Modula-2! We’re sure you’ll find it exciting and reward­ing. The TopSpeed Modula-2 package is a complete Modula-2 development system with all the features you need to make your program development easier, faster, and cleaner. TopSpeed Modula-2 has a completely self-contained, menu driven environ­ment. This environment includes: a multi-window editor; a smart, high-speed linker; an entirely automatic Make facility; and an optimizing compiler.
  346. The editor lets you edit up to four files simultaneously, in different windows. The compiler is not only very fast, it also produces code better than any existing C, Pascal or Modula-2 compiler. The Make facility automatically determines dependencies among module versions, and will recompile only the modules, that have changed since the last compilation. The TopSpeed Modula-2 environment even makes it possible to locate in-source compiler and run-time errors, as well as providing numerous other features that you’ll explore as we proceed.
  347. In addition to the environment you will find a library containing useful utilities such as a complete Window Management System, a Time-Sliced Process Manager, powerful Memory Management routines, and a complete set of I/O routines.
  348. How to Use This Book
  349. Typographic Conventions
  350. To set certain information apart from the surrounding text, such material will be presented using different fonts:
  351. Italics is used to emphasize words.
  352. Boldface is used to introduce new concepts.
  353. Typewriter is used to refer to text that may be part of a program or that may be a command to DOS.
  354. In some cases, the discussion will refer to individual keys on the keyboard. These will appear in a box. For example, |F1|| refers to function key Fl on your keyboard.
  355. Many of the commands in the TopSpeed Modula-2 environment involve the IAlt|| or |Ctrl|| keys. For such commands, you’ll need to hold down both keys simultaneously. This will be indicated by two adjacent boxes, as injAlt||R||, which means you should press and hold down the lAlt|| and then press the [r]] key.
  356. A space between two boxes indicates that you need to release the previous key(s) before pressing the key(s). For example, |Ctrl||K|| QT|| says to:
  357. 1. Press and hold down the |Ctrl|| and then press the key.
  358. 2. Release the flCtrl|| and ITkII keys (or release just the [k] key).
  359. 3. Then press the EJI key.
  360. Structure
  361. This book will take you through all the features of the TopSpeed Modula-2 system. Depending on your previous knowledge you may want to read only selected sections.
  362. Here is how the book is structured:
  363. Chapter 1 is the chapter you are reading right now. It gives you an idea about what is to come.
  364. Chapter 2 gives a very brief overview of some of the most important features of TopSpeed Modula-2. These features will be discussed in more detail in later chapters.
  365. Chapter 3 tells you how to install TopSpeed Modula-2 on your system, and how to get started right away. This chapter tells you how to install a “vanilla-flavored” Modula-2 environment. In later chapters you’ll
  366. Chapter 4
  367. Chapter 5
  368. Chapter 6
  369. Chapter 7
  370. Chapter 8
  371. learn how to customize your Modula-2 environment for your habits and needs.
  372. is a series of program case studies that serve to introduce Modula-2 and the TopSpeed Modula-2 environment to readers with previous programming experience. You’ll find several example programs that illustrate various features of the Modula-2 language. The examples will also show you some of the features of TopSpeed Modula-2 in action.
  373. explains the TopSpeed Modula-2 environment in detail. This chapter contains the main reference information for TopSpeed Modula-2 commands. You’ll also find out how to customize your TopSpeed Modula-2 environment.
  374. is a concise technical reference describing the Modula-2 language. This chapter contains a semi-formal summary of the Modula-2 syntax. Your TopSpeed Modula-2 package also includes a more leisurely introduction to Modula-2, in the Modula-2 Tutorial, by K. N. King.
  375. contains technical details relating to the compiler itself, such as data representation, calling conventions, compiler options etc.
  376. is a comprehensive reference for the TopSpeed Modula-2 library. It covers each library module and discusses its available procedures in detail. The chapter includes brief descriptions of each procedure, as well as examples showing how to use the procedure.
  377. Features of the
  378. TopSpeed Modula-2 System
  379. Modula-2 is a modem, general purpose programming language. It was designed by Niklaus Wirth, who also developed Pascal. In fact, Modula-2 is a direct descendant of Pascal. You can think of Modula-2 as a “better,” or more powerful, Pascal. Wirth designed Modula-2 to be useful for programming very low-level functions in the computer (accessing disks or I/O ports, etc.) as well as for writing high-level pro­grams such as databases, compilers, word processors and accounting systems. (The TopSpeed Modula-2 system is actually written in TopSpeed Modula-2.)
  380. In this chapter we will briefly describe some of the major features of TopSpeed Modula-2. You should scan the following paragraphs and read whatever you find interesting.
  381. Modules
  382. A Modula-2 program normally consists of a series of modules. Each module is a collection of related procedures and data structures that implement a well-defined section of the total program. For example, the TopSpeed Modula-2 library contains about a dozen modules. These contain the data structures and procedures needed for such tasks as handling strings (Str module), handling I/O for screen and files (IO and FIO modules, respectively), and doing mathematical computations (MATHLIB module).
  383. A module consists of two parts: the definition part, which describes what the module can do, and the implementation part, which describes how it is done. These two parts are sometimes called the module definition and the module implementation. The definition part lists all the procedures and data you may access from elsewhere in your program (for example, from another module). The module definition thus contains information about the interface for each procedure. The interface specifies the parameters you need to pass when calling the procedure. The implementation part contains the actual code for each procedure.
  384. Any procedures and data structures included in the definition part can be made accessible to other modules in your programs. However, the implementation part may contain procedures and data structures in addition to those contained in the definition part.
  385. All procedures and data not listed in the definition part remain private to the imple­mentation part and therefore “invisible” to the rest of the world. Just as a procedure is used as an abstraction to hide details, a module can be used to hide details of a whole range of associated procedures and any common data structures.
  386. A module that uses another module is called a client. A module that provides services to another module is called a server. A module may be both a client and a server.
  387. Separate Compilation
  388. Modules may be compiled separately and saved as object code, which may later become part of a complete program. This means you don’t need to recompile each of the modules every time you make a change in your program; you just need to recompile any modules in which you changed the source code. This greatly speeds the compilation process when your programs use existing modules.
  389. TopSpeed Modula-2 makes it easy for you to use the library modules in your pro­grams. You can also create and compile your own modules for use in your programs.
  390. Automatic Librarian
  391. Modula-2 has built-in, automatic library management. The compiler produces a li­brary file whenever it compiles a module. This makes it possible for the system to include only the procedures and data structures actually being used in programs that use the module. This makes your program file smaller.
  392. Smart Linking
  393. In Modula-2 each module has to specify what it uses from other modules. This infor­mation makes it possible to automate the linking process in the TopSpeed Modula-2 environment.
  394. The linker only needs to know the name of the main program. Starting from this in­formation, the linker can gather any routines used in the program or in other mod­ules. If you have several library modules that serve the same purpose, the system lets you specify the sequence in which the libraries should be searched.
  395. Definition Parts Always Recompiled
  396. The TopSpeed Modula-2 compiler is capable of very high-speed compilation — up to 20,000 lines/minute. Because of this speed, all visible definition parts used in a program are always recompiled. The definition parts are much shorter than the implementation parts, so this takes almost no time.
  397. Doing this has the following advantages:
  398. • It allows recompilation of implementation parts in any order. This is possible because the system knows all the interfaces specified in the definition parts.
  399. • It avoids the version control problems associated with definition modules that you may have experienced with other Modula-2 compilers.
  400. • It cuts down on the number of necessary files by avoiding “symbol-files” for the definition parts. The information in the definition parts can be compiled directly into the program, rather than requiring separate files for storing the symbol information.
  401. Automatic Make Facility
  402. In a large program the module dependencies can become very complicated. This makes it difficult to keep track of the program connections. To help overcome this difficulty, TopSpeed Modula-2 provides an automatic Make facility, which does a high-speed analysis of all module dependencies and module time-stamps.
  403. The system can use this dependency information to determine what modules need to be recompiled. The system recompiles only the modules affected by previous changes. The information from the Make facility makes it possible to determine automatically what modules need to be recompiled.
  404. Advanced Data Structures
  405. Both the simple and the aggregate data structures you may know from C or Pascal are fully supported in Modula-2. These include signed and unsigned integers of various sizes, floating point values, uni- and multi-dimensional arrays, records, variant records, sets up to 64K elements, short and long pointers, procedure variables and more.
  406. Full Segment Control
  407. TopSpeed Modula-2 offers a unique feature that allows you to utilize the segmented memory of the 80x86 CPU. Your program and data may be as large as 1 megabyte and still use “short calls” for selected procedures, within as well as across modules. You may also use “short pointers” to speed up execution. In contrast to some other languages that allow the use of short pointers in selected segments only, TopSpeed Modula-2 allows the simultaneous use of short pointers in any segments you choose. You may even move the segments around during program execution to achieve op­timal use of the available memory. (See Chapter 6 for further details.)
  408. Type Checking
  409. Like other high-level languages, Modula-2 does type checking when you use variables — to ensure that you don’t try to assign the wrong type of information to particular variables. For safer programming, Modula-2 has even stricter type checking than its ancestor Pascal. However, Modula-2 does allow you to override type checking whenever necessary. This makes it possible to implement any “tricks” you may need use in order to accomplish exactly what you want.
  410. Procedures
  411. Modula-2 offers advanced procedure parameter handling. You may pass arrays of any size to the same procedure or even pass a procedure as a parameter to another procedure.
  412. Modula-2 includes a procedure type. This type lets you assign procedures to variables dynamically.
  413. TopSpeed Modula-2 also makes it simple to implement interrupt service procedures, so that you can specify the actions to take place if a hardware or software interrupt occurs.
  414. Powerful Control Statements
  415. Modula-2 offers all the control statements available in Pascal. In addition to this, Modula-2 offers, among other things, a LOOP . . . END construct from which you may exit using as many exit points as desired. (See Chapter 6 for the complete set of Modula-2’s control statements.)
  416. In Modula-2, evaluation of Boolean conditions occurs from left to right, and ends as soon as the value of the condition is known. For example, suppose you have an expression that tests whether A and B and C are all TRUE. When evaluating this expression, the system will stop as soon as it finds that one of the terms is FALSE, since that makes the entire compound expression FALSE.
  417. Because of this evaluation method, the use of control statements in Modula-2 is much simpler and more efficient than in languages that do not provide this feature. If you’ve programmed in Pascal, you may have experienced the difficulties you can encounter if this feature is lacking.
  418. Multitasking
  419. Modula-2 has built-in support for multitasking. In addition, the TopSpeed Modula-2 Library includes an advanced time-sliced scheduler, which makes it easy to implement concurrent processes.
  420. Program Control
  421. You have complete control over all aspects of your program. There is a minimum of “built-in” procedures and there are no implicit type conversions to confuse you.
  422. Programming Environment
  423. The TopSpeed Modula-2 system is a state-of-the-art program development system that you may tailor to your own requirements. Moreover, you can even change the menu structure and the command sequences in your TopSpeed Modula-2 environment.
  424. For example, you may have frequent need to use a command that has a long com­mand sequence in the “vanilla version” of TopSpeed Modula-2. You can change the command sequence associated with the command to a shorter one. If you need to give the command thousands of times, saving even one keystroke in executing the command will make a difference — both in time and in accuracy.
  425. TopSpeed Modula-2 includes the complete Modula-2 source text to the library. This means that you can change even these modules if you wish or must, so that you can control the way library work in your programs.
  426. The Assembler source code for the start-up code and for the TopSpeed Modula-2 run-time library is available separately, in the TechKit. This package also includes the JPI TopSpeed Assembler, technical information, as well as communication drives and a module for creating terminate-and-stay-resident (TSR) programs.
  427. Debugging
  428. Because Modula-2 is a strongly typed language, a lot of potential errors are detected at compile time. All “normal” run-time errors (array index out of bounds, using a NIL pointer, overflow, etc.) also can be trapped by the system. If you are running the program under the environment, the system will position the cursor at the point in your source code where the error was detected. This occurs almost instantaneously.
  429. There is of course much more to Modula-2; Chapter 4 will reveal additional features by presenting a series of interesting examples. If you need more complete information, Chapters 6 and 7 explain Modula-2 in greater detail.
  430. Getting Started
  431. Summary of Distribution Disks
  432. Your TopSpeed Modula-2 package includes three 51 inch diskettes. The first of these is labeled System Disk, the second diskette is labeled Library Objects and the third is labeled Library Source. (You can also get TopSpeed Modula-2 on two 31 inch diskettes. In this format, the TopSpeed Modula-2 System and the TopSpeed Modula-2 Library Objects are combined on one diskette, and the second diskette contains the TopSpeed Modula-2 Library Source.)
  433. First, make working copies of these diskettes. Then put the master diskettes in a safe place, and work only with the working copies. For information on making copies of disks, see your DOS documentation.
  434. The disk labeled System contains the main TopSpeed Modula-2 program and related files. These files are:
  435. M2 . EXE The main program for TopSpeed Modula-2.
  436. M2 . OVL Overlay file for main program.
  437. M2 . ERR Compiler error messages.
  438. M2 . MNU Reconfigurable menu definition.
  439. M2. HLP Help text.
  440. Only the first three files are essential when running TopSpeed Modula-2. The others are needed only if you want to use special features, such as on-line help or a cus­tomized menu configuration.
  441. The disk labeled Library Objects contains the following files:
  442. *.DEF
  443. *.OBJ DEMO.MOD WINDEMO.MOD
  444. PROG*.MOD
  445. Definition modules.
  446. Object code for library modules.
  447. A short demonstration program.
  448. A short demonstration of the Window module.
  449. Source code for several example programs. These are named PR0G1 .MOD through PR0G8 .MOD.
  450. Only the *. DEF and *. OBJ files need to be present in order to use the TopSpeed Modula-2 library.
  451. The disk labeled Library Source contains the source code for the library modules.
  452. You do not need this disk to run the system.
  453. Running on a Hard Disk System
  454. Here is how to get started on a hard disk system in four easy steps:
  455. 1. Make a directory on your hard disk, for example: C:\JPIM2
  456. 2. Copy the contents of the System and Library Objects disks to the directory you just made.
  457. 3. Log in the directory you created and start the system by entering M2 at the DOS prompt.
  458. and answer DEMO when TopSpeed Modula-2 prompts for the Main
  459. 4. Press lAltllgJI; ~
  460. file. Press I Enter || and watch the demo program compile, link and execute.
  461. Running on a System with Two Floppy Disks
  462. Here is how to get started in three easy steps on a floppy disk system using
  463. 1. Place the copy of the System Disk in drive A and the copy of the Library Objects disk in drive B.
  464. 2. Log in drive B and start the system by entering A: M2 at the DOS prompt.
  465. HUI tail
  466. 3. Press _
  467. and answer DEMO when TopSpeed Modula-2 prompts for the Main
  468. file. Press |Enter|| and watch the demo program compile, link and execute.
  469. Running on a System Using 3| Inch Disks
  470. _
  471. To use TopSpeed Modula-2 on a system with 3| inch diskettes, you just need the disk containing the System and the Library Objects.
  472. 1. Place the copy of the disk in drive A and prefix to that drive.
  473. 2. Enter M2 at the DOS prompt.
  474. and answer DEMO when TopSpeed Modula-2 prompts for the Main
  475. 3. Press IAlt||Bj|; ' ~
  476. file. Press |Enter|| and watch the demo program compile, link and execute.
  477. How to Continue
  478. Once you’ve got a working Modula-2 environment installed, you can proceed by whatever method best suits your style. Chapters 4 and 5, along with Chapters 7 and 8, contain information about the TopSpeed Modula-2 environment — the compiler, linker, library, etc. For information about the Modula-2 language, refer to Chapter 6 and to the Modula-2 Tutorial by K. N. King, included in your package.
  479. If You Are Patient
  480. To get as much out of the system as possible, we suggest that you read through the case studies in Chapter 4. Before using the environment any further, you may find it a good idea to browse Chapter 5 about the TopSpeed Modula-2 environment.
  481. If You Dislike Reading Manuals
  482. Then you’re probably not reading this anyway. If you are, we’re sure you’ll find IfFlU most useful.
  483. Try pressing |IfTI| and then find out for yourself how to compile and execute the example programs named PROG* . MOD.
  484. Modula-2
  485. Case Studies
  486. This chapter presents a series of case studies that serve as an informal introduction to the Modula-2 language and to the TopSpeed Modula-2 environment. The chapter does not go into sufficient detail to serve as a tutorial on either the language or the TopSpeed Modula-2 environment. See the Modula-2 Tutorial, for such an introduc­tion to Modula-2, and later chapters (especially Chapter 5) for a discussion of the environment.
  487. The examples will use the default TopSpeed Modula-2 configuration that comes on the diskettes in your package. For example, we’ll assume the Modula-2 program and library files are in the same directory. We’ll also assume that the source files for the programs are in this same directory. You may want to change this setup. In that case, simply make the appropriate adjustments as you work through the examples.
  488. Each study serves to illustrate individual aspects of the language rather than the construction of complex algorithms; it is not necessary to fully understand how the programs work. In addition, the examples illustrate the use of TopSpeed Modula-2 commands and features.
  489. We’ve tried to make the examples interesting, but still possible to follow. Note, however, that the level of programming knowledge assumed increases sharply from one study to the next. You should work through at least some of the examples and study the source code for the simpler examples.
  490. TopSpeed M2 Files Edit Compile Make
  491. Link
  492. Run
  493. Run ii
  494. Togl HI
  495. B-se 1 ect L^j-cance 1
  496. FIGURE 4-1 TopSpeed Modula-2 screen after specifying file to run
  497. Hello
  498. To run the first program, type M2 and press |lEnter||. After a few seconds, the main TopSpeed Modula-2 menu will appear. Press [E] to specify that you want to Run an example. You’ll be asked to enter the name of the main program module in a box on the screen. Type progl in this box. (You don’t need to include the . mod extension.) After you type this, but before you press ||Enter||, the screen will look like the one in Figure 4-1.
  499. The program will be compiled and then executed, and the word “hello” will appear on your screen. After you press |lEsc||, the main menu will again be available. You can either press |[ATt]|[Xl] to quit, or you can look at the source file.
  500. To edit the source file, select File from the main menu (type 0 or move the cursor to Files and then press |lEnter]|), Select Load File, and specify progl as the file to edit in window 1, then press |(Enteri|. To leave the TopSpeed Modula-2 environment — even from the editor — press IAlt|fx]|.
  501. In the text window, you’ll find the following source code:
  502. MODULE progl;
  503. (* This program writes 'hello' on the screen *)
  504. FROM IO IMPORT WrStr;
  505. BEGIN
  506. WrStr ('hello') ;
  507. END progl.
  508. Although this is just about the simplest program possible, there are several important points to understand before going on.
  509. The program consists of only the main module, named progl. The body of the program — the material between BEGIN and END — consists of a single statement. The program calls a library procedure to write the word “hello” on the screen.
  510. The following features of Modula-2 are illustrated in the program:
  511. • Upper and lower case letters are not equivalent. Words that have a special mean­ing to the compiler are always written in upper case (capital letters). In this ex­ample, there are six words of this sort. Thus, the program would not compile if the last line had begun with End instead of END in uppercase letters.
  512. • MODULE progl; says that this program is called progl. The file in which the program text is stored must be given the name progl. mod to match the module name.
  513. • Comments start with (* and are terminated by *). Comments do not change the meaning of the program but are included to help explain it to a reader. (However, comments beginning with (*$ are interpreted as instructions to the compiler, as you’ll see later.)
  514. • FROM IO IMPORT WrStr; makes the procedure WrStr in the library module IO available for use by the rest of the program. IO is a standard library module supplied with the TopSpeed Modula-2 system.
  515. • The BEGIN marks the start of the executable statements. Statements are the parts of the program that actually do something when you run the program.
  516. • The statement WrStr ('hello'); causes the string ‘hello’ to be output. In Modula-2 there is no built-in ‘print’ statement. Instead, input/output (I/O) is done by invoking library procedures such as WrStr.
  517. • The line, END progl., marks the end of the program. Notice the period, which must be included at the end of every program.
  518. This first program is illustrative but not at all useful. Here is something a bit more interesting.
  519. Pythagoras
  520. To run the second program, simply go through the same sequence of steps as for progl. Enter prog2 instead of progl, however. The source code for prog2 . mod is shown in the following listing:
  521. MODULE prog2;
  522. (* This program writes out some Pythagorean triples *)
  523. FROM IO IMPORT WrStr, WrLngCard, WrLn;
  524. VAR a,b,o:LONGCARD;
  525. BEGIN
  526. FOR c := 1 TO 100 DO
  527. FOR b := 1 TO c DO
  528. FOR a := 1 TO b DO
  529. IF a*a + b*b = c*c THEN
  530. WrLngCard(a,1);
  531. WrStr(', ');
  532. WrLngCard(b,1);
  533. WrStr (', ');
  534. WrLngCard(c,1) ;
  535. WrLn;
  536. END;
  537. END;
  538. END;
  539. END;
  540. END prog2.
  541. This program searches for positive numbers a, b, c satisfying the equation a2+b2 = c2. For example 3*3 + 4*4 = 9 + 16 = 25 = 5* 5, so a = 3,6 = 4, c = 5 is a solution to the equation. If the sides of a triangle have these lengths, the triangle is right-angled. According to legend (probably untrue), the ancient Egyptians used this fact to help build the pyramids.
  542. The method used by the program is the “brute force” approach — try possible values for a, b and c, checking to see if the equation is satisfied, a, b and c need to be represented by variables — that is, objects that take on different values as the execution of the program progresses. Each variable is declared before it is used.
  543. The FOR Statement
  544. To do its work, the program loops through possible values for a, b, and c. Each of these values is handled in a separate loop. For example, the statement
  545. FOR c := 1 TO 100 DO
  546. END;
  547. causes the statements between DO and the END in the second-to-last line of the program to be executed repeatedly. The variable c is set, successively, to 1, 2,..., 100. The other FOR statements are similar, and, because they are ‘nested’, the variables take on all the possible combinations of values such that a <= b <= c. With such
  548. nested loops, the outermost loop changes most slowly and the innermost loop changes most quickly.
  549. To make it easy to see which END corresponds to which FOR, we use the convention that the END is written directly beneath the corresponding FOR, and the statements in between are indented. This convention also applies to other statements that require an END.
  550. The statement
  551. IF a*a + b*b = c*c THEN
  552. END;
  553. says that the statements between THEN and the ‘matching’ end are to be executed only when the current values of a,b, c satisfy the equation. Thus we only write out the triples in which we are interested. The matching END will be the one at the same level of indentation as the IF statement.
  554. Exercise
  555. As an exercise, you might like to try to find some solutions to the equation a3+63+c3 = d3. The following steps provide one way to do this:
  556. 1. Copy PR0G2 .MOD to PR0G2A.M0D to put the modified program in a separate file.
  557. 2. Type M2 to call up the TopSpeed Modula-2 system.
  558. 3. Select File, then Load from the Main menu and the File menu, respectively.
  559. 4. Type PR0G2A as the file to load, and press lEnter||.
  560. 5. Make the necessary changes in the program file.
  561. 6. Once you’ve made the changes, press II Ait|||Rll to compile and execute the modified program.
  562. 7. Once the program works to your satisfaction, press ||ALT||x|| to leave the Modula-2 system. You’ll be asked whether you want to save PR0G2A.M0D. Answer Y to this question.
  563. You’ll find that this program takes quite a while to execute, since it needs to search through so many values. If you want to interrupt the program, press ICtrI||Break]|. The |Break|| key is the same as the one often marked [Scroll Lock| Once the program is interrupted, press lEsc|[ to continue.
  564. How about some music? The next example shows how to use sound capabilities in your programs.
  565. Music
  566. The following program uses the loudspeaker in your computer to play a couple of musical scales. The example shows how to define and include a procedure in a module, and shows how to construct new data types.
  567. MODULE prog3;
  568. (* This program plays musical scales *)
  569. FROM Lib IMPORT Sound, NoSound, Delay;
  570. FROM MATHLIB IMPORT Exp,Log;
  571. CONST MiddleC = 131.0;
  572. TYPE NoteType = SHORTINT;
  573. TYPE ScaleType = ARRAY [1..8] OF NoteType;
  574. CONST major = ScaleType(0,2,4,5,7,9,11,12);
  575. CONST minor = ScaleType(0,2,3,5,7,8,11,12);
  576. PROCEDURE PlayScale(mode : ScaleType; key : NoteType);
  577. VAR
  578. i:[1..8];
  579. note:NoteType;
  580. freq:LONGREAL;
  581. BEGIN
  582. FOR i := 1 TO 8 DO
  583. note := key + mode[i];
  584. freq := MiddleC * Exp(LONGREAL(note) * (Log(2.0)/12.0));
  585. Sound(CARDINAL(freq));
  586. Delay(200);
  587. END;
  588. NoSound;
  589. Delay (500);
  590. END PlayScale;
  591. BEGIN
  592. PlayScale(major, 0); (* C major *)
  593. PlayScale(minor, 2); (* D minor *)
  594. END prog3.
  595. Data Types
  596. Data types are used to specify which values a variable can take. Modula-2 has a number of built-in data types, such as SHORTINT, LONGREAL, CARDINAL, LONG- CARD, CHAR, BOOLEAN. Notice that there are several ways to represent a number value. A representation should be chosen that ensures that the value of each expres­sion falls within the range of numbers represented.
  597. There are also several ways of constructing new data types. For example, Scale- Type is an array of values. The line
  598. TYPE ScaleType = ARRAY [1..8] OF NoteType;
  599. defines a new data type, called ScaleType, whose values consist of 8 independent components (cells) numbered 1,2 .. 8. In the program, mode is declared to be of type ScaleType. The components of mode are referred to as mode [e], where e is some expression. Thus the assignment
  600. note := key + tnode[ij;
  601. sets the value of note to the sum of the value of key and the value of the ith component of mode.
  602. Constant Declarations
  603. In the program, there are also some constant declarations.
  604. CONST MiddleC = 131.0;
  605. says that wherever the name MiddleC occurs in the program, the value 131.0 is to be substituted.
  606. CONST major = ScaleType(0,2,4,5,7,9,11,12);
  607. says that where the name major occurs, the value is of type ScaleType, and the components are the eight values listed. That is, major is an array, with eight cells. For example, major[7] would have the value 11.
  608. Procedures
  609. A procedure called PlayScale has been defined to “play” the actual sequence of notes. The procedure plays the (eight) notes in a particular musical scale, starting with a specified note. To make it possible to specify the scale and the starting note, the procedure takes two parameters. In PlayScale, the first parameter determines the intervals in the scale, and the second determines the first note of the scale. The scale intervals are passed in an array of values, and the starting note is passed as a small number.
  610. Procedure definitions are similar in form to a complete program: they contain decla­rations followed by a list of statements.
  611. There are two calls to PlayScale:
  612. PlayScale(major, 0);
  613. plays a C major scale, and
  614. PlayScale(minor, 2);
  615. plays a D minor scale.
  616. A statement of the form
  617. variable :« expression
  618. says that the value of the variable is to be set equal to the value of the expression. Where a variable appears in an expression the current value of that variable is used.
  619. Strong Typing
  620. Modula-2 is a ‘strongly typed’ language. This means that the type of each expression must be ‘correct’ for the context in which it occurs. In particular, the types of the operands of a binary operator must match. An expression can be converted to another type by enclosing it in parentheses and placing the required type name in front. In the example, the variable note is converted from SHORTINT to LONGREAL.
  621. Library Routines
  622. The two IMPORT lines at the beginning of prog3 enable the program to use several procedures from two library modules. From the Lib module, the program uses three functions for producing and spacing sounds. From the MATHLIB module, the program uses the Exp and Log procedures.
  623. The next program also uses an array, but in a more complicated way.
  624. Anagram
  625. The following program finds and displays all the permutations of a string of charac­ters. A permutation is a rearrangement — in this case, of characters — where the order of the characters is taken into account. For example, there are six permutations of the letters, ‘a,’ ‘b,’ and ‘c’
  626. abc bac cab
  627. acb bca cba
  628. The program displays these permutations, or anagrams, of the string in an order based on the ASCH character codes. Procedure NextPerm does the real work in the program. This procedure illustrates several new features about procedures and parameters.
  629. The following listing contains the source code for prog4:
  630. MODULE prog4;
  631. (* This program displays the permutations of a string in alphabetic order *)
  632. IMPORT IO, Str;
  633. TYPE StringType = ARRAY [0..9] OF CHAR;
  634. PROCEDURE NextPerm(n:CARDINAL;
  635. VAR s:StringType;
  636. VAR wrap:BOOLEAN);
  637. (* This procedure updates s to the next permutation of the first n characters of s. The sequence of permutations generated by successive calls is in 'dictionary' order. If s is the last string in the sequence, the first is returned. The boolean result wrap is used to indicate this event *)
  638. VAR
  639. i:CARDINAL; (* s[i-l] is the most significant char changed *) j:CARDINAL; (* s[j] is the char to be swapped with s[i-l] *) tmp:CHAR;
  640. BEGIN
  641. IF n = 0 THEN
  642. wrap := TRUE;
  643. RETURN;
  644. , END; <
  645. 1 := n - 1;
  646. LOOP
  647. IF i = 0 THEN
  648. wrap := TRUE;
  649. EXIT;
  650. END;
  651. IF s[i-l] < s[i] THEN
  652. j := n - 1;
  653. WHILE s[j] <= s[i-l] DO
  654. tmp := s[j]; s[j] := s[i-l]; s[i-l] := tmp; (* swap *) wrap : = FALSE;
  655. EXIT;
  656. END;
  657. i := i - 1;
  658. END;
  659. (* s[i]..s[n-l] are in reverse order, reversing them yields the minimum permutation we require *)
  660. j := n - 1;
  661. WHILE i < j DO top := s[j]; s[j] := s[ij; s[i] := tmp; i := i + 1; j := j - 1;
  662. END;
  663. END NextPerm;
  664. VAR Inputstring:StringType; wrap:BOOLEAN;
  665. online:CARDINAL; (* number of strings in output line *) len:CARDINAL;
  666. BEGIN
  667. 10.WrStr('Enter string : ');
  668. 10.RdStr(Inputstring);
  669. len := Str.Length(Inputstring); REPEAT
  670. NextPerm(len,InputString,wrap);
  671. UNTIL wrap; online := 0; REPEAT
  672. 10.WrStr(Inputstring);
  673. I0.WrStr(' '); online := online + 1; IF online = 6 THEN lO.WrLn; online := 0;
  674. END;
  675. NextPerm(len,InputString,wrap);
  676. UNTIL wrap;
  677. END prog4.
  678. This program uses an array of characters to represent a string. The definition,
  679. TYPE StringType = ARRAY [0..9] OF CHAR;
  680. specifies a 10 element array, with each cell containing a CHAR value.
  681. More About Procedures and Parameters
  682. NextPerm is another example of a procedure. The list of parameters that follows the declaration of the procedure name is known as the formal parameter list. This list specifies the slots through which information can be passed. When the procedure is called, a matching list of actual parameters, or arguments, must be supplied.
  683. In this case, there are 3 formal parameters declared:
  684. n:CARDINAL
  685. VAR s:StringType
  686. VAR wrap:BOOLEAN
  687. Variable and value parameters You can always pass information into a procedure through a parameter, but you can only pass information back out through a parameter under certain conditions. Where a formal parameter is preceded by the keyword VAR (as in the second and third parameters for NextPerm), the following points apply:
  688. • the parameter is described as a variable parameter
  689. • you must specify a variable of the appropriate type as an argument (actual pa­rameter) when calling the procedure
  690. • if the parameter is assigned a value within the procedure, the value of the cor­responding variable in the actual parameter list is updated; thus variable param­eters can be used to return results from a procedure
  691. On the other hand, if a formal parameter is not preceded by the keyword VAR, then:
  692. • the parameter is described as a value parameter
  693. • when calling the procedure, you can use any expression that evaluates to a value of the ‘correct’ type as the corresponding actual parameter
  694. • assigning a value to the parameter does not affect the value of the corresponding actual parameter; thus value parameters cannot be used to return results from the procedure
  695. Explaining how procedure NextPerm actually works is quite tricky and beyond the scope of this chapter, which is about the TopSpeed Modula-2 language and environment, rather than complex algorithms. You might like to try to figure it out for yourself. The material in this manual doesn’t depend on your doing this, however.
  696. More About Loops
  697. Program 4 makes use of several different kinds of loops. You’ve already seen the FOR loop in earlier examples. The current example uses a more general form of loop. A statement of the form
  698. LOOP
  699. END;
  700. says that the enclosed statements are to be executed repeatedly until an EXIT state­ment is executed.
  701. Modula-2 also has WHILE and REPEAT statements to control looping. These con­structs can both be expressed using LOOP as the following listings show. In each case, the WHILE or REPEAT loop on the left is equivalent to the LOOP construct on the right:
  702. WHILE expression DO
  703. END;
  704. REPEAT
  705. UNTIL expression;
  706. LOOP
  707. IF NOT expression THEN EXIT;
  708. END;
  709. END;
  710. LOOP
  711. IF expression THEN EXIT;
  712. END;
  713. END;
  714. Notice that for a REPEAT loop the enclosed statements are always executed at least once, since nothing is tested until the end of the loop is reached. For a WHILE loop, on the other hand, the statements in the loop may not be executed at all, because the system checks up front whether expression is still TRUE.
  715. Creating Modules
  716. The next example program will also need to use NextPerm. Such reuse of proce­dures occurs frequently in programming, so Modula-2 allows you to make your own ‘library’ module. To make such a module, you need to create two files. One is the definition file, which specifies what the module does, the other is the implementation file, which specifies how it is to be done. The following discusses how you could make a module for the procedure NextPerm.
  717. Creating a Definition File The definition file will contain the parameter list for the procedure, as well as any data structures needed for the procedure. Definition files have the extension . def. The following listing contains the code for a definition file, which we’ll call perms. def:
  718. DEFINITION MODULE perms;
  719. PROCEDURE NextPerm(n:CARDINAL; VAR s:ARRAY OF BYTE;
  720. VAR wrap:BOOLEAN);
  721. (* This procedure updates a to the next permutation of the first n bytes of s. The sequence of permutations generated by successive calls is in 'dictionary' order. If s is the last string in the sequence, the first is returned. The boolean result wrap is used to indicate this event *) END perms.
  722. Creating an Implementation File The implementation file actually spec­ifies the details of the procedure — in this case, the individual statements that ac­complish the permutation task. Implementation files have the same name as the def­inition files, but have the extension .mod.
  723. IMPLEMENTATION MODULE perms;
  724. PROCEDURE NextPerm(n:CARDINAL; VAR s:ARRAY OF BYTE;
  725. VAR wrap:BOOLEAN);
  726. VAR i:CARDINAL; (* s[i-l] is the most significant byte changed *) j:CARDINAL; (* s[j) is the byte to be swapped with s[l-l] *) toy:BYTE;
  727. BEGIN IF n = 0 THEN wrap :■ TRUE; RETURN;
  728. END;
  729. i :■ n - 1;
  730. LOOP
  731. IF i - 0 THEN
  732. wrap :» TRUE; EXIT;
  733. END;
  734. IF s[i-1] < s[i] THEN j := n - 1;
  735. WHILE s[j] <= s[i-1] DO
  736. j := j - 1;
  737. END;
  738. tmp := s(jj; s[j] := s[i-l); s[i-l] :■ tmp; (* swap *) wrap : = FALSE;
  739. EXIT;
  740. END;
  741. i := i - 1;
  742. END;
  743. (* s[i]..s[n-l] are in reverse order, reversing them yields the minimum permutation we require *) j := n - 1;
  744. WHILE i < j DO trap := s[j]; «[j] .[!]; s[i] := tmp;
  745. i := 1 + 1; j := j - 1;
  746. END;
  747. END NextPerm;
  748. END perms.
  749. Notice that the identical line (END perms.) completes both the definition and im­plementation parts.
  750. Although in this example the module perms implements only one operation (pro­cedure), it is more usual for a module to implement a whole group of related proce­dures. (Note that TopSpeed Modula-2 implements true libraries in the sense that only the procedures that are actually used will be included in the complete program ).
  751. Open Array Parameters
  752. A small change has been made in procedure NextPerm, to make it more generally useful.
  753. VAR s:StringType;
  754. has been changed to
  755. VAR s:ARRAY OF BYTE;
  756. This causes the compiler to relax the type checking rules. This type of parameter is called an open array parameter, and is useful because it allows you to pass arrays of different sizes. The elements of s are numbered 0,1,..HIGH (s). HIGH is a predefined procedure that returns the index of the highest cell possible for an open array of the specified type. (The use of BYTE rather than CHAR allows you to pass arrays of SHORTCARD as well as arrays of CHAR.)
  757. Here is a program that makes use of the perms module to solve a puzzle.
  758. Puzzle
  759. The next program illustrates another type of procedure in Modula-2 — one which returns a value. This type of procedure is similar to a function in Pascal.
  760. MODULE prog5;
  761. (* this program lists the 9-digit numbers, containing every digit from 1 to 9 which are a product of three 3-digit numbers, which also contain every digit from 1 to 9 *) IMPORT IO;
  762. FROM perms IMPORT NextPerm;
  763. PROCEDURE check(n:LONGCARD):BOOLEAN;
  764. (* Checks if the digits of n are a permutation of 1..9 *) VAR i: [1. .9];
  765. digit: [0. .9] ;
  766. seen:ARRAY [0..9] OF BOOLEAN;
  767. BEGIN seen[0] := TRUE; FOR i := 1 TO 9 DO seen[i] FALSE;
  768. END;
  769. FOR i := 1 TO 9 DO
  770. digit : = CARDINAL(n MOD 10); (* n MOD 10 is the remainder when n is divided by 10 *)
  771. IF seen[ digit ] THEN RETURN FALSE;
  772. ELSE seen[ digit ] :- TRUE;
  773. END;
  774. n := n DIV 10; (* DIV means whole number division *) END;
  775. RETURN TRUE;
  776. END check;
  777. VAR d: ARRAY[0..8] OF SHORTCARD; a,b,c:CARDINAL; n:LONGCARD; i:CARDINAL;
  778. wrap:BOOLEAN;
  779. BEGIN FOR i := 0 TO 8 DO d[i] :- SHORTCARD(i) + 1;
  780. END;
  781. PRP17.LT
  782. a := CARDINAL(d[0])*100 + CARDINAL( d[l]*10 + d[2] );
  783. b := CARDINAL<d[3])*100 + CARDINAL( d[4]*10 + d[5] );
  784. c := CARDINAL(d[6])*100 + CARDINAL( d[7]*10 + d[8] );
  785. n :■= LONGCARD (a) * LONGCARD (b) * LONGCARD(c);
  786. IF check(n) THEN
  787. IO.WrStr('A solution is ');
  788. IO.WrCard(a, 1);
  789. IO.WrStr(' x ');
  790. IO.WrCard(b, 1) ;
  791. IO.WrStr(' x ');
  792. IO.WrCard(c, 1);
  793. IO.WrStr(' -');
  794. IO.WrLngCard(n, 1);
  795. IO.WrLn;
  796. END;
  797. NextPerm(9,d,wrap);
  798. UNTIL wrap;
  799. END prog5.
  800. Function Procedures
  801. The procedure check is an example of a function procedure (often referred to simply as a function). Functions are called from within expressions, and the value they return is substituted in the expression. Every function returns a value. The type of the result is indicated after the formal parameter list. For example
  802. PROCEDURE check(n:LONGCARD):BOOLEAN;
  803. indicates that check is a function which returns a BOOLEAN result. The result actually returned is specified by a statement of the form
  804. RETURN expression
  805. within the function body.
  806. This statement can appear anywhere among the statements of a function, and causes the execution of the function to terminate, yielding the value of the expression as the function result.
  807. Subrange Declarations
  808. The declaration
  809. VAR digit:[1..10] ;
  810. needs careful explaining. In fact, this expression is a short form of
  811. VAR digit:CARDINAL[1..10];
  812. The second version of the statement declares digit as a variable of type CARDINAL, but one which takes on values only between 1 and 10, inclusive. In the second statement, each of these points is explicit. In the first statement, only the variable name and the range of possible values are explicit; the variable type is implicit, and is assumed to be CARDINAL.
  813. A declaration in which a variable is allowed to take on only some of the possible values normally allowed for the type is called a subrange declaration. In the example, CARDINAL is known as the base type. It is this base type which determines whether a value is ‘correct’ for the context in which it is being used.
  814. More on Types
  815. This issue of type correctness may seem confusing, but an example should make things clear. Suppose procedure check was changed, to contain the (incorrect) state­ment:
  816. digit := n MOD 10;
  817. The type of n is LONGCARD, so n MOD 10 is also of type LONGCARD. Thus, the statement would be assigning a LONGCARD value to a variable. However, the base type of digit is CARDINAL, so the compiler would report that the assignment is illegal because of incompatible types. The correct statement is
  818. digit := CARDINAL(n MOD 10);
  819. as in the program.
  820. TopSpeed Modula-2 supplies a selection of libraries. The next few examples will make use of several of them, while giving examples of other features of the Modula-2 language.
  821. Graphics
  822. The next program, prog6, uses the TopSpeed Modula-2 graphics module, Graph, to do its task. This module provides some basic procedures for accessing the screen through various graphics boards, including the CGA (default), EGA, VGA, Hercules. The module includes procedures to let you do graphics with any of these boards.
  823. Notice that in this example Width and Depth are variables imported from Graph. So far, we’ve only imported procedures in the examples. In fact, Modula-2 allows procedures, constants, variables and types to be imported.
  824. If you haven’t got a CGA board, then before you compile and run this program, add a procedure call to initialize the system to use the graphics routines appropriate for your graphics board. By default, the initialization code for the CGA is run. The available initialization procedures are: InitCGA InitHerc
  825. InitEGA InitATT
  826. Init VGA
  827. To execute the appropriate initialization code, call the required procedure before the call to RANDOMIZE in the main program.
  828. MODULE prog6;
  829. (* This program draws patterns on the screen *) FROM Lib IMPORT RANDOM, RANDOMIZE;
  830. FROM Graph IMPORT Circle,Disc,GraphMode,TextMode,Width,Depth;
  831. IMPORT IO;
  832. TYPE
  833. FunnyType = RECORD q : INTEGER; (* value *) d : INTEGER; (* rate of change *) min : INTEGER; max : INTEGER;
  834. END;
  835. PROCEDURE init(VAR v:FunnyType);
  836. BEGIN
  837. v.q := v.min;
  838. v.d := INTEGER(RANDOM(v.max-v.min));
  839. END init;
  840. PROCEDURE bounce(VAR v:FunnyType);
  841. (* Update v.q, 'bouncing' when it goes out of range *) BEGIN
  842. WITH v DO
  843. q := q + d;
  844. IF q < min THEN
  845. q := 2*min-q;
  846. d := -d;
  847. END;
  848. IF q > max THEN
  849. q := 2*max-q;
  850. d := -d;
  851. END;
  852. END;
  853. END bounce;
  854. VAR
  855. x,y : FunnyType;
  856. color,radius : CARDINAL;
  857. BEGIN
  858. (* Initialization call for your graphics board here. For example: *) (* InitEGA; *)
  859. RANDOMIZE;
  860. x.max := Width-1; x.min := 0;
  861. y.max := Depth-1; y.min := 0;
  862. 10.WrStr('Press space to continue, any other key to stop'); lO.WrLn;
  863. WHILE NOT lO.KeyPressed() DO
  864. END;
  865. GraphMode;
  866. WHILE I0.RdKey() = ' ' DO
  867. init(x);
  868. init(y);
  869. REPEAT
  870. color := RANDOM (16);
  871. UNTIL color MOD 5 <> 0; (* fill using 2 colors *)
  872. radius := 2 + RANDOM(5);
  873. WHILE NOT lO.KeyPressed() DO
  874. bounce(x);
  875. bounce(y);
  876. Disc(x.q, y.q, radius, color);
  877. Circle(x.q, y.q, radius, color MOD 4);
  878. END;
  879. Disc(0,O,Width+Depth, 0); (* clear screen *)
  880. END;
  881. TextMode;
  882. END prog6.
  883. Using Library Routines
  884. The line:
  885. IMPORT IO;
  886. tells the system to make all the public procedures and data defined in module IO available. This makes over three dozen procedures available. Procedures from a mod­ule imported in this global manner must be referred to by a name that includes the module name. For example,
  887. IO.WrLn;
  888. is used in the main program body for prog6, as opposed to WrLn, as we had in earlier examples.
  889. The program uses ‘low-level’ keyboard input:
  890. • IO.KeyPressed() tells whether a key has been pressed
  891. • IO. RdKey () reads a single character from the keyboard without echoing it or performing any other processing
  892. Note that functions without parameters must be called using an empty parameter list.
  893. The function RANDOM (n) returns a ‘pseudorandom’ whole number in the range 0 .. n-1. RANDOMIZE causes a different sequence of numbers to be generated each time the program is run (by using the time and date as a seed to start the number generator).
  894. RECORD Types
  895. The program declares a record type called FunnyType. Record types are useful for grouping related variables together, regardless of whether each of these variables is of the same type.
  896. The components of a record variable, known as fields, can be accessed either by using a ‘.’ and the field name, as in procedure init, or by using a WITH statement, as in procedure bounce. Although WITH statements may make your programs easier to type, they can also make programs more difficult to follow — since it may not always be easy to determine which assignments refer to fields of the record. For this reason, WITH statements are best used in moderation (if at all).
  897. Sorting
  898. Here is a program to sort the lines of a text file into order. This program makes extensive use of library procedures, and even circumvents Modula-2’s strong typing to accomplish parts of its task.
  899. MODULE progl;
  900. (* Sorts lines of a file into order, deleting duplicates *) IMPORT IO, FIO, Lib, Storage, Str;
  901. TYPE
  902. StringType - ARRAY [0..255] OF CHAR;
  903. StringPointerType = POINTER TO StringType;
  904. VAR
  905. p : ARRAY [1..10000] OF StringPointerType;
  906. PROCEDURE Less(i,j:CARDINAL):BOOLEAN; BEGIN
  907. RETURN Str. Compare (p[i]A, p[ j]A) < 0 ;
  908. END Less;
  909. PROCEDURE Swap(i, j :CARDINAL);
  910. VAR tmp:StrlngPointerType;
  911. BEGIN
  912. tmp := p[i]; p[i] := p[jl; p[j] :» tmp;
  913. END Swap;
  914. VAR s: StringType;
  915. len:CARDINAL;
  916. i,n:CARDINAL;
  917. InFile,OutFile:FIO.File;
  918. buffer:ARRAY [1..512+FIO.BufferOverhead] OF BYTE;
  919. BEGIN
  920. (* check parameters *)
  921. IF Lib.ParamCount() <> 2 THEN
  922. IO.WrStr('Try again : prog7 input-file output-file');
  923. lO.WrLn;
  924. HALT;
  925. END;
  926. (* read file in *)
  927. Lib.ParamStr(s, 1); InFile := FlO.Open(s);
  928. FIO.AssignBuffer(InFile, buffer);
  929. n := 0; LOOP FIO.RdStr(InFile, s); IF FIO.EOF THEN
  930. EXIT;
  931. END;
  932. IF n - HIGH(p) THEN
  933. IO.WrStr('Too many lines!');
  934. lO.WrLn;
  935. EXIT;
  936. END;
  937. INC (n) ;
  938. len := Str.Length(s);
  939. Storage.ALLOCATE(p[n], len + 1);
  940. Lib.Move(ADR(s), ADR(p[n]A), len + 1);
  941. END;
  942. FIO.Close(InFile);
  943. (1 2 sort file in memory *) Lib.HSort(n, Less, Swap);
  944. (* write file out *)
  945. Lib.ParamStr(b, 2); OutFile :« FIO.Create(s);
  946. FIO.AssignBuffer(OutFile, buffer);
  947. FOR i := 1 TO n DO
  948. IF (i = 1) OR (Str.Compare (p[i]A, p[i-l]A) <> 0) THEN
  949. FIO.WrStr(OutFile, p[i]A);
  950. FIO.WrLn(OutFile);
  951. END;
  952. END;
  953. FIO.Close(OutFile);
  954. END prog7.
  955. Function Lib. ParamCount () returns the number of parameters on the command line when the program was invoked. Lib. ParamStr (s, n) is used to copy the nth parameter into s. If you run a program from the TopSpeed Modula-2 environment, you can set up the command line by using Options Run Command-Line.
  956. Command Line Arguments in
  957. the TopSpeed Modula-2 Environment
  958. TopSpeed HZ Files Edit Compile Hake Link Run
  959. Options
  960. Compiler Linker
  961. Run
  962. C - Connand line
  963. I1 Run Command line1
  964. stest.rau stest.srt |
  965. To enable each line from the input file to be stored in exactly the right amount of space, the library procedure Lib. Move is used. A straightforward assignment could not be used to copy the input line into the allocated storage, because only len+1 bytes have been allocated to hold the string. The assignment
  966. p[n]A := s;
  967. would copy 256 bytes (the length of a variable of type StringType). The library procedure Lib.Move, in which you can specify the number of bytes to be copied, has been used instead. The built-in function ADR, which yields the address of a variable, should be used with great care, because its parameter is not type checked.
  968. Heapsort and Quicksort
  969. PROCEDURE QSort(n:CARDINAL; Less:CompareProc; Swap:SwapProc);
  970. PROCEDURE Sort(1,r:CARDINAL);
  971. VAR i, j : CARDINAL;
  972. BEGIN
  973. WHILE r > 1 DO
  974. i :» 1+1;
  975. j := r;
  976. WHILE i <= j DO
  977. WHILE (i <= j) AND NOT Less(1,1) DO INC(l) END;
  978. WHILE (1 <= j) AND Less(l,j) DO DEC(j) END;
  979. IF 1 <= j THEN Swap(i,j); INC(i); DEC(j) END; END;
  980. IF j # 1 THEN Swap(j,l) END;
  981. IF j+j > r+1 THEN (* small one recursively *)
  982. Sort (j+1, r) ;
  983. r := j-1;
  984. ELSE
  985. Sort(1,j-1);
  986. 1 := j+1;
  987. END;
  988. END;
  989. END Sort;
  990. BEGIN
  991. Sort (1, n) ;
  992. END QSort;
  993. END Lib.
  994. The Quicksort algorithm works by partitioning the file on the basis of a chosen element (in this case the first), and then recursively calling itself to sort the two arrays that result. Essentially, the right array will come to contain the larger values and the left array will come to contain smaller values. By repeating this process on smaller and smaller arrays, the entire array is eventually sorted.
  995. Procedure Parameters
  996. Nested Procedures
  997. Notice that the procedure Sort is declared within the procedure QSort — it is nested in Quicksort. Sort can access both its own parameters and local variables, as well as the parameters and local variables of the enclosing procedure.
  998. In the implementation here, the call to sort the larger half has been replaced with a loop back to the start of the procedure. This is a form of ‘tail-recursion’ optimization, which ensures that the amount of stack needed for recursive activations is small.
  999. Recursion and the Compiler One of the problems of using recursion is that the amount of stack needed will vary with the size of the input. The stack check compiler directive (3$S+*) can be used to detect stack overflow (which could otherwise give very unpredictable effects), although of course it will result in some run-time overhead.
  1000. Calculator
  1001. TreeRecordType = RECORD CASE kind:TokenType OF | number :
  1002. NumberValue : LONGREAL;
  1003. | add,sub,mul,div : left : TreeType; right : TreeType;
  1004. END;
  1005. END;
  1006. VAR
  1007. c:CHAR;
  1008. token:TokenType;
  1009. TokenNumberValue:LONGREAL;
  1010. PROCEDURE error(s:ARRAY OF CHAR); BEGIN
  1011. 10.WrStr(s);
  1012. lO.WrLn;
  1013. HALT;
  1014. END error;
  1015. PROCEDURE readtoken; VAR s:ARRAY[0..99] OF CHAR; i: [0..99];
  1016. done:BOOLEAN;
  1017. oldc:CHAR;
  1018. BEGIN
  1019. LOOP oldc : = c; o := 10.RdChar ();
  1020. CASE oldc OF
  1021. • '+' : token := add; EXIT;
  1022. • : token := sub; EXIT;
  1023. • : token := mul; EXIT;
  1024. | : token := div; EXIT;
  1025. I ' (' : token := LeftParen; EXIT;
  1026. | ')' : token := RightParen; EXIT;
  1027. | CHAR(10),CHAR(13),CHAR(26) : token end; EXIT;
  1028. | '0'..'9' : (* read a real number *) i := 1; s[0] := oldc;
  1029. WHILE (c >= '0') AND (c <= '9') DO
  1030. s[i] c;
  1031. INC(i) ;
  1032. c := IO.RdChar();
  1033. END;
  1034. IF c<>'THEN (* add decimal point if none in input *) s[i] INC(i);
  1035. ELSE
  1036. REPEAT (* read fraction part *) s[i] c;
  1037. INC(i);
  1038. c := IO.RdChar ();
  1039. UNTIL (C < '0') OR (c > '9'),’ END;
  1040. s[i] := CHAR(O);
  1041. TokenNumberValue :« Str.StrToReal(s, done); IF NOT done THEN
  1042. error('Bad number?');
  1043. END; token :« number; EXIT;
  1044. ELSE error('Bad character');
  1045. END;
  1046. END;
  1047. END readtoken;
  1048. PROCEDURE read(what:SyntacticType):TreeType;
  1049. VAR t,tl:TreeType;
  1050. BEGIN CASE what OF | factor :
  1051. IF token = LeftParen THEN readtoken; t := read(exp);
  1052. IF token « RlghtParen THEN readtoken;
  1053. ELSE error("Missing ')'");
  1054. END;
  1055. ELSIF token = number THEN
  1056. Storage.ALLOCATE(t, SIZE(tA)); tA.kind := number; tA.Numbervalue := TokenNumberValue; readtoken; ELSE
  1057. error('Missing number?'); END;
  1058. | term: t : = read(factor); WHILE (token = raul) OR (token = div) DO tl := t;
  1059. Storage.ALLOCATE(t, SIZE(tA));
  1060. tA.kind := token;
  1061. readtoken;
  1062. tA.left := tl;
  1063. tA.right := read(factor) ; END;
  1064. I exp: t := read (term); WHILE (token = add) OR (token = sub) DO tl := t;
  1065. Storage.ALLOCATE(t, SIZE(tA)); tA.kind := token; readtoken; tA.left := tl;
  1066. tA.right := read(term); END;
  1067. | main :
  1068. c IO.RdChar();
  1069. readtoken;
  1070. t := read(exp);
  1071. IF (token <> end) THEN
  1072. error('Missing operator?');
  1073. END;
  1074. END;
  1075. RETURN t;
  1076. END read;
  1077. PROCEDURE eval(t:TreeType):LONGREAL; BEGIN
  1078. CASE tA.kind OF
  1079. | number : RETURN tA.Numbervalue;
  1080. | add : RETURN eval(t*.left) + eval(tA.right);
  1081. | sub : RETURN eval(tA.left) - eval(tA.right);
  1082. | mul : RETURN eval(tA.left) * eval(tA.right); | div : RETURN eval(tA.left) / eval(tA.right); END;
  1083. END eval;
  1084. VAR
  1085. t:TreeType;
  1086. result:LONGREAL;
  1087. BEGIN
  1088. LOOP
  1089. 10.WrStr('Enter expression : ');
  1090. t :■» read (main);
  1091. result : = eval(t);
  1092. I0.WrStr(' =');
  1093. 10.WrLngReal(result, 4, 0) ;
  1094. 10.WrLn;
  1095. END;
  1096. END prog8.
  1097. Enumeration Data Types
  1098. The declarations:
  1099. TokenType = (number, add, sub, mul, div, LeftParen, RightParen, end);
  1100. SyntacticType = (main, exp, term, factor);
  1101. declare enumeration data types. The possible values of an enumeration type are just the names listed. Thus, any variables of type SyntacticType can take on four different values — main, exp, term, or factor.
  1102. Variant Records
  1103. A variant record is one with fields that may contain different types of information at different times. The template for a variant data structure is large enough to hold values associated with the largest type of information you’re using. See your Modula-2 Tutorial for more information about variant records.
  1104. The declarations:
  1105. TreeType = POINTER TO TreeRecordType;
  1106. TreeRecordType = RECORD
  1107. CASE kind: TokenType OF
  1108. I number :
  1109. NumberValue : LONGREAL;
  1110. | add,sub,mul,div :
  1111. left : TreeType;
  1112. right : TreeType;
  1113. END;
  1114. END;
  1115. define a ‘recursive’ data type. This definition says that a tree is made up of a field, kind, which is of type TokenType. Depending on the value of kind, a particu­lar tree has either a real number (stored in field Numbervalue), or a left and right sub-tree (stored in fields left and right, respectively). The CASE keyword indi­cates this variant situation. In fact, the TreeRecordType also could be declared as:
  1116. TreeType = POINTER TO TreeRecordType;
  1117. TreeRecordType = RECORD
  1118. kind:TokenType;
  1119. NumberValue : LONGREAL;
  1120. left : TreeType;
  1121. right : TreeType;
  1122. END;
  1123. but this does not convey the sense as well. This version also requires more storage.
  1124. CASE Statements
  1125. There are several CASE statements in the program, used to select one of a group of statements for execution. The statements selected depend on the expression which follows the CASE keyword.
  1126. The case labels must be constant, but ranges are allowed, as in ' 0' . .' 9'. The CASE statement in procedure readtoken has an else part, which is executed if none of the case labels are matched.
  1127. This concludes the case studies. We hope you found the examples interesting. Ob­viously in the space available many points could not be fully explained. You should
  1128. look at the Modula-2 Tutorial for a more thorough introduction to Modula-2, or check Chapter 6 of this manual for a concise, but complete, definition of the lan­guage. The definitive book is Niklaus Wirth’s Programming in Modula-2 (third, cor­rected edition). In addition, there are several good books on Modula-2 that explain the Modula-2 language at greater length. For example, K.N. King’s Modula-2: A Complete Guide, (D.C. Heath, 1988), provides a very complete explanation of the language and how to use it.
  1129. Chapter 5
  1130. The TopSpeed Modula-2 Environment
  1131. In this chapter, you will learn about the TopSpeed Modula-2 environment. You’ll find brief summaries of the major environment features, the commands, and the options available in the Modula-2 environment.
  1132. The first part of the chapter discusses general features of the TopSpeed Modula-2 environment, including how to get started, the Help and Menu systems, and the use of Windows in the environment. The core of the chapter summarizes the commands available under the menus — including the File and Editor menus, as well as the other menus available. The last portion of the chapter describes how you can customize the TopSpeed Modula-2 environment to suit your needs and tastes.
  1133. TopSpeed Modula-2: Features
  1134. The TopSpeed Modula-2 development environment is a multi-window integrated de­velopment system. Within the environment, you can enter and edit your program, compile the text into executable code, and then run your completed program.
  1135. You can do all this without leaving the environment, and without long or complicated command sequences. The environment will also detect errors when you compile or run your program, and will take you to their exact position within the editor.
  1136. The environment is designed especially for developing programs that contain more than one compilation module, as is usually the case with a Modula-2 program. Four Editor Windows are provided, so you can view and edit up to four separate files simultaneously. Thus you can enter the text of an implementation file using one Editor Window, while viewing the relevant definition file in another. In addition to the four user windows, the environment provides an extra Editor Window, in which compile or run-time errors are pointed out in the source text.
  1137. To ensure that each component module of a program is compiled and up-to-date, the environment provides an automatic Make facility. Thus if any part of a program is changed, all modules affected by that change are automatically recompiled and a new executable file is generated.
  1138. The menu system and key setups are all fully reconfigurable to your own personal preferences, by editing a simple text file (M2 .mnu). This allows you to change the text and structure of the menu tree, and the Shortcut keys that invoke environment functions. You can even assign your own programs to menu and key commands.
  1139. The multiple window editor is also fully configurable; you can easily make it resemble your own favorite editor. It is initially configured to be WordStar-compatible, familiar to users of Turbo Pascal or SideKick, although with the ability to edit up to five files simultaneously (including the Error Window) and with a much larger file capacity. As well as editing multiple files in multiple windows, the environment also allows you edit the same file at different positions in the text. For example, you could view the global variables for a module in one window, while editing another part of the module in another window.
  1140. Whenever you leave the environment, the current environment state is recorded, in­cluding which files are being edited and the position within each file. Also the win­dow layout and all user options are saved. When you reenter the environment it will automatically start up from where you left it, allowing you to continue immediately. (If you do not want to continue your previous session, you can use the /N command line option when starting a TopSpeed Modula-2 session, as described below.)
  1141. The hierarchical directory system in DOS can be very helpful in keeping your files in order. For example, you might put all your files with . OBJ extension into a separate directory; you might also keep all your source (. MOD) files in a separate directory.
  1142. In the TopSpeed Modula-2 environment, you can assign search paths specifying the directories in which various types of files can be found. With this useful feature, you can keep all files of a given kind (e.g. . OBJ files or library . DEF files) in a particular directory. In this way you can organize your filing system tidily and consistently, without having cluttered work directories.
  1143. To set up the intended location of files, you need to edit the text file that defines file-to-directory redirection, (M2.RED). See “The Redirection File,” page 77, for more details.
  1144. Starting Up the Environment
  1145. To start up the environment, enter the command M2 at the DOS prompt. The envi­ronment will run, first clearing the screen, then displaying the TopSpeed Modula-2 title banner, and then the Main Menu.
  1146. Files used by the environment include the following:
  1147. M2 . EXE The TopSpeed Modula-2 Environment
  1148. M2 . OVL Overlay file used by M2 . EXE
  1149. M2 . MNU Menu system definition (see “Menu Definition File Format,” page 83 )
  1150. M2. ERR Modula-2 error messages (see “Customizing the Error Messages,” page 92)
  1151. M2 . HER Help text
  1152. All of the above may be located in the start-up directory, i.e. the directory in which you keep M2 . EXE.
  1153. In addition the following files also may exist:
  1154. M2 . RED Redirection file (see “The Redirection File,” page 77)
  1155. M2 . SES Session file (see “Quit,” page 58)
  1156. M2 . SES contains details of your last session in the environment. If this file is present when you type M2, the environment resumes in the same state as when you left. This is true unless you use the /N compiler option, in which case the system ignores the M2 . SES file, and a new session starts instead. To use this option, type
  1157. M2/N
  1158. The Help System
  1159. Press ED] to get context sensitive on-screen help at any time while within TopSpeed Modula-2 the environment. You will get specific information related to your current location in the environment. You can also move around within the help system to look at other topics of interest. Press within the Help System for an index to all help topics available.
  1160. Help Lines
  1161. On the bottom line of the screen a single line is displayed, showing a summary of key functions for the current context. This information can help you use an unfamiliar function, without resorting to the help system or manual.
  1162. You can configure the Help line for the Main Menu and for the Editor Windows. You can also disable the display of help lines. See “Changing Help Lines,” page 83, for details.)
  1163. The Menu System
  1164. You can use pop-up menus to invoke all the facilities of the TopSpeed Modula-2 Environment. This is one of the two major ways in which you can invoke TopSpeed Modula-2 commands — the other being through use of Shortcut key sequences. Generally, you need only a few keystrokes to find and activate any function through menus. The menu system is fully reconfigurable to your own requirements (see “Cus­tomizing The Menu,” page 79).
  1165. Although you may have several menus visible on your screen at any given time, only one of these menu windows will be active at a time. The active menu has a double frame and highlighted command characters.
  1166. Menu commands always act upon the active menu. You can select a command by moving to the command you want, and then pressing || Enter|[ As you move, your cunent line will be in inverse video. This inverted line is called the menu bar, and is used to identify the command you wish to select. You can also select a command by typing the highlighted character in the command’s name. This form of the command will override the menu bar selection.
  1167. Moving Around Menus
  1168. The TopSpeed Modula-2 menu system is very detailed and thorough. The structure is organized as a tree, with the main menu at the top, and various submenus branching off from this one. The default Main Menu tree is shown in Figure 5-1. Several keys are useful for moving through the menu structure.
  1169. Q Moves the menu-bar down one line.
  1170. 0 Moves the menu-bar up one line.
  1171. |lEnter|| Opens a submenu if one exists, or activates the command at the menu bar if there is no submenu.
  1172. |[Esc|| Closes the current menu.
  1173. liHomell Moves the menu bar to the first line.
  1174. ||End]| Moves the menu bar to the last line.
  1175. Letter Pressing a letter that is highlighted in the active menu moves the menu bar to the line containing that letter, then activates the associated function or submenu.
  1176. PTopSpeed M2 Files
  1177. Edit Canpile Make
  1178. Link
  1179. Run Options Info assemble
  1180. == Files
  1181. Load file Pick file Save file ail save Main module Change dir Files dir Dos shell Execute Quit
  1182. ===== Load file
  1183. Windew 1: *.M® Window 2: *.DEF
  1184. Windew 3: *.MOD
  1185. Windew 4: *.DEF
  1186. = Pick file :
  1187. C:\DATABASE\TEST\TRACE.MOD C: \DATABASE\TEST\TRACE.DEF
  1188. C: \DATABASE\READKEY. MOD
  1189. C:\M2\LIB\STR.DEF
  1190. C:\M2\LIB\IO.DEF
  1191. C: \M2\LIB\FIO.DEF
  1192. C:\DATABASE\TRACE.TXT
  1193. — Load file —
  1194. 1 Ccnpiler Options =
  1195. := Options
  1196. Ccnpiler ■
  1197. Linker
  1198. Run
  1199. Editor
  1200. Setup
  1201. Make all
  1202. E - Stop on 1st error : OFF
  1203. F - Filename check : ON
  1204. N - Line numbers : OFF
  1205. F - Volatile variables : OFF
  1206. D - Generate debug info : OFF
  1207. B - Runtime checks default : OFF
  1208. J - Suppress libraries : OFF
  1209. == Linker Options 1
  1210. M - Map file : ON
  1211. I - Initiali ze segments : OFF S - Detailed segment map : OFF T - Trace module references : OFF C - Case sensitive link : CM W - Suppress warnings : OFF
  1212. — Run Options =~:—r
  1213. C - CCmmand line a - Auto make : CN
  1214. T - Timed run : OFF
  1215. F - Find error
  1216. ===== Editor Options =
  1217. a - Auto save files : OFF F - Default filenames E - Default extensions
  1218. N - Number of backups : 1
  1219. T - Top scroll zone : 0
  1220. B - Bottom scroll zone : 1
  1221. Environment Options
  1222. C - OGA snow check : OFF B - Bios scrolling : OFF H - High background : OFF X - Solid cursor : OFF
  1223. R - Load redirection file
  1224. L - Load opticns/windcws S - Save opticns/windcws
  1225. FIGURE 5-1 TopSpeed Modula-2 main menu structure
  1226. ||F10|| Returns to the Main Menu from wherever you are in the menu system. This is also the key that activates the Main Menu from outside the menu system, for example if you are in an Editor Window.
  1227. In addition to the above, there are also global Shortcut keys that you can use to invoke menus and commands. These are independent of the menu windows, and can be used even with no menu active on the screen. For example, in the preceding list ||F10|| is the ShortCut key that invokes the main menu. Shortcut keys are discussed in the next section.
  1228. Thus, there are three ways to activate any environment function:
  1229. • Use the menu to select the required function and press ||Enter||
  1230. • Type the character which is highlighted in the line for the desired command
  1231. • Press the appropriate ShortCut key (if one exists for this command)
  1232. ShortCut Keys
  1233. Many frequently used functions have predefined ShortCut keys assigned to them. Some of these commands are function keys and others consist of a key prefixed by ||Alt||. You can change or add to these commands by editing the menu configuration file, M2 .MNU (see See “Changing ShortCut Keys,” page 81). Initially, the following Shortcuts are defined:
  1234. ||F10|| Invokes the Main Menu.
  1235. |[Ait]|[X]| Exits the TopSpeed Modula-2 environment, returning to the DOS com­mand line. This is equivalent to the Files Quit menu command. Note that before you exit, you will be given a chance to save any edited text. The state of the environment also is saved.
  1236. ||Ait|||E|| Invokes the Editor. If you’re editing in more than one Editor Window, then llAitlllEll will take you to the Editor Window you last used. This is equivalent to invoking the Editor command from the Main Menu. See “The Editor,” page 59, for more details.
  1237. Invokes Editor Window 1
  1238. EEEH Invokes Editor Window 2
  1239. l(Ait]|[3|l Invokes Editor Window 3
  1240. ||Alt|||4|| Invokes Editor Window 4
  1241. Invokes the Error Editor Window, if it is active.
  1242. |[F5|| ‘Zooms’ the current Editor Window, making it the full size of the screen. If the window is already at full size, pressing EJI returns the window to its original size.
  1243. HU
  1244. EjjHI
  1245. HI
  1246. EE
  1247. Cycles through the currently open Editor Windows, making each active in turn.
  1248. Reviews the DOS screen. This allows you to review the last output produced by a program or DOS Shell. This is useful for examining the results of a program after you have returned to the environment. On entry to the environment the review screen is loaded with the screen previously visible. Compile, Make and Link all automatically clear the review screen, ready for the next time you run a program.
  1249. Activates the Information Window that contains useful information on the status of the environment. This is equivalent to the Info Main Menu command. See “The Information Window,” page 77.
  1250. Compiles a single file.
  1251. Makes an up-to-date executable program, compiling and linking as nec­essary.
  1252. Links already compiled files into an executable program.
  1253. Makes an executable program and then runs it. The above four are equivalent to the main menu commands Compile, Make, Link and Run, which provide the interface to the TopSpeed Modula-2 Compiler and Linker. See “Compiling and Running Programs,” page 67, for more details.
  1254. Creates a DOS Shell in which you can execute DOS commands and programs. On exit from the shell (by typing exit) the environment will be restored to its original state. This is equivalent to the Files DOS-Shell command. See “DOS Shell,” page 58.
  1255. Windows in the Environment
  1256. All interaction between the user and the TopSpeed Modula-2 Environment occurs within overlapping windows. These windows can be dynamically positioned, sized and colored according to your taste and requirements.
  1257. Generally, each window is associated with a single task or function. Fbr example, an Editor Window allows you to edit text, while the Compiler Window will contain messages from the compiler.
  1258. Each window is bounded by a frame. This, together with the coloring of the window, makes it clear where each window begins and ends, even when they overlap.
  1259. Whenever you are in the environment, there is always a single active window. As mentioned above, this window contains the task currently being performed — whether it involves an editor, a compiler, a menu or any of the other environment functions. You can always identify the active window by its double-lined frame, as opposed to the single frame of an inactive window.
  1260. The overlapping windows of each function are stacked on top of one other, according to the order in which the functions were invoked. The top window in the stack is always the active window. The active window is always fully visible, on the screen — that is, it is never obscured by other overlapping windows.
  1261. Throughout the environment, |lEsc|| always removes the active window from the screen and makes the next window in the stack active.
  1262. See “Changing Windows” on page 90 for details on how to reposition, resize, and recolor your windows.
  1263. Zoom/Unzoom
  1264. You can make each of the Editor Windows as large as the entire screen by pressing R|. This “zooms” you in so that the entire screen is now filled with the Window. Zooming removes the right and left edges and the bottom frame edge (except in the ErrorEdit window where the bottom line is reserved for error messages). Zooming in is convenient for full screen editing, allowing the maximum area possible for showing text.
  1265. You can move back out (“unzoom”) by pressing IF5|| again. This will restore the win­dow to its original size. The zoom state of each window is saved in the configuration and session files.
  1266. User Dialog Windows
  1267. When the environment needs some input from you, it opens a dialog window. These windows have three forms:
  1268. • Single line input
  1269. • Multiple line input
  1270. • File selection
  1271. Single Line Input Whenever it needs a one line response, the environment opens a single line input window — for example, when prompting for a filename.
  1272. This input window contains a description of the expected input (e.g. Filename:),
  1273. followed by an Editing Field in inverse video. Type your response in this field, and then press
  1274. to indicate that you have finished your input. Table 5-1 shows the
  1275. keys you can use when editing such a response.
  1276. TABLE 5.1.
  1277. Editing Commands for Dialog Windows
  1278. o or HI Character left
  1279. or rails Character right
  1280. I MTflj a P or ICtrl|||A|| Word left
  1281. or Mini Word right
  1282. ||BackSpacc|| or wra)i:i ■ Delete character to left
  1283. or Delete character to right
  1284. ItTabll or KWllJll Tab
  1285. || Ins || or ICtrI|||V|| Toggle insert/overwrite
  1286. IlHomell Start of field
  1287. |[EndJ| End of field
  1288. ICtrlHITII Delete word
  1289. |Ctrl|||Y|| Clear field
  1290. When the editing field first appears, either the default text or the last text entered is already in the field. To accept this text, just press ||Enter||. To edit the entry, use the cursor keys, and to clear the entry, just type over it.
  1291. The editing field may be larger than the input window. In this case the field will scroll to the right or the left during editing.
  1292. To abort input, press I Esc II. This closes the input window and aborts the function requiring input.
  1293. Multiple Line Input Whenever the environment needs more than one line of text (for example, the Search command in the editor) or requires you to choose and ||£tril|[X]|). You can then edit the fields, just as above. Again you can press either IIEsc|| to abort the function, or IIEnterH to accept the input and continue.
  1294. from several alternatives (for example, Load file), it opens a multiple line window with several input fields. You can select these fields by using [t] and Q (or |Ctrl||E||
  1295. ma
  1296. File Selection Window Whenever the environment prompts for a file to read, (for example, in Load file) you can enter a wild filename. A wild filename is one that contains one or more of the characters *?’ or **’. The '?’ character is used to match any single character, and is used to match any sequence of characters. When a wild filename is entered, a file selection window is opened. Such a window has one of two formats, as shown in Figure 5-2. The wide format, shown at the top of the figure, contains just file names and extensions, arranged with several entries
  1297. |, = C:\NIGEL\MOD\OORE\*.* n
  1298. ASCII.DEF ASCII.MOD ASCII.OBJ CORE.TXT
  1299. OORELIB.EXE OORELIB.MOD CORELIB.OBJ DB.BAT
  1300. EXEC.RED INOUT.DEF INOUT.MOD INOUT.OBJ
  1301. REALINOU.DEF REALINOU.MOD REALINOU.OBJ STRINGS.DEF
  1302. STRINGS. MOD STRINGS2.DEF STRINGS2.M0D TERMINAL.DEF
  1303. TERMINAL. MOD TERMINAL.OBJ \. .
  1304. C:\NIGEL\MOD\CORE\*.*
  1305. ASCII.DEF 509 8-19-87 12:46pm
  1306. ASCII.MOD 78 8-02-87 4:10pn
  1307. ASCII.OBJ 444 10-27-87 1:02am
  1308. CORE.TXT 325 8-05-87 5:44pn
  1309. OORELIB.EXE 8412 10-27-87 1:12am
  1310. OORELIB.MOD 1269 10-27-87 12:05am
  1311. CORELIB.OBJ 2861 10-27-87 1:02am
  1312. DB.BAT 48 8-19-87 8:32am
  1313. EXEC.RED 165 4-14-87 l:37pn
  1314. INOUT.DEF 826 10-14-87 10:59am
  1315. INOUT.MOD 4030 10-27-87 1:02am
  1316. INOUT.OBJ 6650 10-27-87 1:03am
  1317. REALINOU.MOD 2096 10-27-87 1:03am
  1318. FIGURE 5-2 File selection window formats
  1319. on each line. The detailed format displays one file or directory entry per line, and includes various types of information about the entry.
  1320. You can toggle between the two formats. Just press the Space bar.
  1321. To select a file, move the menu bar to the required file name and then press |l Enter ||. To move the bar, you can use either cursor movement keys or press the first letter of the file required. Subdirectory entries and the parent (..) directory are preceded by *\’ and highlighted. To move into a subdirectory (or the parent) you should move to the directory using the cursor keys or *\’ and then press lEnter||. This will open a new directory window and allow you to select a file from here. You can press lEsc|| to cancel file selection.
  1322. EES-cance
  1323. FIGURE 5-3 Load File Window
  1324. The File Menu
  1325. The File menu contains commands to load and save files, to view DOS directories, to change the current directory, to execute a DOS command or Shell, and to exit from the TopSpeed Modula-2 Environment. In this section, we’ll summarize the File Menu commands.
  1326. Load File
  1327. ShortCut iF3||
  1328. Loads a file into one of the four Editor Windows and then opens that window for editing.
  1329. When Load file is selected, the Load file window (as shown in Figure 5-3) is opened.
  1330. TopSpeed M2
  1331. Files
  1332. I, 1 ~ Pick file ||
  1333. III C:M12M)OOM¥TSH.HOD III
  1334. C: ^H2^DOOHODS'TEST6. non CAM2M>B0G6.M0D CAM2MX)C\MRUT.M0D C AHZSDOOTESiriAUG .MOD — Load file —
  1335. HJ-help g}-choose fl-select i^-close
  1336. FIGURE 5-4 Pick List Window
  1337. To load a file,
  1338. 1. Use the Q and Q keys to select the Editor Window you want.
  1339. 2. Enter the name of the file to load.
  1340. If you used wildcards in your file name, a file selection window is opened (see “File Selection Window,” page 53). Simply move the cursor to the desired file and press ||Enter||. Once a file is selected it is loaded into the Editor Window and you can start editing. If the file requested does not already exist a new file is automatically created.
  1341. Pick File
  1342. ShortCut IAItllF3B
  1343. This command allows you to pick the name of a file to load from a list of recently loaded files. Such a list is shown in Figure 5-4. Up to eight file names are remembered in a Pick List. The cursor is also restored to the point where you last edited the file.
  1344. To pick a file, move the selection bar to the file required and then press I Enter ||. The file is loaded into the active editor ready for you to continue at the point you last edited the file.
  1345. The Pick List is automatically saved in the session file and will be loaded when re-entering the environment. Use ICtrl|||Y|| to delete an entry within the Pick List.
  1346. Save File
  1347. Shortcut [H
  1348. Saves the file currently being edited to disk. This command is equivalent to the Save command (|ctrl|||K|| |Q) that can be issued from the editor (see “Saving a File,” on page 61).
  1349. All Save
  1350. Saves all files being edited that have been changed since they were last saved. This command is a convenient way of ensuring all changes you have made are saved to disk.
  1351. Main Module
  1352. Sets the name of the Main Module. This name is used by Run, Make, Make All and Link (see “The Main Module,” page 69). You can clear the Main Module name by entering a blank name.
  1353. Change Dir
  1354. Changes the current DOS directory. The command prompts for a new directory and displays the current directory name ready for you to edit. If you enter a blank directory name, a selection window opens, allowing you to select a new directory by moving the cursor.
  1355. Files Dir
  1356. Displays a directory listing of files after prompting for a file mask. All files in the specified directory that match the specified mask (e.g. *. MOD) will be listed. If you don’t specify a path, then matching files from the current directory will be displayed.
  1357. There are two forms of the directory window, the detailed directory, which displays the size and last modification date of each file, and the short directory, which only displays the filename. You can toggle between the two displays by pressing the SpaceBar.
  1358. To display other directories, you can move the selection bar to the required directory and then press ||fcnter||. The new directory is then displayed.
  1359. DOS Shell
  1360. ShortCut IAltHDII
  1361. Enters a DOS shell from which you can execute DOS commands and run programs. To exit the DOS shell you must type EXIT. You will then return to the environment at the point where you left.
  1362. If you would like all edited files to be automatically saved before entry to the DOS shell (for example, if you will need to look at these files in the shell), you should have the Options Editor AutoSave option set (see “Auto Save Files,” page 75).
  1363. Execute
  1364. Allows you to enter a single line DOS command, and then immediately return to the environment. This is a convenient way of quickly executing a program without leaving the environment.
  1365. As with the DOS Shell, you can use the AutoSave option to ensure that all edited files are saved.
  1366. Note that if you often need to execute a particular DOS command or program, you may want to place the command directly in the environment menu. Then you can run the program by menu selection, or ShortCut key.
  1367. Quit
  1368. Shortcut ESE
  1369. Leaves the TopSpeed Modula-2 Environment and returns to the DOS command line prompt.
  1370. If you have set the AutoSave option, your files are saved automatically. Otherwise, the environment will ask whether you wish to save edited files before exiting.
  1371. The environment also saves details of your session in the file M2. SES. The environ­ment then uses this file to restart your work in exactly the same state the next time you call M2. The information saved includes the window layout and coloring, all op­tions set, the files loaded in each Editor Window, the Main Module, and the contents of the pick list.
  1372. You can delete the session file if you want to ‘forget’ the previous session and start anew. You can also accomplish this by starting your current session using
  1373. M2 /N
  1374. The Editor
  1375. The TopSpeed Modula-2 Editor is a multi-window editor in which you can edit up to four text files simultaneously. The editing commands are initially configured to be WordStar compatible but you can customize them easily by altering the m2 .mnu file (see “Customizing the Menu,” page 79).
  1376. The following description of commands and facilities available within the editor assumes the supplied default configuration.
  1377. The Editor Menu System
  1378. You can invoke editing functions through ShortCut key sequences or through pop-up menus. Whenever you are in one of the Editor Windows, OSl will invoke the Editor Menu.
  1379. From this menu you can invoke editor functions in the same way as in the main menu. The Editor-Menu tree is illustrated in Figure 5-5.
  1380. Pop Up Menus
  1381. If you can only remember part of a longer editor command, just enter the first part of the command. After a short delay, editor submenus will automatically pop up. For example,
  1382. Pressing
  1383. Pressing
  1384. Pressing
  1385. pops up the Block Menu pops up the Quick Menu pops up the Options Menu
  1386. If you enter the complete key sequence (e.g. ||CtrlllKll fob. the command will be executed immediately. The menu will not pop up in this case.
  1387. == Editor Menu
  1388. L - load new file
  1389. S - save file W - write to ...
  1390. Q - quick commands K - block commands 0 - editor options
  1391. —■— Quick Menu =====
  1392. F - find
  1393. A - replace
  1394. E - top of window
  1395. X - bottom of windew
  1396. R - top of file
  1397. C - bottom of file
  1398. S - start of line
  1399. D - end of line
  1400. B - beginning of block
  1401. K - end of block
  1402. P - previous position
  1403. Y - delete to end of line
  1404. L - restore line
  1405. G - goto line
  1406. Block Menu ==n
  1407. — D - save file
  1408. B - begin block K - end block H - hide block T - mark word L - mark line C - copy block V - move block Y - delete block
  1409. —■" Options Menu == V - insert node : OFF I - auto indent : OFF T - hard tabs : OFF W - tab width : 8
  1410. R - read block W - write block G - get block P - print block I - indent block Q - quit file
  1411. FIGURE 5-5 Editor Menu Tree
  1412. Loading a File
  1413. You can start editing a file one of four ways:
  1414. • Using the Load File command on the Files menu, or the ShortCut IF3||. This is described in “Load File,” page 55.
  1415. • Using the Pick File command on the Files menu, or using the ShortCut ||Alt||F3||. This is described in “Pick File,” page 56.
  1416. • Invoking the Editor command on the Main Menu, or using the ShortCut I Alt||E||.
  1417. This invokes the active Editor Window (initially 1).
  1418. • Entering one of the Shortcut keys |Alt|||l|| - |[Alt]p1|, to open Editor Windows 1-4, respectively (see “Moving Between Editor Windows,” page 62).
  1419. Whenever you invoke an ‘empty’ Editor Window (i.e. one that has not previously been loaded), you are prompted for the name of the file to edit. If you enter the name of a file that does not already exist, the file will be created.
  1420. You can load a new file into an Editor Window either by pressing |F3||. or by selecting the Load New File command, on the Editor Menu (|F9||), If you were already editing a file in the window, you will be asked whether you want to save changes to that file before the new file is loaded.
  1421. The Error Editor Window is loaded whenever you edit a file as a result of errors produced by compiling or running a program.
  1422. If the same file is loaded into two or more Editor Windows, then this file is shared between the windows. Any edits performed in one window will be reflected in all other windows sharing the same file. This powerful feature allows you to edit a file at more than one position simultaneously. The Error Editor Window is also shared with any of the other windows that contain the file being edited.
  1423. Saving a File
  1424. You can save the file being edited to disk by doing any of the following:
  1425. • pressing llF2ll
  1426. • typing the command ICtrl|||K||
  1427. • selecting the Save File command on the Editor Menu
  1428. You can also save to a file with a different name by selecting the Write To command on the Editor Menu
  1429. The environment will always ensure that you never unwittingly lose changes made to a file by either prompting on exit from the environment or, if the AutoSave option is set, by automatically saving the files (see “Auto Save Files,” page 75). You can also ensure that all changed files are saved before quitting. To specify this, select the Files Menu All Save option.
  1430. Whenever you save a file to disk a backup is created containing the previous contents of the file. If you don’t want to save such a backup version, set the Number-Of-Backups Editor Option to 0.
  1431. Maximum File Sizes The editor is a disk-paged editor and can therefore edit files with total size larger than the available RAM. Individual files being edited can be up to 500K characters long provided the total of all files loaded is less than 1MB. The swapfile used to hold temporary data is called M2. $$$. This file should not be deleted during an editing session. The swapfile will automatically be deleted on exit from the environment.
  1432. The environment will warn you if you should approach either of the two size limits. At that point, you will not be allowed to increase the file size.
  1433. Removing a File from an Editor Window
  1434. The command ||Ctrl||[K|| Hq]] will stop editing the file in the currently active Editor Window, and will close that window. If the file has unsaved edits, you will be asked whether you wish to save these changes.
  1435. Moving Between Editor Windows
  1436. You can use the ShortCut keys — lAltlhlL |Alt|||2||, |Alt||3|| and |Alt||4|| — to move to Editor Windows 1-4, respectively. In addition, you can move to the Error Editor Window, if it is active. Just press |Alt|||O||.
  1437. You also can move between Editor Windows in sequence. Press |F6|| to cycle through any open Editor Windows.
  1438. Editor Commands
  1439. The editor for the TopSpeed Modula-2 environment provides a rich variety of com­mands for editing. Each command can be invoked either by a key sequence or by a menu selection. As mentioned above, you can customize all keys and menus to your own preferences (see “Customizing the Menu,” page 79).
  1440. The initial configuration, described below, resembles WordStar commands, with some useful extensions to assist with program editing.
  1441. Insertion and Deletion Table 5-2 summarizes the keys that enable you to insert or overwrite characters and to delete characters, words, and lines.
  1442. TABLE 5.2.
  1443. Insertion and Deletion Commands
  1444. |[Del1|
  1445. || BackSpacej]
  1446. or |ctrl|||V|| Toggles insert/overwrite
  1447. or |Ctrl|||M|| Inserts line
  1448. iCtriUNl Inserts line below
  1449. or |ctrl|||l|| Inserts a number of spaces,
  1450. or a hard tab character
  1451. (see “Editor Options,” page 75)
  1452. or |Ctrl|||G]| Deletes character to right
  1453. or Deletes character to left
  1454. Deletes word to right
  1455. Deletes line
  1456. |Ctrl|||Q|| El Deletes from the cursor to end of line
  1457. |ctrl|||P|| Prefixes a |ICtrl|| character allowing it to be entered as text and displayed graphically
  1458. Cursor Movement Table 5-3 summarizes the keys that allow you to move the cursor around the file you are editing.
  1459. TABLE 5.3.
  1460. Cursor Movement Commands
  1461. |TA| or
  1462. II—>11 or
  1463. [3 or
  1464. a or
  1465. [ctrilh=ni or
  1466. IctriW or
  1467. ICtrll||W||
  1468. or
  1469. or
  1470. IIHome or
  1471. Il End || or
  1472. |lCtrl|||Home|| or
  1473. fCtdj [Ctrli H 0
  1474. ICtrll loll |s]|
  1475. |Ctrl| l0l||D||
  1476. |Ctrl|||Q|| Je|]
  1477. ICtrllllQH [X|]
  1478. ICtrlllPgUnll or
  1479. or
  1480. ICtrlljlQll |R|| ^0
  1481. ICtrllllQH fBll
  1482. |Ctrl|||Q|| FU
  1483. iMri'oK
  1484. Moves cursor left
  1485. Moves cursor right
  1486. Moves cursor up
  1487. Moves cursor down
  1488. Moves cursor to previous word
  1489. Moves cursor to next word
  1490. Scrolls up
  1491. Scrolls down
  1492. Moves one page up
  1493. Moves one page down
  1494. Moves to start of line
  1495. Moves to end of line
  1496. Moves to top of screen
  1497. Moves to bottom of screen
  1498. Moves to top of file
  1499. Moves to bottom of file
  1500. Moves to start of block
  1501. Moves to end of block
  1502. Moves to the previous cursor position
  1503. Prompts for a line number and then moves to that line
  1504. Block Commands The block commands enable you to define an area of text that you can then copy, move, delete, write to a file, indent or import from another Editor Window. When a block is defined and on display, its text is highlighted. You can change the foreground and/or background of the block text. Use ||ScrollLock|| ||Enter|| to enter the recoloring mode (see “Recoloring Windows,” page 91).
  1505. The available block commands are:
  1506. EEE |Ctrll|Kl| ictriiiKii rn ||Ctrl||K|| in |Ctrl||K|| rctr-iiKiin ICtrlllKlI llvll EEE Marks the start of the block.
  1507. Marks the end of the block.
  1508. Marks a single word.
  1509. Marks a single line.
  1510. Toggles whether the block is displayed.
  1511. Copies the block to the current cursor position. Moves the block to the current cursor position. Deletes the block.
  1512. ||Ctrl||K|| |W|| |ICtrl|JK|| ||R]| EEi Writes the contents of the block to a file.
  1513. Read the contents of a file into a block.
  1514. Gets a block from a different Editor Window, copying it to the current cursor position. This is a convenient way of importing text from other Editor Windows.
  1515. WEE
  1516. IICtrlllKII |Ij] Prints the contents of the block to the standard printer device.
  1517. Indents the text of the block. If the indent specified is positive then the block will move to the right, If negative the block moves to the left. This is a convenient way of fixing indentation in your program. Only spaces are removed when moving left.
  1518. IlCtrlJlKjl toll Quits file. This removes the file from the current active Editor Win­dow and closes the window. You can save any changes before quit­ting, if you wish.
  1519. Editor Options The Editor Options commands set modes for editing. These commands are as follows:
  1520. ILctrlJIoJI |[v]| Toggles between Insert and Overwrite modes. (Same as llns|| and |Ctrl||[V||).
  1521. Hctrl||o|| ||l|| Toggles Auto Indent on and off. If auto indent is set ON then in­serting a new line will automatically indent the new line to match the indent of the line above. Also |ITab|| moves to match the start of words in the line above.
  1522. ICtrlljQlllLT.il Toggles whether spaces or a single tab character will be inserted, whenever ||Tab|| is pressed.
  1523. ||Ctrl||O|| |1W]| Sets the width between tab stops.
  1524. In addition to the options listed above, there are also editor system options that can be found on the Editor Options menu under the Main Menu. These options allow you to set AutoSave mode, default file names and extensions, the number of backup files kept, and the top and bottom scroll zones within the editor window. The latter options are described in the sections: “Top Scroll Zone” and “Bottom Scroll Zone,” page 76. Search and Replace Search lets you search through the file for a specific string, while Replace allows you to replace occurrences of one string with another.
  1525. mH
  1526. |Ctrl||L||
  1527. Prompts for a string to find, and then searches for this string, moving the cursor to its first occurrence, if found. See below for details of the Search options.
  1528. Prompts for a string to find and for a replacement string, then searches for the string, replacing any occurrence found. See below for details of Replace options.
  1529. Repeats the last Find or Replace command, with the same strings and options.
  1530. When seeking or replacing text, you may specify one or more of the following options:
  1531. B Search or replace backwards from the cursor towards the beginning of the file
  1532. U Ignore whether the string is in upper or lower case when matching
  1533. W Only match the search string with whole words
  1534. G Replace globally throughout the file
  1535. L Replace locally within the currently marked block
  1536. R Replace globally from the cursor to the end of the file or, if the B option is set, from the cursor to the beginning of the file
  1537. N Replace without prompting for confirmation
  1538. number Searches or replaces the specified number of times
  1539. You can combine the above options. For example, the option GUN replaces globally without case sensitivity and without asking for confirmation. In a search string, the |lctrl||A|| character is wild and matches any character. To enter a wildcard character into the search string, type lCtrl]||P|| [|Ct'rl||A||.
  1540. Other Editor Commands Other commands available within the editor include uppercase word conversions and correction, marker setting and movement.
  1541. The keys to invoke these commands are as follows:
  1542. mull
  1543. Converts the word at the current cursor position to uppercase. This
  1544. is useful for Modula-2 reserved words.
  1545. [Shift |||F7|| Sets the alphabetic case of the word to be the same as the previ­ous occurrence of the word in the file. This can be used to correct Modula-2 uppercase/lowercase errors.
  1546. |Ctrl||Q|| |0] Sets location marker 1 at the current cursor position.
  1547. |Ctrl||Q|| |2|] Sets location marker 2 at the current cursor position.
  1548. |Ctrl||K|| |E] Goes to location marker 1.
  1549. |Ctrll|K|| J2|| Goes to location marker 2.
  1550. The markers can be used to mark postions in the file for editing and moving between different positions in the file.
  1551. In the Error Editor Window, which is invoked by compilation or run-time errors, you can move to the next and previous error positions as follows:
  1552. ffFSIl Move to the nearest error after the current cursor position
  1553. EzJ Move to nearest error before the current cursor position.
  1554. Compiling and Running Programs
  1555. Within the TopSpeed Modula-2 Environment you can instantly compile your program source into object files, link those objects into an executable program and then run that program. You can do all these things with simple menu selections, or by using ShortCut keys.
  1556. Compiling
  1557. To start compiling a file, do either of the following:
  1558. • Select Compile from the Main Menu
  1559. • Type the ShortCut command, ||Alt|||C||
  1560. If you are currently in an Editor Window and the file you are editing has a .MOD extension, the compiler will start compiling that file. Otherwise you will be prompted for the name of the file to be compiled. After the compiler has finished, the window in Figure 5-6 is displayed.
  1561. During compilation, the compiler window indicates the file being compiled, the cur­rent definition file and the line currently being compiled. The thermometer style in­dicator shows the proportion of the file that has already been compiled, and the disk activity indicator in the top right-hand comer, shows whenever the disk is accessed. At any stage, you can abort the compilation by pressing |lEsc||.
  1562. TopSpeed H2 Files Edit
  1563. Conpile
  1564. flake Link Run Options Info
  1565. - JPI ttodula-2 Uer 1.05 -°i
  1566. Conpiling N2L0CATE.I10D
  1567. Line 512 ■■■
  1568. Conpilation ample ted
  1569. No errors found
  1570. Press any key.
  1571. iBS-abort
  1572. FIGURE 5-6 Compiler Window
  1573. You can set various compiler options to generate debugging information, and to mod­ify the behavior of the compiler. These options are described in “Compiler Options,” page 73.
  1574. Compilation Errors As compilation proceeds the number of errors found Sited. When an error is reported, you can edit the file immediately by pressing This will start editing within the Error Editor Window — at the position of the first error. The bottom line of the window displays any errors present in the current line. To move between multiple errors, use |F8|| to move to the next, and ||F7|| to move to the previous error. Error positions will be adjusted as text is edited, allowing you to correct all the errors found. The compiler will keep up to about 50 error messages, aborting compilation after this limit, but ready for you to start editing. (The exact number of errors the compiler can keep track of depends on the length of the individual error messages.) See “The Editor,” page 59, for details on editing the Error Editor Window file.
  1575. After you have made corrections to the error file, you can continue compilation by either pressing lEsc|| or lAlt|[Cl|. Compilation will restart immediately.
  1576. To abort compilation immediately after the first error is found, set the Options Compiler Stop-on-1st-Error option (see “Stop On First Error,” page 73).
  1577. TopSpeed M2 Files Edit Conpile
  1578. flake
  1579. Link Run Options Info
  1580. - JPI Modula-2 Uer 1.0S -
  1581. Making TSRCALC
  1582. TSRCALC Mo errors found
  1583. TSR Mo errors found
  1584. Make conpleted
  1585. Linking TSRCALC Link conpleted Press any key,
  1586. jSSzabort
  1587. FIGURE 5-7 Make Window
  1588. The Main Module
  1589. The functions Make, Run and Link each need the name of the Main Module. You are prompted for this at the start of each command. The last Main Module name entered is the default choice presented in the prompt window.
  1590. Making a Program
  1591. ShortCut |Alt||M||
  1592. TopSpeed Modula-2 has an automatic Make facility within the compiler. This calcu­lates dependencies and automatically recompiles all out-of-date modules within your program. Then, if all compilations were successful, an executable (. EXE) file is cre­ated by linking the program objects together.
  1593. For example, if you change a particular definition file, then Make will automatically ensure that all modules importing the changed definition will be recompiled to make a consistent program.
  1594. To invoke the Make command, select Make from the Main Menu or press the ShortCut key, | A It |l MIL After you enter the Main Module name, the Make window in Figure 5-7 will be displayed and the Make process will commence.
  1595. The Make window shows all files being compiled. Then, if all files compile with no errors, the window shows the link taking place. If errors are found then the Make is aborted and you can immediately correct the errors by pressing I Enter II When you have finished your corrections, press either ||Esc|| or ||Alt|||Nl|| to restart the Make process. You can abort the Make at any time by pressinglTEscll.
  1596. Once the Make has completed with no errors, you can run the completed program — now in an . EXE file — either inside or outside the environment.
  1597. To compile all component modules of a program, you can also use the Options Menu Make All command. This will recompile all files needed by a program regardless of whether they seem to need recompilation. See “Make All,” page 77.
  1598. Running Programs
  1599. (*$R+*) Subrange Value Out Of Range
  1600. Checks for out-of-range assignment.
  1601. (* $R+ *) Enumeration Value Out Of Range
  1602. Checks for out-of-range enumeration values.
  1603. (* $ Z+*) Dereference Of NIL Pointer
  1604. Checks for the dereferencing of pointers containing the value NIL — that is, uninitialized pointers.
  1605. If any of the above errors occur when running under the environment, you are prompted to specify which of the following you wish to do:
  1606. • Continue the program
  1607. • Abort, returning to the environment
  1608. • Find the position of the error in the source program
  1609. If you select Find, then the Error Editor Window will be loaded with the source file containing the error and the cursor will be positioned at the location of the first error.
  1610. If you are running the program outside the environment, then a run-time error will cause an error message in the form of:
  1611. Run Time Error [AAAA/SSSS:OOOO] Error Type. Continue (y/n).
  1612. Where Error Type is one of the run-time errors listed above, AAAA is the absolute segment of the error, SSSS is the relative segment (which can be seen in the link map), and OOOO is the offset of the error. To find the run-time error within the source, the Options Run Find Error command can be used. This prompts for the Main Module name and for the error address (SSSS: OOOO), then finds and displays the error within the source (see “Find Error,” page 75).
  1613. Linking a Program
  1614. Shortcut ran
  1615. The TopSpeed Modula-2 Linker is an extremely fast, ‘smart’ linker. This means that only code actually used by the program is included in the link, and the linker needs no other information than the Main Module name to link a program.
  1616. You’ve already learned how the linker is invoked as part of the Make and Run sequences. You can also invoke the linker separately. To run the linker you should select the Link main menu option. This will prompt for the Main Module and start linking. The component object files are linked together to produce an executable (. EXE) file, as well as a map (. MAP) file — if the Options Link Map-File option is set to ON. The other options that govern the actions of the linker are described in “Linker Options,” page 74.
  1617. Linker Errors If there are any errors detected while linking your program, they will be reported at the end of the link within a scrollable error window. To exit the error window, press I Esc II Error messages are also output within the map. If any errors are detected, then no . EXE file is produced. Some non-fatal errors can be suppressed by the Options Linker Suppress-Warnings option. Possible linker errors include the following:
  1618. Error message output
  1619. Date/time error Probable cause
  1620. This implies that you have date/time inconsisten­cies between modules within your program. You can use Make, or Make All to remove these in­consistencies (see “Making a Program,” page 69).
  1621. Non-main module This message is output if you attempt to link an implementation module in place of a main module.
  1622. Bad object file This can occur if you have a corrupt or invalid object file.
  1623. Unexpected segment def This can occur if you have a corrupt or invalid object file.
  1624. Unexpected group def This can occur if you have a corrupt or invalid object file.
  1625. Not enough memory This means the environment hasn’t enough space to link your program. Try using the batch linker instead (see “The Batch Compiler and Linker,” page 78).
  1626. Group/Segment exceeds 64K This can occur if you have used the $M or $D com­piler directives and have created segments larger than 64K.
  1627. Definition duplicated
  1628. Fixup overflow
  1629. Symbol is Unresolved Multiple definition of symbol.
  1630. Incorrect fixup.
  1631. Unresolved symbol definition.
  1632. The last three errors will not happen within normal Modula-2 programs but may occur when linking to other languages or assembler objects.
  1633. The Options Menu
  1634. ShortCut |Alt|jo||
  1635. The TopSpeed Modula-2 system is designed to be extremely flexible. It was designed to enable you to adapt it to your own particular needs and preferences wherever possible. Toward this aim, each of the major components has a set of options you can change. These options are saved in the session file and the configuration file, allowing you to set options that will be remembered after leaving the environment.
  1636. You can invoke the Options Menu from the Main Menu or by using the |Alt|||O|| ShortCut command. The Options menu contains five submenus: Compiler, Linker, Run, Editor and Setup. The menu also contains the Make All command.
  1637. Compiler Options
  1638. This section summarizes the options for the compiler described in “Compiling” on page 67.
  1639. B - Defaults for Run-Time Checks This option lets you specify whether compiler directives that do checking at run-time are ON or OFF. This setting affects $1, $0, $R, $S, and $Z. This option affects only the default settings. You can still use directives within your source text to override the default.
  1640. D - Generate Debug Information If ON, the compiler generates a debug information file for the module being compiled. This file is required by the TopSpeed Modula-2 source level debugger, which will be available separately.
  1641. E - Stop On First Error If ON, this causes compilation to stop after the first error is found. You can correct the error immediately, and restart compilation. If the option is OFF, then about 50 errors will be stored, ready for correction.
  1642. F - Filename Check This option is normally ON and causes the compiler to check for module names that do not match the source file name. If OFF, the compiler does not report file and module name inconsistencies.
  1643. J - Suppress Libraries If ON, the compiler suppresses the automatic cre­ation of libraries (smart linking). You may need to use this option when linking Top­Speed Modula-2 OB J-files using linkers other than the TopSpeed Modula-2 linker.
  1644. N - Line Numbers If ON, the compiler will generate line numbers in the .MAP file. You can use these line numbers to locate the line being executed while debugging a program. The line information also can be used by source level debuggers.
  1645. V - Volatile Variables If ON, the compiler will keep all variables in mem­ory. If OFF, machine registers are used wherever possible — because they can be ac­cessed more quickly than memory. This option is useful when debugging a program, as variables can be examined in memory. Otherwise, the option is generally OFF.
  1646. Linker Options
  1647. The following options govern the operation of the linker described in “Linking a Program,” page 71.
  1648. M - Map File If ON, the linker generates a text Map File that contains segment information, the location of procedures and global variables, line number information, run-time error check locations and any linker errors messages generated. The map file has the same name as the main module, but has extension .MAP. If the option is OFF, then no map file is generated.
  1649. The map file generated is compatible with Microsoft map formats and can be used with source level debuggers such as Microsoft Symdeb.
  1650. I - Initialize Segments If ON, then the linker will generate zero filled segments for data not initialized in the program. This is not required for Modula-2 programs as data are not assumed to be initialized. The option is generally OFF, resulting in smaller . EXE files.
  1651. S - Detailed Segment Map If this option is ON, then a complete segment map is generated for every component segment included in the link. This provides extra debugging information, but is generally OFF as a great deal of information can be generated.
  1652. C - Case Sensitive Link If this is ON the linker differentiates identifiers that differ in case. Since Modula-2 is case sensitive, you will need to have this option ON. However, you can turn the option OFF when linking to case insensitive languages or to assembly code.
  1653. W - Suppress Warnings If this is turned ON, the linker suppresses non-fatal error messages. See “Linker Errors,” page 72, for details of the linker error messages.
  1654. T - Trace References If ON, the linker traces the first reference to each module. The linker reports the date/time record for each module linked. This can be useful when analyzing module version conflicts.
  1655. Run Options
  1656. The run options modify the operation of the Run command, described in “Running Programs,” page 70. These options are described in this section.
  1657. C - Command Line Allows you to enter a DOS command line that is passed to the program when it is executed from within the environment. You’ll be prompted for the command line.
  1658. A - Auto Make If this option is ON, then an automatic Make will be performed before any program is run. This is to ensure that the program uses the most recent versions of all the modules.
  1659. T - Timed Run If this option is ON then the execution time of your pro­gram is displayed when the program completes. The format of the time displayed is H:M:S:HS indicating Hours, Minutes, Seconds and 1/lOOths of seconds. The value excludes the time taken to load the program from disk. (The actual precision with which these measurements can be taken depends on your particular DOS implemen­tation. Normally, the precision is about 0.06 seconds, since the clock is checked about 18.2 times per second.)
  1660. F - Find Error This prompts for a program name and a run-time error address. The system then finds and displays the error within the source. This option can be used to find errors when they are reported outside the environment. Such errors have the following format:
  1661. Run Time Error [AAAA/SSSS:OOOO]. Continue (y/n).
  1662. where SSSS :OOOO is the error address.
  1663. You don’t need this command when running a program from within the environment, since the error is located automatically in that case. Note that a map File is required to find the run-time error.
  1664. Editor Options
  1665. The editor options modify the operation of the environment editor which is described in “The Editor,” page 59.
  1666. A - Auto Save Files When ON, this option causes the editor to save all changed files automatically whenever you run a program, enter a DOS shell, or exit the environment. This ensures that no edits will be lost, even if a program should crash. This option also enables programs run under the environment to read the latest version of files being edited. If the option is OFF, the environment will ask whether to save edited files when exiting, but will not automatically save files when running programs.
  1667. F - Default Filenames This option lets you set the default file names supplied when you enter an Editor Window for the first time. The default filenames are initially set to * . MOD, but may be changed to be different for each Editor Window, depending on your use of that window. For example, you may want to set the default file names of windows 2 and 4 to *. DEF so you can quickly select a definition file for editing within those windows.
  1668. E - Default Extensions This allows you to specify the default extensions that are added to file names entered without an extension. Again, you can have different extensions for each Editor Window, if you wish. The default extensions are all initially set to . MOD.
  1669. N - Number Of Backups This lets you specify the number of backup files that are retained by the editor whenever a file is saved. This value must be between 0 and 9, inclusive. 0 means that no backup file is created. 2 means that the two most recent previous versions of your file are kept. The first, most recent, backup file has the extension .BAK, the second .BK2, the third .BK3 and so on. This option is initially set to 1.
  1670. T - Top Scroll Zone This sets the number of lines from the top at which the Editor Window begins to scroll when moving up. For example, if this is set to 2, then the screen will scroll if you move the cursor to the second line from the top. The initial default value is 0. Increasing it above this value allows you to ensure that there are always lines visible above the cursor.
  1671. B - Bottom Scroll Zone This sets the number of lines from the bottom at which the Editor Window begins to scroll when moving down. The initial default value is 1. Increasing it above this value allows you to ensure that there are always lines visible below the cursor.
  1672. Setup Options
  1673. The Setup Options allow you to specify various aspects of the environment. You can also save and restore configuration files, and you can load a new redirection file if you wish.
  1674. C - CGA Snow Check This should be set to ON if your CGA monitor “snows” when displaying windows in the environment. However, be warned that the display of windows is considerably slower when this option is on. The default setting is OFF.
  1675. B - BIOS Scrolling If ON, this option sets a mode in which the scrolling of Editor Windows is performed by calling the IBM BIOS. This mode can result in quicker scrolling when the CGA snow check is ON but can also cause the screen to flicker when scrolling. The mode is thus usually set OFF.
  1676. H - High Background This specifies whether the high background colors available with the IBM CGA should be enabled. See “Recoloring Windows,” page 91, for details.
  1677. X - Solid Cursor If this option is ON, then the cursor will be a solid flashing block; if OFF, the cursor is the normal flashing underline.
  1678. R - Load Redirection File This loads a new redirection file replacing all previous redirections. See “The Redirection File,” on this page.
  1679. L - Load Options/Windows This loads a . CFG file that has previously been saved using Save options/windows. The command loads each window’s color, position and size, and all Option values.
  1680. S - Save Options/Windows This saves the options and window setup to a . CFG file. You can load this file using the Load options/windows command described above. With this option, you can quickly swap between different configurations of the environment.
  1681. Make All
  1682. Make All performs a make in exactly the same way as Make described in “Making a Program,” page 69, except that all component modules whose source can be found are recompiled, not just the out-of-date ones. This command can be useful in resolving date/time linker errors.
  1683. The Information Window
  1684. ShortCut I Alt||I||
  1685. The Information Window contains useful information about the current state of the environment. The window contains the following information:
  1686. • Date and time
  1687. • Current logged drive and directory
  1688. • File names and current size of files being edited
  1689. • Available memory within the environment
  1690. • Disk free space
  1691. The Redirection File
  1692. Within the TopSpeed Modula-2 environment you can define a search path by which files are located in the DOS file system. This allows you to put different kinds of files in different subdirectories. The file that defines these search paths is a simple text file, M2 . RED. This file contains one or more lines with the format:
  1693. MatchName = DirectoryPath { ; DirectoryPath }
  1694. MatchName is a file name specification that can contain wild (**’ and '?’) characters, and DirectoryPath is the location for those files that match the MatchName. You can specify multiple Directory Paths by separating them with a semicolon
  1695. If there is more than one Directory Path specified, each path will be searched in sequence until the file is found.
  1696. This is best demonstrated by an example. Suppose the file M2. RED contains the following text:
  1697. *.DEF * . OBJ M2. ERR M2.$$$ M2.0VL M2.MNU
  1698. . ; \M2\LIB ; \NIGEL\MOD
  1699. \M2\0BJ \M2\EXE \M2\EXE \M2\EXE \M2\EXE
  1700. Whenever a file name that matches * . DEF is specified, the environment first tries to search the directory (current directory). Then, if the file is not found, \M2\LIB is searched, and then finally \NIGEL\MOD. Similarly, all files that match * .OBJ will be sought in the directory \M2\0BJ.
  1701. Whenever a new file is created, it is always created in the first directory that matches the file name. This means that in the above example all .DEF files will be created in the current directory and all . OBJ files will created in \M2 \OBJ.
  1702. Note that whenever you input a full path name (i.e. a complete directory path) to the environment, redirection does not occur. This allows you to override redirection if required.
  1703. The redirection file is always searched from the top until the file is found. This allows you to specify individual file redirection as well as general default cases. For example
  1704. TESTDB.MOD = \M2\TESTING
  1705. READDB.MOD = \M2\TESTING
  1706. • .MOD = . ; \M2\W0RK
  1707. tells the system to search certain directories for general files with a . MOD extension, but to search in different directories for two specific files with this extension. The current directory should always be specified as since Null entries are ignored.
  1708. A word of warning about using file redirection (M2 .RED): It can be rather confusing if there are several versions of a file in the search path. If you seem to be having a problem, check each directory to make sure that the files present are those you expect.
  1709. The Batch Compiler and Linker
  1710. You can invoke the TopSpeed Modula-2 Compiler and Linker from the DOS com­mand line, or from a . BAT command file.
  1711. The command format to run the batch compiler is:
  1712. M2/C filename /options
  1713. The command format to run the batch linker is:
  1714. M2/L filename /options
  1715. For example, to compile the program wptest enter the command:
  1716. M2/C wptest
  1717. at the DOS prompt. To link the program enter the command:
  1718. M2/L wptest /M
  1719. The batch compiler options are described in Chapter 7.
  1720. The batch linker options are:
  1721. /M Generate map file
  1722. /I Initialize all segments
  1723. /S Detailed map of segments
  1724. /N No default libraries
  1725. /T Trace first reference to module
  1726. /W Suppress warning messages
  1727. /C Lower case significant in symbols
  1728. See “Linker Options,” page 74, for a more complete description.
  1729. Customizing the Menu
  1730. The Menu Definition File (M2. MNU) contains text that defines the structure of the TopSpeed Modula-2 Environment Menu System, and of the ShortCut and Editing keys.
  1731. The Menu Definition File is a simple text file that is read whenever the environment is entered. The exact format of the file is described later in “Menu Definition File Format,” page 83. To get an idea of the layout for the definition, you should examine the default M2. MNU supplied.
  1732. You are encouraged to experiment by changing the Menu Definition File to discover the setup that best suits you. However, before you edit M2 . MNU, you should save a copy of the file, in case you later want to go back to the default definitions supplied with the TopSpeed Modula-2 system.
  1733. The following sections describe changes you can make within the Menu Definition File.
  1734. Changing the Main Menu Type
  1735. You can use three types of menus: pop-up, pull-down, and bar. The type of the main menu is defined by the line
  1736. ! PopUp [ TopSpeed M2 ] | <F10>
  1737. which defines a vertical “Pop-Up” style menu. If you wish to have a horizontal “Pull-Down” menu, you should change PopUp to PullDown. If you want a “Bar” style menu (i.e. a Pull-Down menu with no frame), you should change PopUp to LinePull.
  1738. If you wish to change the title displayed at the top of the menu, you can edit the “TopSpeed M2” between the square brackets (‘[’ and *]’). For example, you may want to change it to
  1739. !PullDown [ My TopSpeed M2, Hands Off! ] | <F10>
  1740. You can also change the key that invokes the main menu by changing the <F10> after the ‘ . For example, if you need |Shift|||F10|| to invoke the main menu you
  1741. might have the line
  1742. !PullDown [ My TopSpeed M2, Hands Off! ] | <ShiftF10>
  1743. For information on changing other ShortCut keys, see “Changing ShortCut Keys,” page 81.
  1744. Changing Menu Text
  1745. In the Menu Definition File, you can change the text displayed in the menu by editing the appropriate line. For example, if you want to change Files to read PcDos on the Main Menu you can change the line:
  1746. {FJiles | <AltF>
  1747. to
  1748. (P)cDos | <AltF>
  1749. Note that the character enclosed in the braces (*{’ and *}’) defines the command character that invokes the menu line. This command character may be in the middle of the word — for example, Pc{D}os — or left out all together if not required.
  1750. The number of leading spaces before the menu text defines the Level of the menu within the menu tree. Don’t change this unless the menu tree is to be changed, as described in the next section.
  1751. Changing the Menu Tree
  1752. In addition to changing the text of the menu, you can also change the actual structure of the menu tree. This means you can reorder menus, create new submenus or even delete unwanted commands.
  1753. To illustrate how to change the menu tree, suppose you wish to group the “Compi­lation Functions” together in a single menu. To do this, the lines containing:
  1754. {EJdit
  1755. {CJompile
  1756. {M}ake
  1757. {L)ink
  1758. {R)un
  1759. {OJptions
  1760. could be changed to: | Editor
  1761. | Compiler
  1762. | Make
  1763. | Linker
  1764. | Run program
  1765. 1 <AltE> <AltC> <AltM> <AltL> <AltR> <AltO>
  1766. {E}dit
  1767. {CJompilation | Editor <AltE>
  1768. {CJompile | Compiler <AltC>
  1769. {MJake Make {A}11 | Make
  1770. | Make All <AltM>
  1771. {L}ink | Linker <AltL>
  1772. (R}un {0}ptions I Run program 1 <AltR>
  1773. <AltO>
  1774. This creates a new submenu under the command Compilation. The indentation of the menu text (i.e. number of leading spaces) determines the start and end of each menu. In the above example, this means that the the extra spaces added in front of Compile cause a new submenu to be started. This submenu continues until Options where the indentation returns to its previous level. Look at the Options Menu for further examples of “nested” submenus. Notice that one of the options under Compilation — Make All — uses a letter other than the first letter of the option to invoke it.
  1775. Changing ShortCut Keys
  1776. At the end of a Menu Definition Line, there also may be a ShortCut key sequence defined. This sequence activates that function or submenu. You may change or add to these key definitions to change the ShortCut keys. For example, to assign the key [0| to the Options Run Command-Line function, you would change the line:
  1777. {C} - Command line | Command Line
  1778. to
  1779. {C} - Command line
  1780. | Command Line <F4>
  1781. You can specify multiple keys after the line, if you need more than one key to activate the same function. See “Key Sequences,” on page 89, for a complete description of ShortCut key specification.
  1782. You can also define keys independently of the menus. An example of this is the Review Screen function, which is defined as follows:
  1783. (Key | Review Screen <AltF5>
  1784. You can change, add to, or delete these key definitions in the same way as changing the Menu Definition lines.
  1785. External DOS Commands
  1786. As you may have already noticed, there is an Action Name after the * | ’ and before the ShortCut keys in Menu and Key Definition lines. This name defines the action that is performed when the menu line is selected, or the ShortCut key is pressed.
  1787. In addition to the pre-defined environment actions (which are listed in the sections “Global Actions,” page 87, and “Editor Actions,” page 88) you can also install a LMDS Command String which will be executed under a DOS shell whenever the Menu Line is selected. In this way, you can attach your own programs to the environment menus and keys. For example, if you required the DOS command
  1788. locate *.mod
  1789. as a menu function, then you might add the line
  1790. {LJocate | 'locate *.mod' <AltF3>
  1791. to the menu definition. The DOS command required should be enclosed by single or double quote characters, and may prompt for parameters by placing ‘%M’ or *%P’ within the command string. See “External Command Parameters,” page 89, for more details.
  1792. The Editor Keys and Menus
  1793. The Environment Editor has its own specific keys and menus. These are separated from the rest of the Menu Definition by the line
  1794. !Editor
  1795. Everything after this line is only valid when within the Editor. If you want to add or change Editor keys or menus, the you should edit the lines after ! Editor.
  1796. Changing Help Lines
  1797. You can change two of the Help Lines within the environment. The first is the Main Menu Help Line, which is defined before the lEditor line, and the second is the Editor Help Line, which is defined after. See “Help Lines,” page 84, for the format of the Help Lines.
  1798. Menu Definition File Format
  1799. The Menu Definition file contains lines of text that may be either Menu Directives or Menu Text. Blank lines are not significant, and can therefore be used for clarity. Menu Directives inform the menu system of Menu Types, Menu Titles, Help Line Text and ShortCut Keys. The Menu Text defines the structure of the menu tree and the associated functions.
  1800. Menu Directives
  1801. Menu Directives always begin with an T. Following the T is the directive name, together with any parameters required. Directives can be global to the entire envi­ronment, or they can be restricted to the editor.
  1802. The directives, together with some examples, are as follows
  1803. Menu Type You can have three forms of Menu Type directives
  1804. !PopUp [ MenuTitle ] | KeySequences or
  1805. !PullDown [ MenuTitle ] | KeySequences
  1806. or
  1807. !LinePull | KeySequences
  1808. Such a directive defines the type and title of a top level menu and any ShortCut keys that should invoke the menu. The menu title and shortcut keys are optional.
  1809. The type of the top menu can be one of the following
  1810. • Pop Up (default), which has vertical menu selections
  1811. • Pull Down, which has horizontal menu selections
  1812. • Line Pull, which is a Pull Down menu with no frame or title
  1813. The menu title is text — enclosed by square brackets ( [ and ] ) — and will appear in the top center of the frame enclosing the menu.
  1814. You can define one or more KeySequences to invoke the menu. The KeySequence format is described in “Key Sequences,” page 89.
  1815. Example:
  1816. IPullDown [ TopSpeed M2 } | <F10>
  1817. specifies that the menu named “TopSpeed M2” is to be a pull down menu, and is to be activated by pressing 1F1OIL
  1818. Editor Section
  1819. !Editor
  1820. Generally, your directives will apply to the entire environment. Sometimes, however, you may have a directives that should apply only to the editor. For example, you might want to use a different Help Line for the editor.
  1821. To make this possible, the menu definition is split into two distinct sections. The first section contains general menus and keys, available from anywhere within the envi­ronment. The second section contains editor menus and keys that are only available while editing. To split the two sections, the directive ! Editor must be included in the menu definition. Everything above this directive is global to the environment, and everything below is local to the editor.
  1822. Help Lines
  1823. !Helpline [ help line text ]
  1824. You can define two different user Help Lines. The first is the Help Line displayed when any menu is active. This definition should be located anywhere before the ! Editor directive. The second Help Line is displayed while editing. This must be located after the ! Editor directive.
  1825. Example:
  1826. !HelpLine [ {F10}-main menu {Esc}-close {Alt-X}-exit ]
  1827. Within the Help Line text, { and } can be used to indicate highlighted text, and the escape sequence “nnn can be used to specify the character with ascii value nnn. For example, "26 is the right arrow character.
  1828. Thus, the directive in the example specifies that FIO, Esc and Alt-X should be highlighted and that these should be associated with the commands “main menu,” “close” and “exit,” respectively.
  1829. ShortCut Key Definition
  1830. !Key | Action KeySequences
  1831. You can use the ! Key directive to define ShortCut keys that invoke commands not found on any menu. This directive assigns the specified action to one or more key sequences. The format of actions (which can be a DOS command) is described in the section: “External Commands,” page 88, and the format of key sequences is described in “Key Sequences,” page 89.
  1832. Whenever a sequence of keys is pressed, the appropriate action will be invoked. Keys defined before the ’Editor directive will be active anywhere within the environment, and keys defined after will be active only while editing. An example of an Editor Key is the Case Correct Key (see “Other Editor Commands,” page 66), which is defined as follows:
  1833. !Key | Ed Case Correct <ShiftF7>
  1834. Submenu Title
  1835. ![ submenu title text ]
  1836. This directive allows you to specify the title text displayed in the frame of submenus. The directive should appear immediately before the indented Menu Text for the submenu. Note that the directive must be indented the same number of spaces as the submenu.
  1837. Example:
  1838. {Q} - quick commands | <CtrlQ>
  1839. ![ Quick Menu ] {F} - find | EdFind CCtrlQ F>
  1840. {G} - goto line j EdGotoLine <CtrlQ G>
  1841. This directive specifies that the submenu invoked by pressing
  1842. should be
  1843. called “Quick Menu.”
  1844. Comment
  1845. !! <comment text>
  1846. A line beginning with *!! ’ serves as a comment on other material. The line is ignored by the environment, but will be useful to you or someone else trying to get an overview of the file’s contents. You can include comment lines anywhere in the file.
  1847. Example:
  1848. !! TopSpeed Default Modula-2 Menu Definition
  1849. Menu Line Definition
  1850. A menu line defines the menu level, the menu text, the command character, and the function to be invoked, as well as any ShortCut keys.
  1851. The format of a menu line definition is:
  1852. MenuText | Action KeySequences
  1853. The menu text specifies what will appear on the screen when the menu is invoked. The level of the menu is determined by the number of leading spaces before the menu text.
  1854. When a new submenu definition begins, its text is indented further to the right. When the submenu definition ends, the text is indented to the left to the same indentation as the parent menu.
  1855. Example:
  1856. {OJptions
  1857. | <AltO>
  1858. I
  1859. | CompOptF <AltO F>
  1860. | CompOptE
  1861. j CompOptN
  1862. I
  1863. | CommandLine <AltO C>
  1864. I RunOptA
  1865. | RunOptT
  1866. (C}ompiler
  1867. {F} - Optimize
  1868. {E) - Stop on 1st error
  1869. {N} - Line numbers
  1870. {R}un
  1871. {C} - Command line
  1872. {A} - Auto make :
  1873. {1} - Timed run :
  1874. This declares a menu invoked by selecting Options (or pressing |Alt][[O||), and two submenus that are invoked by selecting Compiler and Run, respectively.
  1875. The Action is the name of the function to be invoked and is described in the following section, “Menu Actions”.
  1876. Note that menu lines that invoke submenus (Options, Compiler and Run, in the above example) should not have an Action defined. They can have associated ShortCut keys, however.
  1877. Within the menu text, you can define a single command character (which invokes that menu line) by enclosing that character within braces — for example, {E}. A command character defined in this way should be unique for that particular menu.
  1878. Trailing and leading spaces are ignored within the menu text (except that leading spaces serve to define the menu level, as described above). If you need actual spaces at the beginning or end of the text, you should use the underscore (_) character. This will be translated into actual spaces in the displayed menu text.
  1879. A number of the pre-defined actions require 3 underscores (i.e. ) to represent
  1880. spaces at the end of the menu text. This space is used to display an option state (e.g. ON/OFF). The actions that require this space are listed below.
  1881. Menu Actions
  1882. The menu actions are invoked either by a key or by menu selection. There are two different kinds of actions, Pre-Defined Actions and External Actions. Pre-Defined Actions invoke an environment command, while External Actions run an external program under DOS.
  1883. Pre-Defined Actions These actions are specified by name. The first eight non-space characters in the name are significant. The following lists specify the pre-defined actions, together with the page number of the section that describes their function. The first list shows the global actions and the second list shows the actions accessible in the editor.
  1884. Global Actions The Global Actions, which may be invoked throughout the environment, are as follows:
  1885. Load File (55)
  1886. Pick File (56)
  1887. Save File (57)
  1888. Save All Files (57)
  1889. Main Module (57)
  1890. Change Dir (57)
  1891. Directory (57)
  1892. DOS Shell (58)
  1893. Execute (58)
  1894. Quit (58)
  1895. Editor (59)
  1896. Compiler (67)
  1897. Make (69)
  1898. Linker (71)
  1899. Comp Opt B * (73)
  1900. Comp Opt E * (73)
  1901. Comp Opt F * (73)
  1902. Comp Opt N * (73)
  1903. Comp Opt D * (73)
  1904. Comp Opt V * (74)
  1905. Comp Opt J * (73)
  1906. Link Opt I * (74)
  1907. Link Opt S * (74)
  1908. Link Opt M * (74)
  1909. Link Opt T * (74)
  1910. Link Opt C * (74)
  1911. Link Opt W * (74)
  1912. Command Line (75)
  1913. Run Opt A * (75)
  1914. Run Opt T * (75)
  1915. Auto Save Files * (75)
  1916. Default Filenames (75)
  1917. Default Extensions (76)
  1918. No Of Backups * (76)
  1919. Top Scroll Zone * (76)
  1920. Bottom Scroll Zone * (76)
  1921. Env Opt B * (76)
  1922. Env Opt S * (77)
  1923. Env Opt H * (76)
  1924. Env Opt C * (76)
  1925. Load Red File (77)
  1926. Load Config File (77)
  1927. Save Config File (77)
  1928. Make All (77)
  1929. Info (77)
  1930. Editl (62)
  1931. Edit2 (62)
  1932. Edit3 (62)
  1933. Edit 4 (62)
  1934. EditO (62)
  1935. Zoom Window (52)
  1936. Cycle Windows (62)
  1937. Review Screen (50)
  1938. Run Program (51)
  1939. Editor Actions The Editor Actions, which may be invoked throughout the editor but not elsewhere, are as follows:
  1940. Ed Load File (60) Ed Opt Indent * (65)
  1941. Ed Write File (61) Ed Opt Hard Tabs * (65)
  1942. Ed Find (66) Ed Opt Tab Width * (65)
  1943. Ed Replace (66) Ed Word Left (63)
  1944. Ed Start Screen (63) Ed Page Down (63)
  1945. Ed End Screen (63) Ed Move Right (63)
  1946. Ed Start File (63) Ed Move Up (63)
  1947. Ed End File (63) Ed Word Right (63)
  1948. Ed Start Line (63) Ed Del Forward (63)
  1949. Ed End Line (63) Ed Del Backward (63)
  1950. Ed Goto Begin Block (63) Ed Tab (63)
  1951. Ed Goto End Block (63) Ed Find Again (66)
  1952. Ed Prev Position (63) Ed Ins Line (63)
  1953. Ed Del End Line (63) Ed Ins Below (63)
  1954. Ed Restore Line (63) Ed Prefix (63)
  1955. Ed Goto Line (63) Ed Page Up (63)
  1956. Ed Begin Block (64) Ed Move Left (63)
  1957. Ed End Block (64) Ed Del Word (63)
  1958. Ed Hide Block (64) Ed Upper Case (66)
  1959. Ed Mark Word (64) Ed Scrl Down (63)
  1960. Ed Mark Line (64) Ed Move Down (63)
  1961. Ed Copy Block (64) Ed Del Line (63)
  1962. Ed Move Block (64) Ed Scrl Up (63)
  1963. Ed Del Block (64) Ed Next Error (66)
  1964. Ed Read Block (64) Ed Prev Error (66)
  1965. Ed Write Block (64) Ed Case Correct (66)
  1966. Ed Get Block (64) Ed Goto Ml (66)
  1967. Ed Print Block (64) Ed Goto M2 (66)
  1968. Ed Indent Block (64) Ed Set Ml (66)
  1969. Ed Insert * (65) Ed Set M2 (66)
  1970. Ed Quit (66)
  1971. Editor Actions can only be used as the action within the Editor section of the menu definition, while Global Actions can be used in either section.
  1972. The functions marked with an **’ require space for a three character field left at the end of the menu text, as described in “Menu Line Definition,” page 86.
  1973. External Commands Within the environment menu system it’s possible to attach an external DOS command or program to any key or menu entry. This can be done by enclosing the command line in either single or double quotes and using it as an Action in the Menu or Key definition described above.
  1974. For example, suppose you have the following menu lines defined:
  1975. {B)ackup Files | 'copy *.mod a:' !Key | "find 'Version' *.MOD" <AltZ>
  1976. If you select the Backup Files menu entry, then the DOS command line
  1977. copy *.mod a:
  1978. is executed. Similarly, when you press lfAJt]([Z]| the command line
  1979. find 'Version' *.MOD
  1980. is executed.
  1981. External Command Parameters Suppose you need to pass the Main Module name to the command you want to execute. You can do this, by including %M in the command at the spot in which you want the name.
  1982. If this name has been specified, the system will use the name. If no name has been specified, you’ll be prompted for a name. Similarly %P (prompt string) in the command string will prompt for a parameter, while displaying the prompt string. The %P will then be expanded to the entered string.
  1983. For example, suppose you define:
  1984. {E}xase | 'del %P (File to delete: )'
  1985. (D)ebug | 'debug %M.EXE'
  1986. Selecting Erase prompts for
  1987. File to delete:
  1988. After you type a file name (let’s say, FTODEL) and press |Enter|, the command line del £todel
  1989. is executed. Similarly selecting Debug will prompt for the Main Module name and will then execute the command
  1990. debug mainfile.exe
  1991. You can include as many *%P’s as you need in the command string.
  1992. Key Sequences
  1993. The ! Key directives and menu entries can have one or more KeySequences attached. These key sequences consist of key names enclosed by the characters *<’ and *>’. Examples of key sequences include:
  1994. <AltA> Alt A
  1995. <CtrlZ> Control Z
  1996. <CtrlQ D>
  1997. <CtrlK M 1> Control Q followed by D
  1998. Control K followed by M then 1
  1999. <ShiftF2> F2 Shifted
  2000. <Home End> Home followed by End
  2001. The following keys are valid and represent the names to use:
  2002. Fl - FIO ShiftFl - ShiftFlO CtrlFl - CtrlFlO AltFl - AltFlO
  2003. AltO - Alt9 AltA - AltZ
  2004. UpArr CtrlUpArr DownArr CtrlDownArr LeftArr CtrlLeftArr RightArr Ct rIRightArr
  2005. PageDown CtrlPageDown PageUp CtrlPageUp Home CtrlHome End CtrlEnd
  2006. Del Ins AltEqual ShiftTab
  2007. If ambiguous key sequences are defined in the menu definition (for example, <CtrlK> and <CtrlK B> and <CtrlK K>), then the menu system will wait a short interval after the initial sequence has been typed. If the remainder of a longer sequence is typed, within this time then the long sequence will be executed. Otherwise, the shorter sequence will be assumed. This can be used to create automatic “pop-up” menus in the menu definition.
  2008. To remove the automatic Pop-Up facility from the standard menu configuration, re­move the “short” key sequences — that is, remove the lines in M2. MNU containing the sequences <CtrlQ>, <CtrlK> and <CtrlO>.
  2009. Changing Windows
  2010. At any time you can change the position, size, and coloring of the active window. This is achieved by pressing RScrollLockl] which enters the Window Control Mode. In this mode you can resize and reposition the window. You can even recolor the window, by pressing |Enter||. To exit the Window Control Mode, press |ScrollLock|| again. As you s-aw earlier, in addition to the Window Control Mode, there is also instant Zoom/Unzoom using the |F5|| key.
  2011. Repositioning Windows
  2012. To reposition a window, use the cursor keys on the numeric keypad after pressing IIScrollLockjl. These move the window to the required position, uncovering any win­dows that may lie beneath. Of course full-sized, or Zoomed, windows cannot be repositioned as they have no room to move. Provided that the environment doesn’t need to reposition a window for a specific context, the new window position will be saved in the Configuration and Session files. You can customize the layout of the Editor Windows by placing them, for example, side-by-side or above each other.
  2013. Resizing Windows
  2014. You can resize each of the Editor Windows wtoi in the Window Control Mode. To do this, use Shift Cursor keys — that is, IShift||[T||, UShiftl^ri], and so forth.
  2015. When resizing a window the top leftjiand comer remains fixgd, and the bottom and right edges move. In this way, the window. Similarly, IlShlft ||m| contracts and I Shift window. The size of each window is saved in the session file and restored when
  2016. contracts and |IShift||UJ| expands the height of expands the width of the
  2017. re-entering the environment.
  2018. Recoloring Windows
  2019. You can recolor the active window by pressing UScrollLockl] then H Enter j. To recolor different areas:
  2020. • Select the area by pressing the |PgUpl| or IPeDnll keys until the text in the required area flashes
  2021. • Use FH1 and FH] to change the background and Q and Q to change the foreground colors
  2022. When you find the desired color, you can either select a new area or you can exit Window Control Mode by pressing |IScrollLockJ| again. If you want to abort recoloring, press |iCtrl||[U|| to restore the original colors.
  2023. The Help Line at the bottom of the screen (see “Help Lines,” page 84) can be recolored by pressing [ScrolILockl | Enter||
  2024. The color of each window is saved in the Configuration and Session files.
  2025. If Options Setup High-Background (see “High Background,” page 76) is ON and you are using an IBM or compatible CGA display, then you can set the background to any of the 16 colors available including the bright backgrounds. Otherwise only eight backgrounds are available on the CGA, together with 16 foreground colors.
  2026. Note that to make recoloring of the environment easier, windows having similar uses are grouped together into Window Classes. Recoloring any window of a window class will automatically recolor all other windows in that class.
  2027. Window classes include the following:
  2028. • Menu windows
  2029. • Error/Waming windows
  2030. • Prompt windows
  2031. • Input windows
  2032. • Directory/File selection windows
  2033. • Compiler/Make/Link windows
  2034. • Each Editor Window
  2035. Customizing the Error Messages
  2036. You can customize or translate the error messages produced by the compiler, by editing the file M2 . ERR.
  2037. This is an ASCII text file, with one line per error message. Each line should start with the error number, followed by the error message text. You can define macros for commonly occurring text by starting a line with %A—%Z, followed by the macro text.
  2038. For example
  2039. %Z File system error
  2040. defines a macro %Z that will be expanded to “File system error” whenever %Z occurs in either Error or Macro definition text.
  2041. The following macros are predefined by the compiler
  2042. %A Used to define the Line/Column string used by the batch compiler. The macro definition is actually as follows:
  2043. (%F %L %C)
  2044. When expanded, this macro displays the following information within paren­theses: file name (%F), number of line on which error was found (%L) and column in which error was found (%C).
  2045. %C Filled in to be the Column of the error.
  2046. %L Filled in to be the Line of the error.
  2047. %F The file name in which the error occurred.
  2048. %N The name the compiler was processing when the error occurred.
  2049. Other macros also have been defined in the M2. ERR file included with your TopSpeed Modula-2 system. These include:
  2050. %E Writes the Line/Column string followed by the string “Error:”
  2051. %I Writes the Line/Column string followed by the string “Internal Error:”
  2052. %X Writes the Line/Column string followed by the string “Compiler Limit:”
  2053. %Y Writes the Line/Column string followed by the string “Lexical Error:”
  2054. %Z Writes the Line/Column string followed by the string “File System Error:”
  2055. See the M2. err file for the exact format of these macros. You can redefine these macros if you wish; you cannot redefine the macros that are predefined by the com­piler. The %A macro is actually defined in the M2 . ERR file, as described above. Since it is used in many of the error messages, you should be very careful about redefining it.
  2056. Chapter 6
  2057. The Language
  2058. This chapter gives a concise definition of the TopSpeed Modula-2 language. The lan­guage definition is kept compact and should be read with care. This style of presen­tation is in contrast to the case studies, which give a more informal and explanatory description.
  2059. Programs must conform to the syntax of Modula-2. The syntax specifies the basic textual structure of valid programs. Only syntactically correct programs are accepted by the compiler.
  2060. Secondly, programs must conform to the compile-time (static) semantics of Modula-2. This concerns the meaning associated with program identifiers, and the way they are used. It involves, among other things, type-checking. Errors in these matters are detected by the compiler.
  2061. Finally, programs should conform to the run-time (dynamic) semantics of Modula-2. This involves the actual behavior of an executing program. It is required, for example, that array-index values stay within certain ranges. It is optional whether these con­straining rules are enforced during program execution. If not, violating them will gen­erally produce undefined results, but can be used to achieve certain devious effects.
  2062. The underlying machine architecture is the 8086-family with an address space of 220 (IM) bytes of 8 bits. A physical address is formed from a 16-bit segment and a 16-bit offset; the absolute byte-address is: (16 * segment) + offset. Therefore, address arithmetic is handled differently than specified by Wirth (in Programming in Modula-2). See the discussion of pointer constructors later in this chapter (page 109).
  2063. Boldface will be used when new concepts are introduced, or when an ordinary phrase is given a special well-defined meaning.
  2064. Examples will be used to illustrate each of the concepts described; some will refer to entities declared in previous examples.
  2065. Textual Topics
  2066. Tokens
  2067. Tokens are the basic textual elements on which the structure of Modula-2 is based. A token is a sequence of characters from the ASCII set. The tokens fall into four classes: keywords, delimiters, generic tokens, and separators. The keywords and delimiters consist of fixed sequences of characters, whereas for each generic token a multitude of character sequences are possible.
  2068. The keywords are:
  2069. AND FOR OR
  2070. ARRAY BEGIN
  2071. BY
  2072. CASE
  2073. CONST
  2074. DEFINITION DIV
  2075. DO
  2076. ELSE
  2077. ELSIF
  2078. END
  2079. EXIT EXPORT FORWARD FROM GOTO IF
  2080. IMPLEMENTATION IMPORT
  2081. IN LABEL LOOP MOD MODULE NOT OF POINTER
  2082. PROCEDURE QUALIFIED RECORD REPEAT RETURN SET
  2083. THEN TO TYPE UNTIL VAR WHILE WITH
  2084. The delimiters are:
  2085. + * / : = &
  2086. : ( ) [ 1 { } * ~
  2087. = # <> < ■<— > >= « »
  2088. The generic tokens are:
  2089. Identifier: a list of letters (‘A’ to ‘Z’, ‘a’ to ‘z’ and and digits (‘0’
  2090. to ‘9’) starting with a letter; the 43 keywords are excluded. Uppercase and lowercase letters are considered distinct.
  2091. Examples:
  2092. HelloThere Agent_007
  2093. main
  2094. Decimal literal: a list of digits.
  2095. Examples: 12345 0 255
  2096. Octal literal: a list of octal digits (‘0’ to ‘7’) followed by ‘B’.
  2097. Examples:
  2098. 10B (=8) 377B (=255)
  2099. Hex literal: a list of digits and hexadecimal letters (‘A’ to ‘F’) followed by ‘H’; it must start with a digit.
  2100. Examples:
  2101. 10H (=16) OFFH (=255)
  2102. Real literal: a list of digits, followed by optionally followed by a list of digits, optionally followed by an exponent part consisting of an ‘E’ followed by an optional sign, *+’ or followed by a list of digits.
  2103. Examples:
  2104. 3.14 12.3E-3 (=0.0123)
  2105. String literal: a list of characters enclosed in quotes (’) or double-quotes (”). The enclosed list cannot contain the enclosing character, nor can the list extend over line breaks. A string of length one is alternatively called a character. A character can also be specified by its octal ASCII value as a list of octal digits followed by ‘C’.
  2106. Examples:
  2107. 'Hi' "that's ok" 101C (='A')
  2108. The separators are:
  2109. White-spaces: any list of blanks, tabs and line breaks.
  2110. Comments: any list of characters enclosed in ‘ (*’ and **) ’. Comments can
  2111. be nested and can extend over line breaks.
  2112. The tokens *#’ and ‘O’ can be used interchangeably, as can *&’ and AND. The tokens and NOT can also be used interchangeably.
  2113. Identifiers are used to denote user-defined entities.
  2114. The decimal, octal, and hex literals denote whole numbers.
  2115. Real literals denote real numbers. The exponent part denotes multiplication by the specified power of 10.
  2116. As many characters as possible are fitted into each token: 123 is one three-digit literal, not three one-digit literals.
  2117. Separators, except comments starting ‘ (*$’ (see Chapter 7), have no influence on the meaning of the program except to separate tokens.
  2118. Syntax
  2119. The syntax of Modula-2 describes how sequences of tokens are grouped to form valid program text. The syntax contains a set of syntactical constructs and pro­ductions. The productions specify how constructs and tokens are combined to form new constructs. Each construct can have several alternative productions, each spec­ifying a possible expansion of that construct. The alternatives will be shown where relevant, rather than being shown collectively.
  2120. The following meta-symbols are used in the productions:
  2121. square brackets ([ and ]) are used to enclose optional parts.
  2122. curly braces ({ and }) are used to enclose parts that can be repeated zero
  2123. or more times.
  2124. bar (I) is used to separate alternatives.
  2125. definition symbol (: : =) separates the syntactical construct being defined from its expansion.
  2126. Mixed case is used for names of constructs, upper case for keywords. Delimiters are shown in single quotes. The generic tokens are named: Id, WholeNumber, RealNumber and String.
  2127. The productions form the backbone of the language definition, and should be ‘read’ like ordinary statements; the text following each production will implicitly refer to its constituents. Thus
  2128. • IdLlst ::= Id { Id }
  2129. defines a list of one or more identifiers separated by commas.
  2130. Examples:
  2131. HelloThere, _main , X
  2132. Agent_007
  2133. Declarations and Visibility
  2134. Every identifier must either be declared or predefined. Declarations introduce programmer-defined entities and establish their properties. After an identifier is de­clared, it is used to name the declared entity:
  2135. • Name ::= Id
  2136. Declarations come in lists:
  2137. • Del List ::= { Declaration }
  2138. Identifiers must be declared before they are used. The only exception is types desig­nated by pointers (see “Pointer Types,” page 104), which must be declared by the end of the same declaration list. Before the declaration, operations requiring knowledge of the designated type are illegal — for example, anything involving de-referencing.
  2139. All identifiers declared in a declaration list must be distinct.
  2140. A declaration remains in effect throughout the scope of the declaration. The scope extends from the declaration itself, throughout the rest of the declaration list, and throughout a possible list of statements associated with the declaration list.
  2141. Declaration lists can be nested by means of procedure bodies and modules (see “Bodies,” page 116 and “Modules,” page 121), and it is legal to re-declare identifiers in such inner scopes. WITH-statements are another way of making nested scopes. A particular instance of an identifier denotes the entity declared previously in the innermost enclosing scope; it hides entities denoted, by the same identifier in outer scopes.
  2142. Example:
  2143. / /
  2144. MODULE M;
  2145. VAR I,J: CARDINAL; (* Two variables belonging to M *) PROCEDURE P;
  2146. VAR I,K: INTEGER; (* Two variable^ belonging to P *) BEGIN
  2147. I := 7; (* P's I *)
  2148. J := 8; (* M's J *)
  2149. K := 9; (* P's K *)
  2150. END P;
  2151. BEGIN
  2152. I := 10; (* M's I *)
  2153. J := 11; (* M's J *)
  2154. (* no K is visible here *) END M;
  2155. Alias declarations do not declare new entities, but introduce alternative names for existing ones:
  2156. • Declaration ::= const { id Name }
  2157. The name can denote any entity.
  2158. Example: CONST VisibleVersion : := AboutToBeHidden;
  2159. The predefined identifiers, listed below, are considered to be declared in an (outer­most) scope, which is all-enclosing The meaning of individual identifiers is explained later.
  2160. ABS DEC LONGCARD ORD WORD
  2161. ADDRESS DISPOSE LONGINT PROC VSIZE
  2162. ADR EXCL LONGREAL REAL
  2163. BITSET FALSE LONGWORD SHORTADDR
  2164. BOOLEAN FLOAT MAX SHORTCARD
  2165. BYTE HALT MIN SHORTINT
  2166. CAP HIGH NEW SIZE
  2167. CARDINAL INC NIL TRUE
  2168. CHAR INCL NULLPROC TRUNC
  2169. CHR INTEGER ODD VAL
  2170. Types
  2171. A type defines a set of values. Modula-2 contains a number of predefined types, and constructs for defining new types. New types can be given names in type declarations:
  2172. • Declaration type { Id '=’ TypeDef}
  2173. Some types are called simple types:
  2174. • TypeDef ::= SlmpleType
  2175. A type can be just the name of a type:
  2176. • SimpleType ::= Name
  2177. Note: this syntactical construct is used for naming any type, not just simple ones.
  2178. If the definition of a type declaration is just the name of a type, the defined type is identical to the named one.
  2179. Example: TYPE O'ustCardinal = CARDINAL;
  2180. Numeric Types
  2181. CARDINAL Types M'odula-2 has three predefined cardinal types, whose values are unsigned whole numbers in the specified ranges:
  2182. CARDINAL: SHORTCARD: LONGCARD:
  2183. 0 to 65535
  2184. (0 to 216 - 1)
  2185. (0 to 28 - 1)
  2186. (0 to 232 - 1)
  2187. 0 to 255
  2188. 0 to 4294967295
  2189. INTEGER Types Similarly, there are three predefined integer types, whose values are signed whole numbers in the specified ranges:
  2190. INTEGER: -32768 to +32767 (-215 to 215 - 1)
  2191. SHORTINT: -128 to+127 (-27 to 27 - 1)
  2192. LONGINT: -2147483648 to+2147483647 (-231 to 231 - 1)
  2193. Collectively, the integer and cardinal types are called whole number types.
  2194. REAL Types There are two predefined real types, whose values are the real numbers to a certain precision:
  2195. REAL: +/- 1.2E-38 to 3.4E+38 6 digits precision
  2196. LONGREAL: +/- 2.3E-308 to 1.7E+308 15 digits precision
  2197. Collectively, the integer, cardinal and real types are called numeric types.
  2198. Ordinal Types
  2199. CHAR Type The predefined type CHAR contains 256 values. The first 128 are the characters of the ASCH set, the last 128 are special graphic characters.
  2200. Enumeration Types Modula-2 provides a mechanism for defining enumer­ation types by giving a complete list of the values in the type. The values, enumera­tion literals, are represented by identifiers, which are declared by the type definition:
  2201. • SimpleType ::= '(’ IdList')’
  2202. Example:
  2203. TYPE Color = (Red,Yellow,Green,Brown,Blue,Pink,Black); Gender = (Male,Female);
  2204. Modula-2 has one predefined enumeration type containing truth values:
  2205. TYPE BOOLEAN = (FALSE, TRUE) ;
  2206. Collectively, the integer, cardinal, character, and enumeration types are called ordinal types; they have whole-number ordinal values. Enumeration literals are numbered consecutively starting from zero. Likewise for the character type. The short ordinal types exclude LONGCARD and LONGINT.
  2207. Subrange Types
  2208. Given an ordinal type, it is possible to define a subrange type of that base type:
  2209. • SlmpleType ::= [Name ] ‘[’ Expr Expr ']’
  2210. The two expressions must be constant and of the same type. They restrict the values of the type by specifying a lower and upper bound (lower <= upper). If the Name is present it names the base type; otherwise, if the expression values are of unspecified whole-number type, the base type is assumed to be INTEGER if the first expression is negative, otherwise CARDINAL.
  2211. Examples:
  2212. TYPE Year = [1900..2001]; (* Base is CARDINAL *)
  2213. Mylnt = [-1000..+1000]; (* Base is INTEGER *)
  2214. Digits = ['0'..'9']; (* Base is CHAR *)
  2215. IntYear = INTEGER [1900..2001]; (* Base is INTEGER *)
  2216. LongYear = LONGCARD[101900..102001];
  2217. HighColor = [Blue..Black]; (* Base is Color *)
  2218. Subrange types are themselves ordinal types.
  2219. Set Types
  2220. Given any short ordinal type, it is possible to define a set type whose values are (unordered) sets of values of that short ordinal type:
  2221. • TypeDef ::= set of SimpleType
  2222. A set type contains any subset of values of the set element type.
  2223. Example:
  2224. TYPE Chars = SET OF CHAR;
  2225. There is one predefined set type:
  2226. TYPE BITSET = SET OF [0..15];
  2227. Array Types
  2228. Array types provide mappings from a short ordinal index type onto any array element type:
  2229. • TypeDef ::= array IndexLIst of TypeDef
  2230. • IndexLIst ::= SlmpleType { ’ SlmpleType }
  2231. An array type definition with more than one index type is equivalent to the expanded type definition:
  2232. ARRAY Indexl OF ARRAY Index2 ... OF TypeDef
  2233. All explanations assume a single index type.
  2234. A value of an array type contains an ordered collection of values of the element type — one for each value in the index type.
  2235. Examples:
  2236. TYPE Namestring = ARRAY [0..24] OF CHAR; (* A person's name *) IntArray » ARRAY BOOLEAN OF INTEGER;
  2237. Record Types
  2238. Record types provide an aggregation of individual fields:
  2239. • TypeDef ::= record FleldDefLIst end
  2240. • FleldDefLIst ::= FieldDef { Field Def }
  2241. • FieldDef ::= [ Id ListTypeDef ]
  2242. All the identifiers, called field names, must be distinct, but they are local to the record type definition and need not be distinct from other identifiers.
  2243. A record value contains one value of the relevant type for each field.
  2244. Examples:
  2245. TYPE Person = RECORD
  2246. First,Last: Namestring;
  2247. Age: SHORTCARD [0..125];
  2248. END;
  2249. AdrPair = RECORD Ofz,Seg: CARDINAL; END;
  2250. Variant record types allow for alternative groups of fields, variants, to be present in a record value. Variant parts can be arbitrarily nested.
  2251. • Field Def ::= Variant Part
  2252. • VariantPart ::= case [ Id] Name of Variant { '|' Variant} /■else FieldDefUst J end
  2253. • Variant ::= [ CholceList FieldDefUst ]
  2254. • CholceList ::= Choice { Choice }
  2255. • Choice ::= Expr [ ’ Expr ]
  2256. The optional tag identifier after CASE is followed by the name of a short ordinal tag type. If the tag identifier is present, it defines an actual field of that type.
  2257. The variants and the optional ELSE part each specify a list of field definitions, but only the fields of one of these variants are present in any value of the variant record type.
  2258. The choice expressions must be constant and of the tag type, and must not have overlapping values. A choice with two expressions denotes all values in the range. Each choice list should specify the tag values for which the corresponding variant is present; the ELSE-part covers any remaining values.
  2259. The presence or absence of variant fields is merely logical; they are always all ac­cessible, but they share storage.
  2260. Example:
  2261. TYPE Location =
  2262. RECORD
  2263. Value: BYTE;
  2264. CASE Simple: BOOLEAN OF
  2265. | TRUE: ByteOfz: LONGCARD;
  2266. I FALSE: SegOfz: AdrPair;
  2267. END;
  2268. END;
  2269. Pointer Types
  2270. The values of a pointer type are access paths to objects of a designated type:
  2271. • TypeDef ::= pointer [ Expr ] to TypeDef
  2272. If the expression is omitted, an absolute pointer type is defined; the values of the type are complete 32-bit segment/offset physical addresses.
  2273. By including a CARDINAL expression (after POINTER), a based pointer type is defined. Such values only contain the offset part of a physical address. The segment part is obtained by evaluating the expression every time the designated object is accessed. Based pointers are thus short, 16-bit.
  2274. Note: Based pointers allow relocated objects to be referenced by just modifying the base (segment) value (leaving the offset unaffected).
  2275. Examples:
  2276. TYPE ListPtr = POINTER TO ListNode; (* Note: ListNode not defined yet *) ListNode = RECORD
  2277. Value: CARDINAL; (* element value *)
  2278. NextNode: ListPtr; (* next element *) END;
  2279. ShortPtr = POINTER Base TO ListNode;
  2280. There are two predefined pointer types:
  2281. TYPE ADDRESS = POINTER TO WORD;
  2282. SHORTADDR = POINTER 0 TO WORD; (* Zero base segment *)
  2283. The values in a pointer type either are obtained as the (absolute) addresses of existing objects of the designated type, or they can be raw storage addresses obtained from a storage manager (see Chapter 8).
  2284. Array, record and pointer types are collectively called compound types; the rest, except for set types, are the simple types.
  2285. Type Compatibility
  2286. Numerous situations require types to be compatible; there are three levels of com­patibility, each of decreasing strength.
  2287. The most restrictive — and hence, the strongest — is to require types to be identical; that is, they must denote the same type definition.
  2288. Next comes compatible. This includes subrange types being compatible with their base types and other subrange types of the same base type. ADDRESS is compatible with any absolute pointer type, and SHORTADDR with any based pointer type.
  2289. Finally assignment compatibility also holds between the pairs CARDINAL / IN­TEGER, SHORTCARD / SHORTINT and LONGCARD / LONGINT.
  2290. There are three predefined types called BYTE, WORD and LONGWORD. They corre­spond to 1, 2 and 4 bytes of memory, respectively, and are assignment compatible with all other types of equal size.
  2291. Special compatibility rules apply to formal parameters (see “Calling Procedures,” page 118).
  2292. Objects and Values
  2293. Objects have types and hold values exclusively of that type. There are two kinds of objects: variables and formal parameters (see page 115). Objects of array and record types can contain several component objects.
  2294. Variables have to be declared:
  2295. • Declaration ::= var { Varld { Varld } TypeDef }
  2296. • Varld ::= id
  2297. Each declaration declares all the identifiers of the list to be variables of the specified type. Their initial values are undefined.
  2298. Examples:
  2299. VAR CARDINAL;
  2300. Base: CARDINAL;
  2301. L: LONGCARD;
  2302. X,Y: LONGREAL;
  2303. P: POINTER TO INTEGER;
  2304. S: ARRAY [1..100] OF CHAR;
  2305. R: RECORD X,Y: INTEGER; END;
  2306. C: CHAR;
  2307. Z: Chars;
  2308. Bad : BOOLEAN;
  2309. Loc: Location;
  2310. Persons: ARRAY BOOLEAN OF POINTER TO Person;
  2311. A variable can be placed at a fixed physical address, by specifying constant expres­sions of type CARDINAL for the segment and offset:
  2312. • Varld ::= Id ‘[’ Expr Expr ']’
  2313. Example:
  2314. VAR ColorScreen [0B800H:0] : ARRAY [1..25] OF
  2315. ARRAY [1..80] OF
  2316. RECORD
  2317. Chr: CHAR;
  2318. Atr: SHORTCARD;
  2319. END;
  2320. Constants
  2321. Constant literals denote the most basic values:
  2322. • Value ::= WholeNumber
  2323. • Value ::= String
  2324. The whole numbers are possible values for the integer and cardinal types, the real numbers for the real types, and strings for the character type (in which case, the string must have length 1) and for types of the form: ARRAY ... OF CHAR.
  2325. Constant record and array values are formed with aggregates:
  2326. • Value ::= Name ‘(’ Expr Expr { Expr } ')’
  2327. The expressions, of which there must be at least two, are constant and give the component values for the named type.
  2328. For array types, one value must be given for each value in the index range.
  2329. For record types, one value is given for each field present. Values must be specified even for absent tag fields, in order to determine to which variant the following values belong.
  2330. Named constants can be declared, introducing identifiers that represent constant values:
  2331. • Declaration const { Id '=’ Expr }
  2332. There is a predefined constant, NIL, compatible with any absolute pointer type.
  2333. Neither literals nor named constants are objects.
  2334. Examples:
  2335. CONST Pi = 3.14159;
  2336. Ratio = 360.0 / (2.0 * Pi) ;
  2337. K = 1024;
  2338. P = Person("Donald","Duck", 50) ;
  2339. LastLoc = Location(0,FALSE,AdrPair(0FFFFH,0FH));
  2340. X = IntArray(-12345,16*K);
  2341. S = Chars { 'a', ' e', 'i', 'o', 'u'};
  2342. Set Values
  2343. Set values are formed with a set constructor:
  2344. • Value ::= [ Name ] '{’ [ CholceList ] *} ’
  2345. The expressions of the choices are values of the set element type; they need not be constant. The name denotes the set type; omitting it means BITSET.
  2346. Example:
  2347. Chars { 'A'..'2' , 'a'..'z' , '_' }
  2348. Designators
  2349. Designators are used to denote objects. Component objects of a compound object are designated by supplying suffixes to the designator of the compound object. Suffixes are also used to designate components of named aggregate constants.
  2350. Using a designator as a value means the value of the designated object:
  2351. • Value ::= Designator
  2352. The simplest form of designator is just the name of an entity:
  2353. • Designator ::= Name
  2354. This is also the way to use enumeration literals and named constants as values — just name them.
  2355. Indexing is used to designate components of objects of array types:
  2356. • Designator ::= Designator ‘[’ Expr { Expr} “]’
  2357. A list of index expressions is equivalent to a list of separate indices: X [A,B, C] is equivalent to X[A] [B] [C]. All explanations assume a single index expression.
  2358. The value of the expression must have a type assignment compatible with the index type; the designator selects the corresponding component object.
  2359. Example:
  2360. S[I+7]
  2361. Field selection is used to designate components of objects of record types:
  2362. • Designator ::= Designator Id
  2363. The identifier is any field identifier of the record type; the resulting designator des­ignates that field of the record object.
  2364. Example:
  2365. R.Y
  2366. Dereferencing is used to designate the object pointed at by objects of pointer types:
  2367. • Designator ::= Designator ‘A ’
  2368. If the pointer type is based, this includes evaluation of the base expression.
  2369. Example:
  2370. PA
  2371. Indexing, field selection and dereferencing can be mixed.
  2372. Example:
  2373. Persons[TRUE]A.Last[0] (* First letter of last name *)
  2374. A pointer constructor is provided to combine CARDINAL segment and offset values into a physical address:
  2375. • Designator ::= '[’ Expr Expr [ Name ] ']’
  2376. The name specifies the resulting absolute pointer type; omitting it means ADDRESS.
  2377. Example:
  2378. [ListSeg:FirstNode+N ListPtr]A.Value]
  2379. Expressions
  2380. Expressions specify the computation of values. Within expressions, operators are used to combine operands, which are themselves expressions.
  2381. Expressions, as well as values, have types unless all the operands are numeric literals; in that case, determination of types for such expressions is deferred until the context requires a specific type. This is how the same numeric literals (or named constants) can be used for the different numeric types. Until a context is introduced, the only distinction is between whole numbers and real numbers.
  2382. When the operands of an operator or predefined function are constant, the result is also constant, and is calculated at compile-time.
  2383. Precedence of operators is described in the syntax below; association is left-to-right. Parentheses can be used to enforce any grouping:
  2384. • Expr ::= SimpleExpr [ RelOp SimpleExpr ]
  2385. • SimpleExpr ::= [ SignOp ] Term { AddOp Term }
  2386. • Term ::= Factor { MulOp Factor }
  2387. • Factor ::= '(’ ExPr ')’
  2388. • Factor ::= not Factor
  2389. • Factor ::= Value
  2390. • RelOp ::= '=’ | '#’ | '<’ | '<=' | S’ | *>=’ | in
  2391. • SlgnOp |
  2392. □ AddOp ::= '+ ’ | | or
  2393. • MulOp ::= '*’ | 7’ I div | mod | and | '«’ | “»’
  2394. The operation indicated by an operator depends both on the operator and on the operand types.
  2395. All operators, except IN, require operands of compatible types.
  2396. The relational operators and IN deliver a result of type BOOLEAN. The rest deliver a result of the same type as the operand(s).
  2397. The operators *=’ and '#’ are defined for all types, and compare for equality an inequality, respectively.
  2398. Operators *<’, *<=’, *>’ and *>=’ are defined for the ordinal and real types, and compare for relative ordering. *<=’ and *>=’ are defined for set types, and compare for subset and superset.
  2399. The sign operator *+’ is defined for numeric types; it does nothing. The sign operator is defined for integer and real types, negating the operand.
  2400. The adding operators *+’ and are defined for numeric types and indicate addition and subtraction, respectively. They are also defined for set types and indicate set union and set difference, respectively. Finally, *+’ is also defined for any combination of constant characters and string literals, concatenating them to produce one string constant. The OR operator takes BOOLEAN operands and computes the logical sum; the right operand is only evaluated if the left is FALSE.
  2401. The multiplying operators DIV and MOD are defined for integer and cardinal types, computing product, quotient (truncated towards zero) and remainder (after division). *«’ and *»’ are defined for cardinal types, computing logical left and right shift of the left operand by the amount of the right operand. '*’ and ‘/’are defined for real types, computing (approximate) product and quotient. **’ and ‘/’are defined for set types, computing set intersection and symmetric set difference. The AND operator is defined for BOOLEAN operands, computing the logical product; the right operand is only evaluated if the left is TRUE.
  2402. The NOT operator takes a BOOLEAN operand and complements it.
  2403. The IN operator takes values of set types as right operands and values of the set element type as left operands; it tests whether the element value is in the set value.
  2404. Note: Sets are represented as bitmaps with one bit for each possible element value (indicating its presence), so the set operators ‘+’, **’, ‘/’ and correspond to bitwise boolean operations OR, AND, XOR and AND NOT, respectively.
  2405. Examples:
  2406. (J = 0) OR (I MOD J = I - (I X * Y / Ratio
  2407. R.X + 1
  2408. S[l] IN Z * (Chars{'A'..'F'} 'Line terminated with cr/lf'
  2409. DIV J)*J) (* Always TRUE *)
  2410. + Charsf'0'..'9' ))
  2411. + CHR(13) + CHR(10)
  2412. Statements
  2413. Programs achieve their effect by executing (possibly nested) statements. Statements come in lists and are executed one at a time.
  2414. • StmtList ::= [ Stmt ] { [ Stmt] }
  2415. The after the last statement is optional.
  2416. Assignment Statement
  2417. The assignment statement is used to change the value of an object:
  2418. • Stmt ::= Designator Expr
  2419. The expression is evaluated, and its value replaces the old value of the designated object. The expression must be assignment compatible with the designated object’s type.
  2420. String literals are a special case: they can be assigned to any object whose type is array ... OF CHAR and is long enough to contain the string; if the object is longer than the literal being assigned, a null character (0C) is included after the string value.
  2421. Examples:
  2422. X := 0.0;
  2423. I := J + 1;
  2424. Z := Z - Chars{' a' . .' z' ) ;
  2425. Persons[NOT Bad]A.First := "Kurt";
  2426. IF Statement
  2427. The IF statement is used to select a statement list conditionally depending on BOOLEAN expressions, conditions:
  2428. □ Stmt ::=
  2429. if Expr then StmtList { elsif Expr then StmtList } [ ELSE StmtUSt ] END
  2430. At most one of the statement lists is executed, namely the one following the first expression evaluating to TRUE, where ELSE is treated as ELSIF TRUE THEN.
  2431. Example:
  2432. IF I > J THEN
  2433. M := I;
  2434. ELSIF I < J THEN
  2435. M := J;
  2436. ELSE (* I must be = J *)
  2437. B := TRUE;
  2438. M := I;
  2439. END;
  2440. CASE Statement
  2441. The CASE statement selects between alternative statement lists depending on the value of a case expression of short ordinal type:
  2442. □ Stmt ::= case Expr of Case { ' | ’ Case } [ else StmtList ] end
  2443. • Case ::= [ ChoiceListStmtList ]
  2444. The ‘ | ’ before the first case is optional.
  2445. The types of the choice expressions must be compatible with the case expression type; they must be constant and their values must not overlap.
  2446. The statement list executed is the one whose choice list includes the value of the case expression. If none do, and there is an ELSE, that statement list is executed; otherwise, execution continues with the statement following the case statement.
  2447. Example:
  2448. CASE S[I] OF
  2449. • ': I := 999;
  2450. • 'A' . .'Z' : L := L + 1;
  2451. U := U + 1;
  2452. L := L + 1;
  2453. X := X + 1;
  2454. ELSE END;
  2455. TheEnd := TRUE;
  2456. WHILE Statement
  2457. The WHILE statement is used to execute a statement list zero or more times depending on the value of a condition:
  2458. • Stmt ::= while Expr do StmtLIst end
  2459. The expression is evaluated before each execution of the statement list; repetition stops as soon as the expression is FALSE.
  2460. Example:
  2461. WHILE (I > 0) AND (I MOD 2=0) DO
  2462. I := I DIV 2;
  2463. END;
  2464. REPEAT Statement
  2465. The REPEAT statement is used to execute a statement list one or more times, de­pending on the value of a condition:
  2466. • Stmt ::= repeat StmtList until Expr
  2467. The expression is evaluated after each execution of the statement list; repetition stops as soon as the expression is TRUE.
  2468. Example:
  2469. REPEAT
  2470. I := I MOD N + 1;
  2471. UNTIL S[I] = '
  2472. LOOP and EXIT Statements
  2473. The LOOP statement is used to execute a statement list repeatedly, with several exit points possible:
  2474. • Stmt ::= loop StmtList end
  2475. • Stmt ::= exit
  2476. An EXIT statement is only legal inside LOOP statements; it terminates the innermost enclosing LOOP.
  2477. Example:
  2478. LOOP
  2479. IF I = J THEN EXIT; END;
  2480. WHILE I < J DO
  2481. I := (I * J) MOD N;
  2482. IF I = 0 THEN
  2483. I := J;
  2484. EXIT; (* exit LOOP, not just WHILE *) END;
  2485. END;
  2486. I := I DIV 2;
  2487. END;
  2488. (* The LOOP has now been EXITed *)
  2489. FOR Statement
  2490. The FOR statement is used to execute a statement list a precalculated number of times, with an ordinal control variable taking on a progressing series of values:
  2491. • Stmt ::= for Id Expr to Expr [ by Expr ] do StmtLlst end
  2492. The first two expressions are evaluated to obtain the start and stop values; they must have types compatible with the ordinal type of the identifier. The expression after BY, the step value, must be a constant whole number; omitting it means +1.
  2493. The control variable takes on ordinal values beginning with the start value and spaced by the step value. The FOR statement terminates when the next value would exceed the stop value. If the start value exceeds the stop value, the statement list is not executed at all. The direction of progression is determined by the sign of the step value.
  2494. The value of the control variable should not be changed inside the statement list, and it is undefined after the FOR statement.
  2495. Example:
  2496. FOR Ball :» Black TO Yellow BY -2 DO
  2497. LastBall := Ball; (* Takes on: Black, Blue, Green *) END;
  2498. WITH Statement
  2499. The WITH statement is used to create a local scope wherein the field names of a record type can be used directly to denote the fields of a particular designated record object.
  2500. • Stmt ::= with Designator do StmtLlst end
  2501. Example:
  2502. WITH Persons[TRUE]A DO
  2503. IF Age < 4 THEN First := "baby";
  2504. ELSIF Age < 15 THEN
  2505. First := "junior";
  2506. END;
  2507. END;
  2508. GOTO Statement
  2509. The GOTO statement is used to alter the flow of execution explicitly:
  2510. • Stmt ::= goto Id
  2511. The target of the jump is indicated by the label identifier, which must be located somewhere in the same body (see “Bodies,” page 116):
  2512. • Stmt ::= Id [ Stmt ]
  2513. Labels must be declared in the body in which they are used:
  2514. • Declaration ::= label IdLlst
  2515. Procedures
  2516. Procedures are used to group commonly performed operations into isolated blocks. Proper procedures are used like statements, whereas functions compute values and are used in expressions.
  2517. Procedures:
  2518. • are declared like other entities, and are subsequently invoked by calls
  2519. • can have parameters which are objects or values supplied at the call
  2520. • finish execution by returning
  2521. Procedures can also be handled without being called; they can be valid values of a procedure type and can be manipulated as such.
  2522. The characteristics of a procedure are specified in a procedure heading:
  2523. • ProcHead ::= procedure Id [ FormalLIst [ Name ] ]
  2524. • FormalLIst ::= '(’ [ FormalSectlon { FormalSectlon } ] “)’
  2525. • FormalSectlon ::= £var ] IdLlst Formallype
  2526. • Formaliype ::= [ array of ] Name
  2527. A procedure heading declares the identifier denoting the procedure. It has a (possibly empty) list of formal parameters declared similarly to variables. The absence of the and the name in the procedure heading indicates a proper procedure; their presence indicates a function, in which case the name states the return type (which can be a structured type).
  2528. Each formal section does the following:
  2529. • declares a list of formal parameters
  2530. • states their formal type
  2531. • indicates whether they are variable, or VAR parameters or value parameters by the presence/absence of the keyword,VAR
  2532. All the parameter identifiers in a formal list must be distinct.
  2533. Examples:
  2534. PROCEDURE NewLine;
  2535. PROCEDURE PrintNumber ( N: INTEGER; Width: SHORTCARD );
  2536. PROCEDURE Accumulate ( VAR X: LONGREAL; Delta: LONGREAL );
  2537. PROCEDURE HypSquare ( A,B: LONGREAL ): LONGREAL;
  2538. PROCEDURE PrintMessage ( M: ARRAY OF CHAR );
  2539. PROCEDURE GetChar (): CHAR;
  2540. Bodies
  2541. A procedure heading is combined with a body specifying the internal workings of the procedure; a FORWARD declaration is used to delay specifying the body:
  2542. • Declaration ::= ProcHead Body Id
  2543. • Declaration ::= ProcHead forward
  2544. • Body ::= Del List [ begin StmtList ] end
  2545. The identifier repeats the procedure name.
  2546. A FORWARD declared procedure must be completed later in the same declaration list by a full procedure declaration repeating the procedure heading and supplying a body.
  2547. The declaration list declares entities that are local to the procedure; they must have names distinct from the formal parameters.
  2548. Formal parameters of type ARRAY OF Type, open array parameters, are consid­ered to be local arrays indexed with CARDINALS starting from 0; the upper index bound is obtained by the HIGH function.
  2549. Local variables come into existence when procedures are called and vanish when they return. Procedures can call themselves directly or indirectly, causing several incarnations of local variables to be in existence simultaneously. Designating any local variable refers to the instance in the most recent active invocation of that procedure.
  2550. A formal value parameter is considered an ordinary local variable whose value is initialized when the procedure is called. Formal VAR parameters denote actual objects, which are identified by the caller when the procedure is called.
  2551. Open arrays can be used as actual parameters to other open array formal parameters; otherwise they can only be manipulated element-wise.
  2552. The statement list specifies the actions of the procedure.
  2553. Executing a RETURN statement is the only legal way of leaving & function. A proper procedure can also return by just reaching the end of the statement list.
  2554. • Stmt ::= return [ Expr ]
  2555. The expression must be present for functions exclusively, and the expression’s type must be assignment compatible with the return type; it is the value returned to die caller.
  2556. Examples:
  2557. PROCEDURE Max ( X,Y: LONGREAL): LONGREAL; BEGIN IF X > Y THEN RETURN X;
  2558. ELSE
  2559. RETURN Y;
  2560. END;
  2561. END Max;
  2562. PROCEDURE HypSquare ( A,B: LONGREAL ): LONGREAL; FORWARD;
  2563. PROCEDURE Accumulate ( VAR X: LONGREAL; Y: LONGREAL );
  2564. VAR Z: LONGREAL;
  2565. BEGIN
  2566. Z := HypSquare( Y , 10.0-Y );
  2567. X := X + Max(Z * Z , -999.99);
  2568. END Accumulate;
  2569. PROCEDURE HypSquare ( A,B: LONGREAL ): LONGREAL;
  2570. BEGIN
  2571. RETURN A*A + B*B;
  2572. END HypSquare;
  2573. Calling Procedures
  2574. Proper procedures are invoked in call statements:
  2575. • Stmt ::= Designator [ ActualLIst ]
  2576. • ActualLIst ::= ’(’ [ ExPr { Expr } ] ')’
  2577. The actual parameter list must supply one value or designator for each correspond­ing formal parameter. For a VAR parameter the expression must be a designator of an object with type identical to the formal type; for value parameters any expression of assignment compatible type is valid. String literals are valid parameters for any value parameter of type ARRAY ... OF CHAR.
  2578. A formal type ARRAY OF Type is considered identical to any array type with that element type; the index range of the actual parameter is mapped onto the CARDINALS starting from 0. An expression of the element type is also valid (and is treated as an array with one element).
  2579. The formal types BYTE, WORD and LONGWORD are compatible with any type of identical size. The formal types ARRAY OF BYTE, ARRAY OF WORD and ARRAY OF LONGWORD are compatible with anything, allowing the procedure to treat the actual parameter as unstructured storage.
  2580. Examples:
  2581. NewLine;
  2582. PrintMessage("Don't panic");
  2583. Accumulate( X , 7.0 * Y );
  2584. Functions are invoked in expressions:
  2585. • Value ::= Designator ActualLIst
  2586. The parameter rules are as for proper procedures.
  2587. Examples:
  2588. X := HypSquare( 10.0 , Y );
  2589. C :“ GetChar ();
  2590. Some procedures can alternatively be called using infix notation:
  2591. • Infix ::= \ ’ Designator ‘\ ’
  2592. The designated procedure must take two parameters.
  2593. Functions are applied like operators of the lowest possible expression precedence:
  2594. • Expr’ ::= Expr { Infix Expr }
  2595. Proper procedures are called similarly to assignment statements:
  2596. • Stmt ::= Expr Infix Expr’
  2597. Examples:
  2598. X \Accuraulate\ 1.0 + (5.0 \HypSquare\ Y-1.0); (* infix *)
  2599. Accumulate( X , 1.0 + HypSquare( 5.0 , Y-1.0 ) ); (* same *)
  2600. Procedure Types
  2601. A procedure type denotes a family of procedures with identical calling characteristics:
  2602. • TypeDef ::=
  2603. procedure I'(’ [ FormalTypeLlst ] ')’ [Name ]]
  2604. • FormalTypeLlst ::=
  2605. [ var ] FormalType { [ var ] FormalType }
  2606. The procedures belonging to the type are those with matching procedure headings: each parameter must be of identical type for VAR parameters, and of identical or assignment compatible type for value parameters; return types must be identical for functions. Predefined procedures and procedures nested within other procedures are excluded.
  2607. Example:
  2608. TYPE PutProc = PROCEDURE ( ARRAY OF CHAR );
  2609. VAR G: ARRAY BOOLEAN OF PROCEDURE () : CHAR;
  2610. P: PutProc;
  2611. There is one predefined procedure type:
  2612. TYPE PROC = PROCEDURE; (* Procedures without parameters *)
  2613. One predefined procedure value, NULLPROC, is compatible with any procedure type. Calling it causes a run-time error.
  2614. Procedure values are denoted by designators without parameter lists.
  2615. Examples:
  2616. P :■ PrintMessage; (* P now denotes PrintMessage *)
  2617. P("Hi, there"); (* Call it *)
  2618. G[TRUE] :■= GetChar; (* G[TRUE] now denotes GetChar *)
  2619. C := G[TRUE] (); (* Call it *)
  2620. Predefined Procedures
  2621. Modula-2 contains a number of predefined procedures. Some are generic in the sense that they are valid for several parameter types and can take one or two parameters.
  2622. Predefined Function Procedures The predefined function procedures are:
  2623. ABS ( X ) ADR( X ) CAP ( C ) CHR( X ) FLOAT( C ) HIGH ( A ) MAX ( T ) MIN( T ) ODD( X ) ORD ( X ) SIZE( T ) TRUNC( R ) VAL( T,X ) VSIZE( R.F )
  2624. Absolute value of numeric operands.
  2625. The physical ADDRESS of object X.
  2626. Character C, changing *a’..‘z’ to *A’..‘Z’.
  2627. The CHAR with ordinal value X.
  2628. REAL value of CARDINAL C.
  2629. The upper index bound of open array A.
  2630. Maximum value of ordinal/real type T.
  2631. Minimum value of ordinal/real type T.
  2632. TRUE if ordinal value X is not even.
  2633. CARDINAL, short ordinal value of X.
  2634. Size in bytes of type or object T.
  2635. CARDINAL, truncated value of real R.
  2636. The value X converted to type T.
  2637. Size of record type R if it contained just the fields up to and including field F. See the following example:
  2638. Example: To illustrate how VS I ZE works, consider the following RECORD
  2639. definition:
  2640. TYPE VSTest = RECORD
  2641. A : CARDINAL;
  2642. B : INTEGER;
  2643. C : CARDINAL;
  2644. D : LONGCARD;
  2645. END;
  2646. With this RECORD definition, a call to VSIZE (VsTest. C) would return the size of the record including only the first three fields — A, B, and C.
  2647. VAL can convert values between any two numeric or ordinal types.
  2648. Any type name can be used as a type transfer function, taking one value parameter of any type. The result is that value interpreted as a value of the named type. The actual bit pattern of the value remains unchanged, except if the value type and transfer type are numeric or ordinal, when a proper VAL conversion is performed.
  2649. A type transfer is considered well-behaved if the sizes of the value type and the transfer type are equal, or a proper VAL conversion is performed. Such type transfers can be used freely in expressions.
  2650. If the value type size is larger than the transfer type size, the remaining last bytes of the value are ignored. If it is shorter, the last bytes of the resulting value are undefined.
  2651. Such type transfers should only be used to circumvent the type requirements of assignment and parameter passing.
  2652. Examples:
  2653. I := CARDINAL( BITSET(I) L :« LONGCARD( SegOfz ); SegOfz := AdrPair( L );
  2654. P :« ADDRESS ( L ) ;
  2655. * BITSET(J) ); (* bitwise AND *) (* record -> cardinal *) (* cardinal -> record *)
  2656. (* Not address of L!!! *)
  2657. Predefined Proper Procedures The predefined proper procedures are:
  2658. DEC( X ) DISPOSE! X )
  2659. DEC( X,N ) EXCL( S,E ) HALT INC( X ) INC( X,N ) INCL( S,E ) NEW ( X)
  2660. Decrement ordinal object X.
  2661. When the compiler encounters the DISPOSE procedure, This is replaced by a call to DEALLOCATE ( X, SIZE(XA)). Decrement ordinal object X by amount N.
  2662. Exclude element E from set object S.
  2663. Terminate program execution successfully.
  2664. Increment ordinal object X.
  2665. Increment ordinal object X with amount N.
  2666. Include element E in set object S.
  2667. This is replaced by a call to ALLOCATE ( X, SIZE(XA)) when the compiler encounters the NEW procedure.
  2668. Modules
  2669. Modules encapsulate related declarations. An executing program consists of a main module and a number of server modules. The server modules are partitioned into a definition part, which is visible to clients, and an implementation part, which hides the internal details from clients.
  2670. Modules provide a general facility for implementing features not supported explicitly within the language. Such features include: input and output, string handling, storage management, concurrency, operating system access, etc. (see Chapter 8).
  2671. Modules are the basic units of compilation:
  2672. • Compilation ::= Def Module
  2673. • Compilation ::= [ implementation ] Module
  2674. • Module ::=
  2675. module Id [ Priority ] {Import} [ Export ] Body Id
  2676. • DefModule ::=
  2677. DEFINITION MODULE Id { Import } DcILIStEND Id
  2678. • Priority ::= ‘[’ Expr “]’
  2679. Each identifier names the module defined.
  2680. Modules optionally have a CARDINAL priority used with the SYSTEM module (see
  2681. Chapter 8).
  2682. A compilation module without IMPLEMENTATION is a main module.
  2683. Server Modules
  2684. The definition part of a module declares the entities available to clients. Only CONST, TYPE and VAR declarations are legal, in addition to the following two, which are legal only in definition parts:
  2685. • Declaration ::= ProcHead
  2686. • Declaration ::= type { Id [ ‘=’ TypeDef ] }
  2687. The first form declares the existence of a procedure. The second form, when the type definition is omitted, declares the existence of an opaque pointer type with unknown designated type; the only allowed operations on objects of opaque type are assignment and test for equality. Corresponding full declarations for objects of the opaque type must appear in the implementation part of the module.
  2688. Objects declared in compilation modules are called global and exist throughout the execution of the program (as opposed to variables local to procedures).
  2689. Example:
  2690. DEFINITION MODULE Str; (* A bit of string handling *)
  2691. CONST MaxWidth = 20;
  2692. TYPE Buffer = ARRAY [1..MaxWidth] OF CHAR;
  2693. VAR Width: [1..MaxWidth];
  2694. PROCEDURE Put ( C: CARDINAL ): Buffer;
  2695. PROCEDURE SetFill( C: CHAR );
  2696. END Str.
  2697. The implementation part contains declarations private to the module. These declara­tions are not accessible to client modules. The optional list of statements, initializa­tion code, is executed before any statements of clients are executed. If this is im­possible to satisfy because of circularity, the initialization order is undefined within the circle. The TopSpeed Modula-2 TechKit contains a program for determining the module dependencies in a program, and for detecting circular dependencies.
  2698. The declarations in the implementation part form a single scope together with those in the definition part. Consequently every name from the definition part is visible, and additional names declared must be distinct from those. Reimporting identifiers is allowed.
  2699. Example:
  2700. IMPLEMENTATION MODULE Str;
  2701. VAR FillChar: CHAR;
  2702. PROCEDURE Put ( C: CARDINAL ): Buffer;
  2703. VAR P: [0..MaxWidth];
  2704. S: Buffer;
  2705. BEGIN
  2706. P := Width;
  2707. REPEAT
  2708. S[P] := CHR( ORD('O') + C MOD 10 );
  2709. C := C DIV 10;
  2710. DEC( P );
  2711. UNTIL (C = 0) OR (P = 0);
  2712. WHILE P > 0 DO
  2713. S[P] := FillChar;
  2714. DEC( P );
  2715. END;
  2716. RETURN S;
  2717. END Put;
  2718. PROCEDURE SetFill ( C: CHAR );
  2719. BEGIN
  2720. FillChar := C;
  2721. END SetFill;
  2722. BEGIN
  2723. FillChar := ' ';
  2724. END Str.
  2725. Importing
  2726. Clients gain access to a server module by importing from it:
  2727. • Import ::= [ from Id ] import IdLlst
  2728. The FROM form takes one module and a list of identifiers naming entities in it. Those names are considered declarations of those identifiers and thus achieve direct visibility of the named entities. Importing an enumeration type also imports the enumeration literals.
  2729. The FROM-less form imports each of the modules named. Qualified names are used to denote the entities in those modules:
  2730. • Name ::= Name Id
  2731. The name denotes a module; the second component — the Id — an entity therein. The same qualified notation can be used to name a module’s own entities, but only within the implementation part.
  2732. Example:
  2733. FROM Str IMPORT Put,Width;
  2734. IMPORT Str;
  2735. VAR S: Str.Buffer;
  2736. Str.SetFill(' ');
  2737. Width := Str.MaxWidth DIV 2;
  2738. S := Put( 1+7 );
  2739. Local Modules
  2740. In addition to their use as compilation units, local modules can be declared;
  2741. • Declaration ::= Module
  2742. Local modules obey special scope rules. Any required entity (except the predefined ones) from outside the local module must be imported, and must be visible imme­diately outside the local module. Thus FROM-less import can name any entity (not only server modules). Using the FROM form requires the named server module to be visible (and thus already imported) immediately outside the local module.
  2743. Exportation is valid only in local modules:
  2744. • Export ::= export [ QUALIFIED ] IdLlst
  2745. The listed identifiers are declared in the enclosing scope to make those entities directly available.
  2746. Qualification can be used to access any entity.
  2747. If the export list contains QUALIFIED, then the export statement has no effect.
  2748. The optional statement lists of local modules are executed (in the sequence they appear) before the statement list of the enclosing body.
  2749. This concludes the TopSpeed Modula-2 language definition.
  2750. Sources for Language Examples
  2751. K. N. King’s TopSpeed Modula-2 Language Tutorial, included with your TopSpeed Modula-2 package, contains a more detailed discussion of the language, as well as numerous examples. The discussion of library procedures in Chapter 8 provides additional exposure to the language’s constructs and how to use them. The case studies in Chapter 4 also show examples of how certain Modula-2 types and constructs
  2752. are used. You can refer to the source code for the library modules to see how various Modula-2 constructs are used, and also to see how modules are constructed.
  2753. In Chapter 7, you will find out about options you can use to check that your program conforms to the run-time semantics of the language.
  2754. Chapter 7
  2755. The Compiler
  2756. The TopSpeed Modula-2 compiler has a one-pass architecture, meaning that it outputs the generated code simultaneously with reading the source text; no temporary files are used.
  2757. Importing is handled by (re)compiling module definition files (DEF-files) whenever required. This eliminates the need for special ‘symbol-table’ files, and means that module definitions need not be compiled explicitly; it also means that such defini­tions affect subsequent compilations as soon as they are modified. This strategy also eliminates the compilation-order restrictions that usually apply to module definitions; module implementations can be compiled in any order.
  2758. The output from the compiler is a relocatable object file (OB J-file) in Intel/Microsoft format. A collection of such files is combined into one executable file (EXE-file) by a linker.
  2759. The OBJ-file
  2760. The OBJ-file created by the compiler contains special information that makes linking easier, checks consistency, and minimizes EXE-file size.
  2761. Include-records are inserted into the OBJ-files. These records tell the linker the names of the files used by the module. This means that only the name of the main module needs be supplied when linking. The linker will find the remaining files through the include-records.
  2762. Version-records are also inserted. These record the date and time of the DEF-files used. The linker will check that all modules agree on these versions. If they don’t, there is the possibility of a fatal inconsistency which should be eliminated by recom­piling (see the Make option in “Making a Program,” page 69).
  2763. The OBJ-file is built as a library, meaning that the module is split into sections which are only included by the linker if they are used. This eliminates the overhead for large general-purpose library modules. Thus, your EXE-file is as small as possible. In the OBJ-file, each global procedure is in a section by itself, and so are groups of data-declarations belonging to the same VAR or CONST part.
  2764. Data Representation
  2765. The basic storage unit is an 8-bit byte. Any Modula-2 object is represented in a number of bytes determined by the object’s type. Subrange types are represented as their base types.
  2766. Taking the ADDRESS of an object yields the address of the first byte of its storage. For multi-byte numeric types, the least significant byte of the object is stored at the lowest address.
  2767. Cardinal types are represented as unsigned binary numbers, and have the following storage requirements:
  2768. SHORTCARD: 1 byte
  2769. CARDINAL: 2 bytes
  2770. LONGCARD: 4 bytes
  2771. Integer types are represented as 2’s-complement binary numbers, and require the following storage:
  2772. SHORTINT: 1 byte
  2773. INTEGER: 2 bytes
  2774. LONGINT: 4 bytes
  2775. Real types are represented as 8087 mantissa/exponent pairs. (See the relevant 8087 documentation for your machine.) These types require the following amounts of storage.
  2776. REAL: 4 bytes
  2777. LONGREAL: 8 bytes
  2778. Enumeration types are represented as unsigned binary (ordinal) numbers:
  2779. <= 256 values: 1 byte
  2780. > 256 values: 2 bytes
  2781. BOOLEAN: 1 byte
  2782. CHAR: 1 byte
  2783. Absolute pointer types occupy 4 bytes. The first two bytes hold an offset value and the last two bytes hold a segment value. NIL is represented as (0,0). Based pointers occupy 2 bytes, which hold an offset.
  2784. FAR procedure variables are represented as absolute pointers to the first instruction of the procedure’s code. NEAR procedure variables are represented as 16-bit offsets within the applicable code segment.
  2785. Sets are represented as packed bit-maps with one bit for each potential member in the element type, say [ 0 . . N]. The number of bytes required to represent a set is given by 1+ (N DIV 8). For example, if you have a set which can have up to 100 elements, you need 13 bytes — that is, (1 + 100 DIV 8) —to represent this set. The set element E, where (0 <= E <= N) is represented by bit number E MOD 8 in byte number E DIV 8. The formula assumes you start counting with byte 0 and with bit 0.
  2786. Elements of arrays are stored in consecutive memory locations, and ordered according to increasing indices. The total array size is the size of a single element multiplied by the number of elements.
  2787. Fields of records are likewise stored in consecutive memory locations, and are ordered as they appear in the type declaration. Each field is stored according to its own type. The total record size is the sum of sizes of the individual fields. Variant record parts are special: the fields of different alternatives are overlayed (share storage). The total size of a variant part is the sum of the field sizes of the biggest alternative.
  2788. Example:
  2789. TYPE R = RECORD
  2790. Fl: INTEGER; (* Bytes 0-1 *)
  2791. CASE F2: BOOLEAN OF (* Byte 2 *)
  2792. 1 FALSE: F3, (* Byte 3 *)
  2793. F4, (* Byte 4 *)
  2794. F5: CHAR; (* Byte 5 *)
  2795. 1 TRUE: F6: CARDINAL; (* Bytes 3-4 *)
  2796. END
  2797. F7: SET OF [0..20]; (* Bytes 6-8 *)
  2798. END; (* SIZE ( R ) = 9, VSIZE( R.F6 ) = 5
  2799. This record requires nine bytes:
  2800. • two bytes (0-1) for field Fl
  2801. • one byte (2) for field F2
  2802. • three bytes (3-5) for fields F3, F4, and F5 together
  2803. • three bytes (6-8) for field F7
  2804. Note that field F6 is subsumed by the larger storage allocated for the fields when F2 is FALSE.
  2805. Calling Conventions
  2806. This discussion of the calling conventions used in TopSpeed Modula-2 code files assumes familiarity with the 8086-architecture. We will refer to the registers by the following names: AX(, AL), BX, CX, DX, SI, DI, BP, SP, CS, SS, DS, ES, IP, and Flags. For most programming tasks, you won’t need to be concerned with these conventions, since the default conventions will suffice.
  2807. The Stack Frame
  2808. Procedure activation makes use of the hardware stack (defined by registers SS and SP) for several purposes:
  2809. • Passing parameters.
  2810. • Saving return addresses.
  2811. • Saving registers which are used and must be preserved.
  2812. • Saving 8087 contents if not enough 8087 stack space is left for local floating point computations.
  2813. • Building ‘displays’ for accessing variables local to surrounding procedures.
  2814. • Storing local variables (whether user or compiler generated).
  2815. • Storing copies of value open array parameters, so they can be modified without modifying the actual parameters.
  2816. • Saving the process priority of the caller.
  2817. The parameters are pushed onto the stack by the calling procedure; the rest of the information on the stack is built by the called procedure on entry. The BP register points to the base of the stack-frame, and is used to access the local variables and parameters.
  2818. The general picture is:
  2819. old SP -*• Higher addresses
  2820. parameters Actual parameters
  2821. retum-CS retum-IP Return segment for FAR
  2822. Return offset
  2823. new BP —>
  2824. new SP —> saved BP display-BPs local variables local temps saved registers value-copies priority saved 8087 Caller’s BP
  2825. BPs of enclosing procedures Local user variables
  2826. Local anonymous variables
  2827. Caller’s registers
  2828. Copies of array parameters Saved (process) priority Caller’s 8087-contents
  2829. Lower addresses
  2830. Only the parts required are actually built; for very simple procedures, saving BP will be sufficient.
  2831. When returning, a procedure will restore the stack and preserved registers (see the $C directive) to their state before the call. This restoration includes popping the space used by the parameters.
  2832. Parameter Passing
  2833. Parameters are pushed onto the stack in the order they appear in the procedure dec­laration. Precisely what is pushed depends on the corresponding formal parameter’s type and whether it is a VAR parameter or not.
  2834. All VAR parameters and any open array parameters are passed by reference. That is, the full segment-offset address for the parameter or array is pushed, and the procedure uses this address to access the storage for the actual parameter. Such a parameter takes up 4 bytes, regardless of the parameter’s base type.
  2835. Value parameters, except open arrays, are passed by pushing the actual value of the parameter onto the stack. The space taken up is determined by the parameter’s type, except that any 1-byte type occupies 2 bytes when pushed.
  2836. For open array value parameters, the procedure will optionally make a copy of the passed value into local storage, and will modify the address passed to point at the copy rather than at the original array. (See the $V- directive in “Directives (in source text)” page 133.)
  2837. For open array parameters (whether VAR or not), the caller also will push the (2-byte) size (in bytes) of the actual array. This information will be pushed before the address of the array.
  2838. Function Results
  2839. Results from functions are returned in various ways, depending on the type of the value being returned.
  2840. REALS and LONGREALs are returned on the top of the 8087 stack.
  2841. Scalar values, small sets, pointers, and procedure variables are returned in 8086 registers according to their size: 1 byte in AL, 2 bytes in AX, and 4 bytes in DX:AX.
  2842. Sets of other sizes, arrays, and records are returned on the stack under the parameters: before pushing parameters, the caller will allocate the required space.
  2843. Options (on Command Line)
  2844. When invoking the compiler, you can use options to specify what you want from the compiler. You can invoke any of these options on the DOS command line; you can also specify some of them from menus when compiling in the TopSpeed Modula-2 environment. To specify an option from the appropriate menu, select the Options Compiler menu, then set entries to the desired values. See Chapter 5 for more details about the TopSpeed Modula-2 options.
  2845. When you invoke the options from the command line, you must precede the name of the file you want to compile with /C, to tell the system that you want to invoke the compiler on the file that follows as the next command line argument. (Command line options are not case sensitive. Thus, /C and /c are equivalent.)
  2846. Example:
  2847. M2 /C MyMain /ML
  2848. The compiler options are:
  2849. /B This option lets you specify whether compiler directives that do checking at run-time are ON or OFF. This option affects only the default settings for these options. You can override these settings with directives in the source code, as described in the next section.
  2850. /D If selected, the compiler generates a debug information file for the module being compiled. This file is required by the TopSpeed Modula-2 source level debugger.
  2851. /F Allows file names to be different from module names.
  2852. /H Used together with Make (see the /M option below) to show which files need recompilation.
  2853. /J Suppresses smart linking — that is, the automatic generation of libraries. When this directive is used, non-library OB J-files are created, meaning that everything in the file will always be included when linking. Although this results in larger, slower files, this file format is necessary for some linkers.
  2854. /L Generates a screen log containing information about compilation speed for definition and for implementation modules.
  2855. /M Invokes the Make utility. The file specified to the compiler must contain a mam module. Make will, based on the imports specified in that file, find all modules required by the program. For each of these, Make checks whether the corresponding OBJ-file is up-to-date, based on the time/date values of the files used. Modules that need it are recompiled. Only files whose module implementation is accessible are considered. See “Making a Program,” page 69, for more information about Make.
  2856. /N Include line numbers in the OBJ-file. This enables a program such as a de­bugger to determine the correspondence between code addresses and source program lines.
  2857. /O Where possible, the compiler will try to produce the fastest code it can. To do this, the compiler will sometimes reorganize expressions, in order to speed up their evaluation. The /O option disables reorganization of expressions. This ensures that expressions are evaluated left-to-right, but results in suboptimal code.
  2858. /P Tells the compiler to display the name of each procedure as it is compiled, to indicate progress.
  2859. /R Used together with Make to recompile everything, regardless of checks. This option may be necessary because the Make facility only considers the actual time/dates values of files; it does not read OBJ-files to find the version-records.
  2860. /V Makes all variables volatile: instead of trying to keep variables in registers, they are kept in memory. This can help when debugging. This option results in slower code than if registers are used.
  2861. Directives (in Source Text)
  2862. Directives, which appear in the source text, are used to specify various details about how code should be generated. Directives are specified in special comments, whose first character is $ after the comment opening characters, (*. Each directive is indicated with a single letter, optionally followed by a parameter; several directives can be given in a single comment by separating them with commas.
  2863. Most of the directives are flags. In such cases, the parameter is a + or - to indicate whether to enable the feature or not. The flags can be reset to their value before the most recent use of the directive by specifying the flag with = as the parameter.
  2864. Example:
  2865. (*$V-,M mycode,N*) (* set $V feature to regardless of current value *) .... (* code here *)
  2866. (*$V=,F*) (* restore $V feature to value it had before $V- *)
  2867. Other directives require a number or a name as their parameters — for example,
  2868. M ntycode
  2869. above. (Notice that the $ appears only once in the comment line.) Finally, a few directives are set simply by including the directive, without a parameter.
  2870. Directives take effect from the spot in which they first occur, and remain in effect until the end of the source file or until revoked by another directive. The current setting for a directive is sampled at the place where its value is relevant.
  2871. If certain directives are specified in a module definition, their settings override any settings in the module implementation. These directives are: C,G,F,K,N.
  2872. The following list summarizes the compiler directives that are available in TopSpeed Modula-2. Where applicable, default values are specified in boldface.
  2873. $A+/- Enable/disable aliased behavior on global variables. The compiler will assume that variables declared with the directive disabled cannot be accessed directly and indirectly at the same time.
  2874. $B+/~ Include/exclude a control-break handler in the program. If included, pressing |ctrl|||Breakj] will terminate the program. The handler can be dynamically enabled and disabled with library procedures. The directive must be in the main module.
  2875. $C h Specifies which registers will be preserved by procedures. The hexadec­imal number, h, specifies the registers, based on the following values:
  2876. AX=1, CX=2, DX=4, BX=8, DS=10, ES=20, SI=40, DI=80.
  2877. The BP register is always preserved. The default configuration is
  2878. $D n
  2879. $E+/-
  2880. $F
  2881. $G+/~
  2882. $H+/-
  2883. $1+/-
  2884. $J+/-
  2885. $K+/-
  2886. $M n
  2887. $N
  2888. $O+/-
  2889. FO = DS+ES+SI+DI
  2890. This would be specified as:
  2891. (*$C FO*)
  2892. Specifies the name, n, of the data segment in which to put the global variables declared by the module. The default is to use the module name. In any case, the name specified is prefixed by D_. If used, this directive must appear before the MODULE keyword in both definition and implementation files.
  2893. Enable/disable relaxed alias treatment of variant records. Because of overlapping, the compiler will normally consider fields of variant records volatile, causing them to be kept in memory.
  2894. Procedures will be called with FAR calls. Likewise, procedure types are 32-bit. This is the default, and applies only to global procedures; local procedures are always called with NEAR calls.
  2895. Enable/disable module prefixes in external names. Enabling such pre­fixes guarantees that external names will be unique.
  2896. Enable/disable treating constant aggregates as variables, thereby allow­ing them to be modified. This is possible because the values are in mem­ory anyway.
  2897. Enable/disable index checking. If enabled, accessing a non-existent ar­ray element will produce a run-time error. All variables are assumed to hold legal values corresponding to their type (see $R below). Likewise, type transfer on indices is assumed not to cause problems.
  2898. Enable/disable interrupt procedures, by generating IRET returns instead of the usual RET instruction.
  2899. Enable/disable the C language calling convention for procedures. This specifies that caller (not called) pops parameters. Across calls, the DS register is set to the group named ‘DGROUP.’
  2900. Specifies the name, n, of the code segment in which to put code. The default is to use the module name. In any case, the name is prefixed by C_. When used, this directive must appear before the MODULE keyword in both definition and implementation files.
  2901. When this directive is used, procedures will be called with NEAR calls. This requires callers to be in the same code segment. With this directive, procedure types are 16-bit.
  2902. Enable/disable overflow checking on whole number operations. If this directive is enabled, a numeric overflow will cause a run-time error.
  2903. $P+/~ Enable/disable generating external names for local procedures. En­abling eases debugging but can cause name clashes.
  2904. $Q+/- Enable/disable procedure tracing. If enabled, procedures will execute an INT 60H instruction on entry and and INI 61H on exit. Handlers for these interrupts must be installed explicitly (see “Interrupt Handlers,” page 140). Library module ProcTrace enables you to do this.
  2905. $R+/- Enable/disable subrange checking. If enabled, a run-time error is gen­erated by assignment or parameter passing if the value is outside the bounds of the receiver’s type.
  2906. $S h The hex number, h, specifies the amount of stack allocated for the program. If used, this directive must be in the main module.
  2907. $S+/- Enable/disable stack overflow checking. If this directive is enabled, a run-time error is generated if stack space is exhausted.
  2908. $V+/~ Enable/disable copying of open array value parameters. Disabling such copying increases efficiency but is potentially incorrect.
  2909. $W+/- Enable/disable the use of volatile variables. Volatile variables are not kept in registers across statements. The ability to use volatile variables can be essential if concurrent processes communicate via shared global variables, and can make debugging easier. The /V command line option selects this globally.
  2910. $X+/~ Enable/disable 8087 stack spilling for procedures. Spilling is necessary if nested function calls exhaust the 8087 stack. Spilling involves saving excess values from floating point computations on the hardware stack — because there is no longer room on the 8087 stack.
  2911. $Y+/- Enable/disable coinciding variant fields in a record. If enabled, it is legal to use the same name for fields in distinct alternatives, provided that these fields have the same type and are at the same offset in the record.
  2912. $Z+/- Enable/disable checks for dereferencing of NIL pointers, which then generate a run-time error. When the feature is enabled, all local variables are initialized to zero. If the feature is enabled in the main module, all global variables are also zeroed.
  2913. Interface to Other Languages
  2914. Since the compiler generates standard OB J-files, it is possible to link these files with code written in other languages and compiled with other compilers.
  2915. However, anything called from Modula-2 must be declared in Modula-2 terms. This means that module definitions (DEF-files) must be written, even for the parts that are not implemented in Modula-2. The actual OBJ-file may be generated by a different compiler.
  2916. For this to work, the different parts of the program must agree on the run-time structure of the total program. So, you’ll need to understand the run-time structure of both Modula-2 and the other languages being used.
  2917. Inspecting the MAP-file produced by the linker can be a big help when fitting the pieces together. This file is also useful simply as a source to help understand how running programs are put together. The documentation for the TopSpeed Modula-2 TechKit provides information about this, and also includes an example of how to create and use a module written in assembler.
  2918. Controlling Run-Time Program Structure
  2919. You can control the Modula-2 run-time structure by using several of the directives summarized in the preceding section:
  2920. $D selects the segment where data goes.
  2921. $M selects the segment where code goes.
  2922. $G disables module name prefixing.
  2923. $N produces NEAR procedures.
  2924. $F produces FAR procedures.
  2925. $C selects which registers are preserved by procedures.
  2926. $K follows C calling conventions.
  2927. Segments, Groups and Classes
  2928. The concept of a segment is fundamental to the 8086, and it is extended by the concepts of group and class in the OBJ-language.
  2929. An item is the fundamental, undivisible piece of code or data, and is sometimes called a “logical segment.”
  2930. A segment is a collection of items whose total size is less than 64K bytes; a segment has a name. Any item belongs to one segment.
  2931. A group is a collection of segments, whose total size is still less than 64K bytes; a group also has a name. Any segment belongs to at most one group, but need not belong to any.
  2932. When linking a set of OBJ-files, all the items must be arranged in physical memory in a way that ensures that items of the same segment or group are within the same 64K of memory.
  2933. Segments may be qualified with the concept of named classes. These are used to specify preference when arranging the items: items with the same class name are placed adjacent to each other; within classes, items of the same segment are placed adjacent to each other. Classes take precedence, so if two items have the same segment name but different class names, they are not even considered to belong to the same 64K segment.
  2934. The linker will order classes in the sequence it encounters them when linking. The compiler utilizes this to achieve the correct storage layout of the final program: first comes code (classes CODE, FCODE), then global data (MJDATA), then stack data (STACK), and finally heap data (HEAP).
  2935. For each module, the compiler will generate four segments and one group with names derived from the module name. The segments are:
  2936. C_module contains code for procedures.
  2937. K_module contains structured constants (like strings).
  2938. S_module contains special segment constants.
  2939. D_module contains global variables.
  2940. and the group is:
  2941. G_module group containing the C_, K_, and S_ segments.
  2942. Segments can be renamed with compiler directives: $D applies to the D_ segment, $M to the C_, K_ and S_ segments and the G_ group. This control can be used to make different modules use the same segments: for example, using the compiler directive (*$D DATA*) in all modules will put all global data in the same 64K segment.
  2943. A further segment, INITCODE, contains initialization code for modules and the code for the main module. If (*$M CODE*) is specified, segments INITCODE and C_CODE are put in a group called G_CODE, enabling all code to reside within the same 64K group.
  2944. Because there is a single data segment and code group for each module, the code and global data are limited to 64K bytes for each module. A complete program can have an arbitrary amount of code and data.
  2945. Addressing Items
  2946. A physical address consists of two parts: a segment address and an offset. All items in the same group or segment have the same segment address but different offsets.
  2947. To address an item, a segment register must contain its segment address. This (im­plicit) register is combined with an explicit offset value to address the item. FAR calls, on the other hand, specify both the segment address and the offset explicitly.
  2948. Thus, distinct objects can be accessed without reloading a segment register only if they belong to the same segment or group. Similarly, a procedure can only be called with a NEAR call if the caller is within the same (code) segment (so the CS register does not have to be changed).
  2949. Note: Whether a procedure is considered NEAR or FAR ($N and $F directives, respectively) is determined by the procedure’s RETum instruction. The determination has nothing to do with the segment the procedure is in or with what else is in that segment.
  2950. Naming Conventions
  2951. The various OBJ-files refer to each other’s items by means of public external names. These names must be unique and distinct.
  2952. The compiler forms the external name of an item by prefixing its source code name with the name of the module in which the item is declared. A $ or @ separates these two names: $ is used for FAR procedures, and @ is used for NEAR procedures and for data. Such prefixing can be disabled with the $G directive.
  2953. Items declared in local modules immediately within global modules are prefixed with the names of both the global and local modules separated by @.
  2954. Example:
  2955. (*$D XYZ*)
  2956. DEFINITION MODULE M;
  2957. V: INTEGER;
  2958. PROCEDURE F; (* (* (* Segments C_M, External name External name K M, M@V M$F S M, D XYZ *)
  2959. *)
  2960. *)
  2961. (segment (segment D M) C_M)
  2962. (*$N,G-*) PROCEDURE Nl; (* External name Nl (segment C _M) *)
  2963. (*$G+*)
  2964. PROCEDURE N2; (* External name M0N2 (segment C_ _M) *)
  2965. END M.
  2966. 8087 Support
  2967. The compiler generates 8087 instructions for floating point operations. At run-time these instructions either will be executed by an actual 80x87 chip or they will be emulated by software.
  2968. The emulator is included if any part of the program uses floating point instructions. At run-time the emulator will check if an 80x87 chip is present. If so, the emulator will patch the emulator calls back to 8087 instructions. The same EXE-file can thus be run on any machine at maximum possible speed.
  2969. Normally 80x87 exceptions are suppressed. However, you can install exception han­dlers by just importing the FloatExc module (see Chapter 8).
  2970. Interrupt Handlers
  2971. It is possible to write interrupt handlers in Modula-2, though it should not be at­tempted without a thorough understanding of the 8086 and of MS-DOS.
  2972. An interrupt handler is written as a Modula-2 procedure; the $ J+ directive gives it a proper return instruction, and the $C FF directive makes it save all registers. The $w+ directive can be used to keep shared global variables in memory.
  2973. Hardware interrupts can be enabled or disabled with the El and DI procedures from the SYSTEM module (see Chapter 8).
  2974. The interrupt handler is installed by assigning its address to one of the interrupt vectors in low memory. For more details on interrupt vectors, consult references on DOS or on the 80x86 chip.
  2975. Example:
  2976. MODULE Int ;
  2977. VAR Prtlnt [0:5*4]: ADDRESS; (* Interrupt 5: print-screen *) Oldlnt: ADDRESS;
  2978. (*$W+*)
  2979. Flag: BOOLEAN;
  2980. (*$W-*)
  2981. (*$J+,C FF*)
  2982. PROCEDURE Handler ;
  2983. BEGIN
  2984. END Handler;
  2985. (*$J-,C F0*)
  2986. BEGIN
  2987. Oldlnt := Prtlnt;
  2988. Prtlnt := ADR( Handler );
  2989. Prtlnt := Oldlnt;
  2990. END Int.
  2991. If you’re very adventurous, the TechKit contains a module you can use to create terminate-and-stay-resident (TSR) programs, using the 031H MS-DOS call. A sample TSR program is also included. When creating such a program. Break handling must be disabled (by setting $B-), and the stack can be kept small. Use the $S directive to do this — for example:
  2992. $s 500
  2993. Finally, the heap requirements of the EXE-file must be trimmed using the supplied SETHEAPS utility, which is included in the TechKit; otherwise there will be no space left for other programs.
  2994. Chapter 8
  2995. The TopSpeed
  2996. Modula-2 Library
  2997. Introduction
  2998. This chapter describes the library modules supplied with the TopSpeed Modula-2 compiler. TopSpeed Modula-2 comes with 12 different modules, containing more than 250 procedures in all.
  2999. Most of these modules are ordinary Modula-2 modules. They all have a Modula-2 definition part, but some of the implementation parts are written in assembler.
  3000. The following sections of this chapter describe each module in detail, but first an overview of the modules is presented. How the modules interrelate is also described.
  3001. The modules can be partitioned into levels of successively more abstract functions, where each level will make use of the lower levels.
  3002. Level MODULE
  3003. System
  3004. Assembly
  3005. Utility :SYSTEM
  3006. : AsmLib, MATHLIB
  3007. : Str, Lib, Storage, Process, Graph, FloatExc, Proc- Trace
  3008. IO : IO, FIO
  3009. Window : Window
  3010. Library Overview
  3011. SYSTEM
  3012. The SYSTEM module is a low-level module that contains compiler dependent features, such as data types of special interest in this implementation. Some of the procedures in this module are built-in to the compiler — that is, code for these procedures will be generated inline rather than as calls to the procedures.
  3013. SYSTEM covers:
  3014. • support for the specifics of the 8086 family of processors
  3015. • support for concurrent processes
  3016. SYSTEM does not make use of other modules.
  3017. AsmLib
  3018. AsmLib is an auxiliary module which you need not use directly; it is there to keep all the various assembler bits in one module. Some of the procedures that appear to be defined in other modules are actually from the AsmLib module. This is achieved by means of TopSpeed Modula-2’s alias-concept (see chapter 6).
  3019. AsmLib uses SYSTEM.
  3020. MATHLIB
  3021. MATHLIB is implemented in assembler.
  3022. MATHLIB covers:
  3023. • trigonometric and hyperbolic functions on reals
  3024. • logarithmic functions on reals
  3025. • conversion of reals to/from binary coded decimals
  3026. • 8087 specifics
  3027. MATHLIB uses SYSTEM.
  3028. Str
  3029. The Str module deals with string handling.
  3030. Str covers:
  3031. • string concatenation, appending, insertion, deletion
  3032. • string comparison
  3033. • string searching, matching
  3034. • string conversion to and from numeric types
  3035. Str uses AsmLib and MATHLIB.
  3036. Lib
  3037. This module contains a collection of useful procedures. Parts of it are written in Modula-2 and parts of it are aliases into the AsmLib module.
  3038. Lib covers:
  3039. • sorting
  3040. • random number generation
  3041. • DOS-interrupt calls
  3042. • command line access
  3043. • memory block operations
  3044. • long jumps
  3045. • address arithmetic
  3046. • break and error handling
  3047. • sound procedures
  3048. Lib uses SYSTEM, AsmLib, Str and Storage.
  3049. Storage
  3050. The Storage module maintains dynamic heaps of storage.
  3051. Storage provides:
  3052. • allocation and deallocation of storage
  3053. • information about storage availability
  3054. Storage uses SYSTEM.
  3055. Process
  3056. This module implements a multi-process manager with time-sliced scheduling and process synchronization.
  3057. Process covers:
  3058. • starting up processes
  3059. • synchronization by means of semaphores
  3060. Process uses SYSTEM, Lib, Storage.
  3061. Graph
  3062. The module Graph implements simple graphics. The module supports the following graphics boards: CGA, EGA, VGA, Hercules, and AT&T.
  3063. Graph covers:
  3064. • selecting a graphics board
  3065. • selecting screen modes
  3066. • writing and reading of single pixels
  3067. • drawing of lines and circles
  3068. • drawing of filled circles and polygons
  3069. Graph uses SYSTEM, Lib.
  3070. FIO
  3071. This module allows access to MS-DOS files. Input/output to files can either be un­formatted binary data, or formatted data to text files. Files are usually disk-files, but can be any device that MS-DOS allows.
  3072. FIO covers:
  3073. • creating, deleting, renaming, opening, closing files
  3074. • reading, writing, seeking on files
  3075. • creating, deleting, changing directory
  3076. • directory scanning
  3077. • reading and writing of characters, booleans, integers, cardinals, reals, strings
  3078. FIO uses SYSTEM, AsmLib, Lib, Str.
  3079. IO
  3080. The IO module provides formatted input/output to the standard I/O devices (i.e. screen and keyboard). Input and output can be redirected. IO also contains functions for direct keyboard input.
  3081. IO covers:
  3082. • reading and writing of characters, booleans, integers, cardinals, reals, strings
  3083. • redirection to any device
  3084. • reading characters directly from keyboard
  3085. • testing for key-ready
  3086. IO uses SYSTEM, Lib, Str, FIO.
  3087. Window
  3088. The Window module allows you to define areas of the screen for output. These areas are called windows, and may be displayed simultaneously, possibly overlapping, on the physical screen.
  3089. Window covers:
  3090. • creating, disposing, opening, closing windows
  3091. • setting frame, color, title on windows
  3092. • rearranging the size, position, layering of windows
  3093. • cursor control inside windows
  3094. • inserting and deleting lines in windows
  3095. • palette windows
  3096. • writing to windows using the IO module
  3097. Window uses SYSTEM, AsmLib, Lib, Str, Storage.
  3098. FloatExc
  3099. The module FloatExc supports 8087 exception handling.
  3100. FloatExc covers:
  3101. • enabling/disabling of 8087-exceptions.
  3102. FloatExc uses SYSTEM, Lib, MATHLIB, Str.
  3103. ProcTrace
  3104. The ProcTrace module lets you trace procedure calls and to monitor variable values during program execution.
  3105. ProcTrace covers:
  3106. • monitoring procedure calls
  3107. • determining the current procedure
  3108. • monitoring the value of variables
  3109. ProcTrace uses SYSETM, Lib, IO, FIO, Str.
  3110. This concludes the general introduction to the library. More specific descriptions are given in the following sections.
  3111. How to Use the Library Reference
  3112. Rather than describing the procedures in alphabetical order, a description of the individual procedures can be found under the module where they belong. A list of all the procedures can be found on page 246.
  3113. When you read a description of a particular procedure, you should also read the general remarks in the section to which the procedure belongs.
  3114. MODULE Str
  3115. This section deals with the string handling functions, which include string manipu­lation, as well as conversions from strings to numbers and vice versa.
  3116. The Modula-2 language does not have a built-in string type. Strings are implemented as the type ARRAY [0. .N] OF CHAR. When a string literal is assigned to such an array type, it will be zero-terminated by appending the character value CHR(OC) to the string. However, this is not the case if the length of the string literal is equal to the maximum length of the destination string.
  3117. All procedures that return a string (via a VAR parameter) will zero-terminate that string unless the length of the result string is greater than or equal to the length of the destination string. If the length of the result string is greater than the length of the destination string, the result string is truncated.
  3118. Positions in the string are indexed starting with 0. Thus, the second character in the string has position 1.
  3119. General String Procedures
  3120. Append
  3121. PROCEDURE Append(VAR R: ARRAY OF CHAR; S: ARRAY OF CHAR);
  3122. Appends the string S to R. If the combined length of S and R is longer than the maximum length of S, only as much of R is appended as will fit in S.
  3123. Example:
  3124. (* si, s2 are strings *)
  3125. si := 'ex';
  3126. s2 := 'ample';
  3127. Append( si, s2); (* Bl now = 'example' *)
  3128. Caps
  3129. PROCEDURE Caps (VAR S: ARRAY OF CHAR) ;
  3130. Converts lower case letters in string S to upper case letters. Other letters are left unchanged.
  3131. Example:
  3132. s := 'example';
  3133. Caps( s); (* s now = 'EXAMPLE' *)
  3134. Compare
  3135. PROCEDURE Compare(SI,S2: ARRAY OF CHAR) : INTEGER;
  3136. Compares the strings SI and S2 lexicographically. The function compares characters from left to right until a (possible) difference is found. The result is indicated the following way:
  3137. Value Condition
  3138. -1 if SI is less than S2.
  3139. 0 if SI equals S2 — that is, no differencs was found.
  3140. 1 if SI is greater than S2.
  3141. Example:
  3142. result Compare( 'lowercase', 'uppercase');
  3143. (* result = -1, since 'lowercase' precedes 'uppercase' *)
  3144. result := Compare( 'lowercase', 'Lowercase');
  3145. (* result = 1, since '1' comes later than 'L' lexicographically *)
  3146. Concat
  3147. PROCEDURE Concat(VAR R: ARRAY OF CHAR; S1,S2: ARRAY OF CHAR);
  3148. Concatenates SI and S2, and returns the result in R. The second string is truncated if the concatenated string becomes longer than the Length ( R).
  3149. Example:
  3150. (* strl, str2, catstr are strings *)
  3151. strl := 'ex';
  3152. str2 := 'ample';
  3153. Concat( catstr, str2, strl); (* catstr now = 'ampleex' *)
  3154. Copy
  3155. PROCEDURE Copy (VAR R: ARRAY OF CHAR ; S: ARRAY OF CHAR);
  3156. Copies the string S to R. If S is too long to fit into R, then the copy of S is truncated.
  3157. Example:
  3158. strl := 'example';
  3159. str2 := 'ample';
  3160. (* strl now = 'ample' *)
  3161. Copy( strl, str2) ;
  3162. Length
  3163. PROCEDURE Length(S: ARRAY OF CHAR) : CARDINAL;
  3164. Returns the length of the string S, not including the zero-terminator if present.
  3165. Example:
  3166. result := Length('hello');
  3167. (* result now = 5 *)
  3168. Pos
  3169. PROCEDURE Pos(S,P: ARRAY OF CHAR) : CARDINAL;
  3170. Returns the position (starting from 0) of the first occurrence of the substring P in the string S. If P is not found in S the result is MAX(CARDINAL).
  3171. Example:
  3172. result :■ Pos( 'example', 'ample'); (* result = 2 *)
  3173. result :■ Pos( 'source string', 'not in source—'); (* result = 65535 *)
  3174. Slice
  3175. PROCEDURE Slice (VAR R : ARRAY OF CHAR; S : ARRAY OF CHAR; P,L : CARDINAL);
  3176. R is assigned a slice of string S. This slice goes from position P to P+L-l. If P+L-l is greater than Length (S), R is assigned the slice from P to Length (S). If P is greater than Length (S) or L is 0, then R becomes a null string (i.e. a string of length 0).
  3177. Example:
  3178. Slice(si, 'overused', 4, 2);
  3179. (* si = 'us' *)
  3180. (* si = 'used' *)
  3181. (* si = null string *)
  3182. Slice(si, 'overused', 4, 12);
  3183. Slice(si, 'overused', 12, 4);
  3184. Item
  3185. PROCEDURE Item(VAR R : ARRAY OF CHAR; S : ARRAY OF CHAR; T : CHARSET; N : CARDINAL);
  3186. Consider the string S divided into (nonempty) substrings which are separated by elements from the set T. Item returns the Nth of these substrings (counting from 0). The result goes in R.
  3187. Example : The following call of Item
  3188. si : = "aa bb,cc dd"; Item(s2, si, CHARSET{' 2) ;
  3189. will assign “cc” to s2.
  3190. ItemS
  3191. PROCEDURE ItemS (VAR R : ARRAY OF CHAR;
  3192. S : ARRAY OF CHAR; T : ARRAY OF CHAR; N : CARDINAL);
  3193. This procedure works like Item. The only difference is that in Items the delimiters, given by T, are specified as an ARRAY OF CHAR as opposed to a CHARSET in Item.
  3194. Example:
  3195. TYPE SmArr = ARRAY [ 0 .. 3] OF CHAR;
  3196. CONST delims = SmArr ( CHR(IO), CHR(13), CHR(26), ' ');
  3197. VAR Bl, s2 : ARRAY [ 0 . . 40] OF CHAR;
  3198. si : = ”aa bb cc dd";
  3199. ItemS( s2, si, delims, 3);
  3200. will assign “dd” to s2.
  3201. Insert
  3202. PROCEDURE Insert(VAR R : ARRAY OF CHAR;
  3203. S : ARRAY OF CHAR;
  3204. P : CARDINAL);
  3205. Inserts string S into string R at position P. If P is greater than Length (R), then S is inserted at position Length (R).
  3206. Example: The following example shows how insert new material in an existing
  3207. string:
  3208. si := "abcdefg";
  3209. Insert(si,"xyz",3); (* si now = "abcxyzdefg *)
  3210. Delete
  3211. PROCEDURE Delete(VAR R: ARRAY OF CHAR; P,L: CARDINAL);
  3212. Deletes a sequence of L characters in the string R starting at position P. Delete has no effect if P is greater than Length (R).
  3213. Example:
  3214. si := "abcdefg"; Delete(si,3,3); (* Bl now = "abcg" *)
  3215. si := "abcdefg"; Delete(si,3,7); (* Bl now = "abc" *)
  3216. si := "abcdefg"; Delete(si,7,3); (* sl now = "abcdefg" *)
  3217. Match
  3218. PROCEDURE Match(Source,Pattern: ARRAY OF CHAR) : BOOLEAN;
  3219. Returns TRUE if the string Source matches the string Pattern. The pattern may contain any number of wild characters **’ and *?’. The *?’ character matches any single character, **’ matches any sequence of characters (including a zero length sequence).
  3220. Example:
  3221. VAR IsAMatch : BOOLEAN;
  3222. IsAMatch := Match( "*m?t*i*", "Automatic");
  3223. returns TRUE.
  3224. Conversion Procedures
  3225. This section describes procedures to do conversions from numbers to strings and vice versa.
  3226. A string that represents a number may start with a sign ('+’ or however is not allowed for CARDINAL numbers. No leading or trailing spaces are allowed in the string.
  3227. A string resulting from a conversion will contain a sign only if the number is negative. The string contains no leading or trailing spaces.
  3228. All the conversion procedures have a BOOLEAN result parameter, OK, which is set to TRUE if the conversion succeeded, or FALSE otherwise.
  3229. Procedures that convert between strings and integer or cardinal numbers take a pa­rameter, Base, which denotes the base (normally 10) used in the conversion. Base should have a value in the range 2 to 16. The hexadecimal letters *A’..‘F’ are used in numbers when Base is larger than 10. No H is added to hexadecimal numbers.
  3230. IntToStr
  3231. PROCEDURE IntToStr( V : LONGINT;
  3232. VAR S : ARRAY OF CHAR;
  3233. Base : CARDINAL;
  3234. VAR OK : BOOLEAN);
  3235. Converts the LONGINT value V into a string representation. OK is set to FALSE if the string S is too short to hold the converted value.
  3236. Example:
  3237. VAR si : ARRAY[ 0..20] OF CHAR;
  3238. Done : BOOLEAN;
  3239. IntToStr( -1234567, si, 8, Done); (* si = "-4553207" *)
  3240. IntToStr( -1234567, si, 10, Done); (* si = "-1234567" *)
  3241. IntToStr( -1234567, si, 16, Done); (* si = "-12D687" *)
  3242. CardToStr
  3243. PROCEDURE CardToStr( V : LONGCARD;
  3244. VAR S : ARRAY OF CHAR;
  3245. Base : CARDINAL;
  3246. VAR OK : BOOLEAN);
  3247. Converts the LONGCARD value V into a string representation. OK is set to FALSE if the string S is too short to hold the converted value.
  3248. Example:
  3249. VAR si : ARRAY[ 0..20] OF CHAR;
  3250. Done : BOOLEAN;
  3251. CardToStr( 1234567, si, 8, Done); (* si = "4553207" *)
  3252. CardToStr( 1234567, si, 10, Done); (* si = "1234567" *)
  3253. CardToStr( 1234567, si, 16, Done); (* si = "12D687" *)
  3254. RealToStr
  3255. PROCEDURE RealToStr (
  3256. V : LONGREAL;
  3257. Precision : CARDINAL;
  3258. Eng : BOOLEAN;
  3259. VAR S : ARRAY OF CHAR;
  3260. VAR OK : BOOLEAN);
  3261. Produces a string representation of the LONGREAL value V. Precision denotes the number of digits you want in the mantissa, and must lie in the range 1 to 17. (If Precision is outside this range its value will be adjusted to the nearest bound). If Eng is TRUE, engineering notation is used — that is, the exponent is displayed as
  3262. a multiple of three. If Eng is FALSE the mantissa is displayed with one significant digit before the decimal point. OK is set to FALSE if the string S is too short to hold the representation of V.
  3263. Examples:
  3264. RealToStr(123.45,7,FALSE,S,b); (* S now = "1.234500E+2" *)
  3265. RealToStr(0.12345,7,FALSE,S,b); (* S now = "1.234500E-1" *)
  3266. RealToStr(0.12345,7,TRUE,S,b); (* S now = "123.4500E-3" *)
  3267. FixRealToStr
  3268. PROCEDURE FixRealToStr(
  3269. V : LONGREAL;
  3270. Precision : CARDINAL;
  3271. VAR S : ARRAY OF CHAR;
  3272. VAR OK : BOOLEAN) ;
  3273. Produces a string representation of the LONGREAL value V. No exponent is given in this format (see RealToStr). Precision denotes the number of digits after the decimal point. OK is set to FALSE if the string S is too short to hold the representation of V, or if ABS (V) is larger than 1.0E18.
  3274. Examples:
  3275. FixRealToStr(0.12345,7,S,b); (* S now = "0.1234500" *)
  3276. FixRealToStr(123.4567,5,S,b); (* S now = "123.45670" *)
  3277. FixRealToStr(123.4567,2,S,b); (* S now = "123.46" *)
  3278. StrToInt
  3279. PROCEDURE StrToInt( S : ARRAY OF CHAR;
  3280. Base : CARDINAL;
  3281. VAR OK : BOOLEAN ) : LONGINT;
  3282. StrToInt takes a string S representing an integer value, and returns the corre­sponding LONGINT representation. Base denotes the base of the number currently in string form, and must lie in the range 2 to 16. OK is set to FALSE if the string S does not represent a LONGINT value.
  3283. Example:
  3284. VAR FInt : LONGINT; Done : BOOLEAN;
  3285. FInt := StrToInt( "-4553207", 8, Done); (* FInt = "-1234567" *)
  3286. FInt :» StrToInt( "-1234567", 10, Done); (* FInt = "-1234567" *)
  3287. FInt := StrToInt( "-12D687", 16, Done); (* FInt = "-1234567" *)
  3288. StrToCard
  3289. PROCEDURE StrToCard( S : ARRAY OF CHAR;
  3290. Base : CARDINAL;
  3291. VAR OK : BOOLEAN ) : LONGCARD;
  3292. StrToCard takes a string S, representing a cardinal value, and returns the corre­sponding LONGCARD representation. Base denotes the base used in the conversion, and must lie in the range 2 to 16. OK is set to FALSE if the string S does not repre­sent a LONGCARD value.
  3293. Example:
  3294. VAR FCard : LONGINT;
  3295. Done : BOOLEAN;
  3296. FCard := StrToCard( FCard := StrToCard( FCard :« StrToCard(
  3297. "4553207", 8, Done);
  3298. "1234567", 10, Done) "12D687", 16, Done);
  3299. (* FCard = "1234567" *)
  3300. (* FCard = "1234567" *)
  3301. (* FCard = "1234567" *)
  3302. StrToReal
  3303. PROCEDURE StrToReal( S : ARRAY OF CHAR;
  3304. VAR OK : BOOLEAN ) : LONGREAL;
  3305. StrToReal takes a string S representing a real value and returns the corresponding LONGREAL value. The syntax for valid REAL values can be found in chapter 6. OK is set to FALSE if S does not represent a real value.
  3306. Example:
  3307. VAR FReal : LONGINT;
  3308. Done : BOOLEAN;
  3309. FReal StrToReal(
  3310. FReal : = StrToReal(
  3311. FReal :« StrToReal(
  3312. "455.3207", Done);
  3313. "123456e7", Done);
  3314. "-0.1234567", Done)
  3315. (* FReal - "4.553207E+2" *) (* FReal » "1.23456E-2" *)
  3316. (* FReal - "-1.234567E-1" *)
  3317. MODULE Lib
  3318. The module Lib contains a number of general purpose procedures. These include: random number generation, data sorting, using DOS interrupts, producing sounds on the computer, and so forth.
  3319. Sorting
  3320. TopSpeed Modula-2 supplies two different sort procedures. These implement the quicksort and the heapsort algorithms. Quicksort is usually the fastest, but can be rather slow in the worst case (which is when the elements are already sorted). The running time of heapsort has a very small variance. Quicksort is a stable sorting algorithm, i.e. equal keys are not swapped, while heapsort is not stable.
  3321. QSort
  3322. TYPE
  3323. CompareProc = PROCEDURE( CARDINAL, CARDINAL ) : BOOLEAN;
  3324. SwapProc = PROCEDURE ( CARDINAL, CARDINAL ) ;
  3325. PROCEDURE QSort(N: CARDINAL; Less: CompareProc; Swap: SwapProc);
  3326. QSort performs a quicksort. The number of elements to be sorted is given by N. The elements are numbered from 1 to N. less is a function procedure which takes two CARDINAL parameters and returns the BOOLEAN result TRUE if the element specified by the first parameter is less than the element specified by the second parameter, swap is used to swap two elements specified by the parameters. You must provide procedures that perform the tasks carried out by less and swap.
  3327. Example:
  3328. MODULE SortArray; (* This module sorts an array *) IMPORT Lib;
  3329. VAR a : ARRAY [1..100] OF CARDINAL;
  3330. PROCEDURE less(11,12 : CARDINAL) : BOOLEAN;
  3331. BEGIN
  3332. RETURN a[il] < a[12);
  3333. END less;
  3334. PROCEDURE swap(11,12 : CARDINAL);
  3335. VAR tmp : CARDINAL;
  3336. BEGIN
  3337. tmp := a[ll]; a[il] := a[12]; a[12] := tmp;
  3338. END swap;
  3339. BEGIN
  3340. GetValues(a); (* assign values to a *)
  3341. Lib.QSort(100,less,swap); (* sort the array a *) END SortArray.
  3342. HSort
  3343. PROCEDURE HSort(N: CARDINAL; Less: CompareProc; Swap: SwapProc);
  3344. HSort performs a heapsort. See Qsort above for an explanation of the parameters.
  3345. You can also use the example under QSort to try HSort.
  3346. Random Number Generation
  3347. RANDOMIZE
  3348. PROCEDURE RANDOMIZE;
  3349. This procedure initializes the pseudorandom number generator, and should be called before you start calling the procedures RANDOM or RAND. If you do not call RAN­DOMIZE before using the other two procedures, the “random” behavior of your pro­gram will be the same each time you run the program.
  3350. RANDOM
  3351. PROCEDURE RANDOM (Range: CARDINAL) : CARDINAL;
  3352. Returns a random CARDINAL number in the range 0 to Range-1, inclusive.
  3353. Example:
  3354. VAR RVal : CARDINAL;
  3355. RVal := RANDOM( 10000);
  3356. returns a random CARDINAL value between 0 and 9999.
  3357. RAND
  3358. PROCEDURE RAND() : REAL;
  3359. Returns a random REAL number in the range: 0.0 <= result < 1.0.
  3360. Example:
  3361. VAR RVal : REAL;
  3362. RVal := RAND();
  3363. might return 0.569, for example.
  3364. Environment Procedures
  3365. You can access the DOS command line via the pointer variable CommandLine or via the procedures ParamStr and ParamCount.
  3366. TYPE
  3367. CommandType = POINTER TO ARRAY [0.. 126] OF CHAR;
  3368. VAR
  3369. CommandLine : CommandType;
  3370. The procedures listed below let you access the DOS environment and the command line.
  3371. Environment
  3372. PROCEDURE Environment(N : CARDINAL) : CommmandType;
  3373. Returns string number N in the DOS environment. The first string has number zero.
  3374. Example: The following statements illustrate the elements needed to call and
  3375. display a DOS environment string. The statemements assume that the appropriate modules have been imported.
  3376. VAR CLString : Lib.CommandType;
  3377. WhichString : CARDINAL;
  3378. CLString := Lib.Environment ( WhichString);
  3379. lO.WrStr ( CLString*);
  3380. Depending on your DOS environment and on the value of WhichString, the calls to Lib.Environment and to lO.WrStr might produce, for example:
  3381. PROMTT=$p$g
  3382. ParamCount
  3383. PROCEDURE ParamCount() : CARDINAL;
  3384. Returns the number of arguments on the command line. The program name is not counted as an argument. For example, if you call program pctest with the following command line:
  3385. pctest first second third fourth
  3386. ParamCount will return 4 as the number of arguments in the following call:
  3387. CardResult := ParamCount ();
  3388. ParamStr
  3389. PROCEDURE ParamStr(VAR S: ARRAY OF CHAR; N: CARDINAL);
  3390. Returns argument number N on the command line in the string S. The first argument has number one.
  3391. Example: With the command line shown in the example for ParamCount,
  3392. ParamStr ( argstr, 3);
  3393. returns “third” in string argstr.
  3394. Memory Block Operations
  3395. All procedures in this section perform some operation on a consecutive block of memory.
  3396. Move
  3397. PROCEDURE Move(Source,Dest: ADDRESS; Count: CARDINAL);
  3398. Copies a block of Count bytes from the memory area given by Source to the memory area given by Dest. The copy direction is chosen so that overlapping blocks are copied correctly.
  3399. This move operation is independent of type, so the information in Dest will only be in a proper format if you moved the appropriate number of bytes. For example, if you move part of a string to a memory area allocated for another string, the destination “string” will not necessarily be null terminated.
  3400. Example:
  3401. Move ( ADR( vail), ADR( val2), 4);
  3402. moves four bytes of material, beginning at the start of the memory area allocated for vail. The material is moved to the four bytes of memory that begin at the address of val2.
  3403. WordMove
  3404. PROCEDURE WordMove(Source,Dest: ADDRESS; WordCount: CARDINAL);
  3405. Similar to Move, except that WordCount denotes the number of words (2 bytes) to be moved, rather than the number of bytes. This procedure is quicker than performing a Move of twice the size.
  3406. Example:
  3407. WordMove ( ADR( vail), ADR( val2), 4);
  3408. moves eight bytes (four words) of material, beginning at the start of the memory area allocated for vail. The material is moved to the eight bytes of memory that begin at the address of val2.
  3409. Fill
  3410. PROCEDURE Fill(Dest: ADDRESS; Count: CARDINAL; Value: BYTE);
  3411. Stores Value in the Count consecutive bytes starting at Dest. This is a fast way of initializing certain areas of memory in your program.
  3412. Example:
  3413. Fill ( strl. Length( strl), 47);
  3414. initializes the string, strl, with the character (*/’) whose ASCII code is 47.
  3415. WordFill
  3416. PROCEDURE WordFill( Dest : ADDRESS;
  3417. WordCount : CARDINAL;
  3418. Value : WORD);
  3419. Stores Value in the Count consecutive words starting at Dest.
  3420. Example:
  3421. WordFill ( ADR( vail), 4, 32768);
  3422. puts the bit pattern for 32768 in the four consecutive words beginning at the the location of Vail.
  3423. ScanR
  3424. PROCEDURE ScanR( Dest : ADDRESS;
  3425. Count : CARDINAL;
  3426. Value : BYTE) : CARDINAL;
  3427. ScanR searches for the first occurrence of Value in the block starting at location Dest and going Count bytes ahead towards higher addresses. The procedure returns the position relative to Dest, with Dest being in position 0. ScanR returns Count if Value is not found.
  3428. Examples:
  3429. VAR Res : CARDINAL;
  3430. Res := ScanR (ADR ('klmnopqrst'), 10, SHORTCARD ('p')) ; (* Res = 5 *)
  3431. Res ScanR(ADR('klmnopqrst'),10,SHORTCARD('k')); (* Res = 0 *)
  3432. Res := ScanR(ADR('klmnopqrst'),10,SHORTCARD('x')); (* Res = 10 *)
  3433. ScanL
  3434. PROCEDURE ScanL( Dest : ADDRESS;
  3435. Count : CARDINAL;
  3436. Value : BYTE) : CARDINAL;
  3437. Works like ScanR, except the search starts at Dest and works towards lower ad­dresses — still returning a positive distance from Dest.
  3438. Examples:
  3439. VAR TestStr : ARRAY[ 0 .. 80] OF CHAR;
  3440. Res : CARDINAL;
  3441. TestStr := "abcdefghijklmnopqrst";
  3442. Res :« ScanL( ADR( TestStr[ 10]), 10, SHORTCARD( 'd')); (* Res = 7 *)
  3443. Res := ScanL( ADR( TestStr[ 10]), 10, SHORTCARD( 'k')); (* Res = 0 *)
  3444. Res := ScanL( ADR( TestStr[ 10]), 10, SHORTCARD( 'z')); (* Res = 10 *)
  3445. ScanNeR
  3446. PROCEDURE ScanNeR(Dest : ADDRESS;
  3447. Count : CARDINAL;
  3448. Value : BYTE) : CARDINAL;
  3449. Scans the block given by Dest, going Count bytes ahead towards higher addresses, to the first position where the contents differ differ from Value. It returns Count if every element in the block is equal to Value.
  3450. Examples:
  3451. VAR Res : CARDINAL;
  3452. Res :» ScanNeR ( ADR (' aaaaabbbcc') ,10, SHORTCARD (' a')); (* Res = 5 *)
  3453. Res := ScanNeR( ADR('aaaaaaaaaa'), 10, SHORTCARD ('a')); (* Res “ 10 *)
  3454. Res : = ScanNeR( ADR('aaaaaaaaaa'), 10, SHORTCARD ('b')); (* Res = 0 *)
  3455. ScanNeL
  3456. PROCEDURE ScanNeL(Dest : ADDRESS;
  3457. Count : CARDINAL;
  3458. Value : BYTE) : CARDINAL;
  3459. Similar to ScanNeR, except the search starts at Dest and works towards lower addresses. The distance returned from Dest is 0 or a positive value.
  3460. Examples:
  3461. VAR TestStr : ARRAY[ 0 .. 80] OF CHAR; Res : CARDINAL;
  3462. TestStr : = "aaaaabbbbb";
  3463. Res := ScanNeR ( ADR( TestStr [ 9]), 10, SHORTCARD ('a')) ; (* Res = 5 *)
  3464. TestStr :« "aaaaaaaaaa";
  3465. Res := ScanNeR) ADR( TestStr[ 9]), 10, SHORTCARD ('a')) ; (* Res = 10 *)
  3466. TestStr := "aaaaaaaaaa";
  3467. Res := ScanNeR( ADR( TestStr[ 9]), 10, SHORTCARD ('b')); (* Res = 0 *)
  3468. Compare
  3469. PROCEDURE Compare(Source,Dest : ADDRESS;
  3470. Len : CARDINAL) : CARDINAL;
  3471. Compares the two blocks specified by Source and Dest. The procedure looks for the first position where a difference occurs, and returns this position. Len denotes the length of the search. Compare returns Len if the two blocks are equal.
  3472. Example:
  3473. CardResult := Compare ( ADR( "abcdefghijkl"), ADR( "abcdeghujkl"), 10);
  3474. returns 5, since the two locations differ in the sixth position, which has index 5.
  3475. DOS Procedures
  3476. Dos
  3477. PROCEDURE Dos(VAR R: SYSTEM.Registers) ;
  3478. Allows you to access DOS services through the DOS function handler (INI 21H). Consult the DOS documentation for details of the various function calls. Also see “MODULE System,” page 202, for a description of SYSTEM.Registers.
  3479. Example:
  3480. VAR r : SYSTEM.Registers;
  3481. BEGIN
  3482. r.AH : = 2CH; (* 2CH is the number of the DOS service requested *) Dos (r);
  3483. END;
  3484. Upon return, r contains the current time in the following bytes of the CX and DX registers.
  3485. Register Value
  3486. CH hour (0 through 23)
  3487. CL minutes (0 through 59)
  3488. DH seconds (0 through 59)
  3489. CH hundredths of seconds (0 through 99)
  3490. Intr
  3491. PROCEDURE Intr(VAR R: SYSTEM.Registers; I: CARDINAL);
  3492. Allows you to make a software interrupt directly — that is, to bypass the DOS function handler (INT21H) when sending an interrupt. I is the interrupt number. Consult the DOS documentation for details of the interrupts. Also see page 203 for a description of SYSTEM.Registers.
  3493. Example:
  3494. VAR r : SYSTEM.Registers;
  3495. BEGIN
  3496. Intr(r, 12H) ; END;
  3497. This interrupt returns the amount of RAM memory in the field r. AX
  3498. Execute
  3499. PROCEDURE Execute (Name CommandLine StoreAddr StoreLen
  3500. ) : CARDINAL;
  3501. ARRAY OF CHAR, ARRAY OF CHAR, ADDRESS; CARDINAL
  3502. (* full name of program *) (* command line for program *) (* storage to execute in *) (* length in paragraphs *) (* DOS reply (0=OK) *)
  3503. This procedure executes a program. Name is the full name (including the extension) of the program you want executed. CommandLine holds the parameters (if any) for the program that is to be run. You must also supply a pointer to the storage where the program can be executed (StoreAddr), and the length in paragraphs of this storage (StoreLen). This storage could be allocated by the ALLOCATE function, see page 198.
  3504. Execute returns the DOS return status. Zero means the program has executed; for other values consult the DOS documentation. The newly started program inherits a copy of the environment of the parent program. It also inherits all open files of the parent program.
  3505. Example:
  3506. MODULE h;
  3507. IMPORT IO, Lib;
  3508. VAR s : ARRAY[0..30] OF CHAR;
  3509. BEGIN
  3510. Lib.ParamStr(«,1) ;
  3511. IO. WrStr ('Hallo ');
  3512. 10.WrStr(a);
  3513. END h.
  3514. Compile and link h. mod to get h. exe; now h. exe can be executed from the following program:
  3515. MODULE ExecEx; (* Execute example *)
  3516. IMPORT Storage, Lib, IO;
  3517. VAR a : ADDRESS;
  3518. i : CARDINAL;
  3519. BEGIN
  3520. Storage.ALLOCATE(a,20000);
  3521. 1 := Lib.Execute("h.exe"," there",a,20000 DIV 16);
  3522. IF i # 0 THEN IO.WrStr ('Failed' ); END;
  3523. Storage.DEALLOCATE(a,20000);
  3524. END ExecEx.
  3525. This will produce the following output:
  3526. Hello there
  3527. Program h. exe writes “hello” and whatever is passed as the first command line argument — in this case, “there” is passed as an argument to Execute.
  3528. Address Arithmetic
  3529. The procedures in this section perform arithmetic (addition and subtraction) on point­ers. Addresses in the 8086 family of processors consist of a segment part and an off­set part. The physical address is calculated as: segment * 16 + offset. A normalized pointer is a pointer with an offset in the range 0 to 15.
  3530. AddAddr
  3531. PROCEDURE AddAddr(A: ADDRESS; increment: CARDINAL): ADDRESS;
  3532. Returns the normalized address of the byte increment bytes after the physical address A.
  3533. Example:
  3534. VAR ShiftedAddr : ADDRESS;
  3535. Reference : LONGREAL;
  3536. ShiftedAddr := AddAddr( ADR( Reference), 8);
  3537. returns the address eight bytes past the starting location of Reference.
  3538. SubAddr
  3539. PROCEDURE SubAddr(A: ADDRESS; decrement: CARDINAL): ADDRESS;
  3540. Returns the normalized address of the byte decrement bytes before the physical address A.
  3541. Example:
  3542. VAR ShiftedAddr : ADDRESS;
  3543. Reference : LONGREAL;
  3544. ShiftedAddr := AddAddr( ADR( Reference), 8);
  3545. returns the address eight bytes before the starting location of Reference.
  3546. IncAddr
  3547. PROCEDURE IncAddr(VAR A : ADDRESS; increment : CARDINAL);
  3548. A becomes the normalized address of the byte increment bytes after the physical address A.
  3549. Example:
  3550. VAR ShiftedAddr : ADDRESS;
  3551. Reference : LONGREAL;
  3552. ShiftedAddr :- ADR( Reference);
  3553. IncAddr( ShiftedAddr, 8);
  3554. makes ShiftedAddr refer to the address eight bytes after the starting location of Reference.
  3555. DecAddr
  3556. PROCEDURE DecAddr(VAR A : ADDRESS; decrement : CARDINAL);
  3557. A becomes the normalized address of the byte decrement bytes before the physical address A.
  3558. Example:
  3559. VAR ShiftedAddr : ADDRESS;
  3560. Reference : LONGREAL;
  3561. ShiftedAddr := ADR( Reference);
  3562. IncAddr( ShiftedAddr, 8);
  3563. makes ShiftedAddr refer to the address eight bytes before the starting location of Reference.
  3564. Long Jumps
  3565. Long jumps are a (restricted) way to do non-local gotos. That is, by means of long jumps execution can be transferred from one procedure to another, without returning. The following procedures are often used to deal with error situations.
  3566. SetJmp and LongJmp
  3567. TYPE
  3568. LongLabel = ARRAY[0..3] OF CARDINAL;
  3569. PROCEDURE SetJmp (VAR Lbl: LongLabel) : CARDINAL;
  3570. PROCEDURE LongJmp(VAR Lbl: LongLabel; result: CARDINAL);
  3571. SetJmp and LongJmp are used in conjunction with each other. SetJmp saves the state of a procedure in the buffer Lbl, and returns the value 0. A later call to LongJmp with the same buffer will restore that state, so that it appears as if SetJmp has been called and has returned the value result.
  3572. SetJmp must be called before LongJmp is called, and the procedure that called SetJmp must still be active when LongJmp is called, otherwise the result is un­predictable.
  3573. Note that local variables are often held in machine registers (even across proce­dure calls), which means that their values might have been changed when SetJmp “returns” via LongJmp. To deal with this problem, the volatile compiler directive (*$W+*) (see Chapter 7) can be used for those local variables whose values you wish to save.
  3574. Example:
  3575. MODULE LongJmpEx;
  3576. IMPORT IO, Lib;
  3577. VAR buf : Lib.LongLabel;
  3578. PROCEDURE p2; FORWARD;
  3579. PROCEDURE p;
  3580. BEGIN
  3581. IF Lib.SetJmp(buf) # 0 THEN
  3582. IO.WrStr('LongJmp has been called'); HALT;
  3583. END;
  3584. IO.WrStr ('Hello') ; lO.WrLn;
  3585. p2;
  3586. END p;
  3587. PROCEDURE p2;
  3588. VAR error : BOOLEAN;
  3589. BEGIN
  3590. error := TRUE;
  3591. IF error THEN Lib.LongJmp(buf,1); END;
  3592. END p2;
  3593. BEGIN
  3594. p;
  3595. END LongJmpEx.
  3596. Will produce the following output:
  3597. Hello
  3598. LongJmp has been called
  3599. Error Handling
  3600. MathError and MathError2
  3601. PROCEDURE MathError ( R: LONGREAL; S: ARRAY OF CHAR);
  3602. PROCEDURE MathError2(Rl,R2: LONGREAL; S: ARRAY OF CHAR);
  3603. These are default math error handling procedures. They are called by some of the procedures in the module MATHLIB, in case of an invalid argument.
  3604. MathError outputs a message which includes the name of the procedure in error. See “Error Handling” for the MATHLIB module, page 211, for more information.
  3605. UserBreak
  3606. PROCEDURE UserBreak;
  3607. This procedure aborts the program with a runtime error message, and terminates by a call to the procedure HALT (see Chapter 6). The run-time error message has the following layout:
  3608. Run Time Error [AAAA/SSSS:OOOO] User Break
  3609. AAAA is the absolute segment of the user break, SSSS is the relative segment (which can be seen in the link map), and OOOO is the offset of the user break.
  3610. DisableBreakCheck
  3611. PROCEDURE DisableBreakCheck;
  3612. Disables the control-break handler. After a call to this procedure the program can no longer be aborted with ICtrllllBreakH The check setting is ON by default. You can also specify this setting through the (*$B*) compiler directive (see Chapter 7).
  3613. EnableBreakCheck
  3614. PROCEDURE EnableBreakCheck;
  3615. Enables the control-break handler, so the program can be aborted using ||Ctrl||[Brcak]|. When the program is aborted through such a key sequence, a run-time error message is reported and the program terminates by a call to the HALT procedure (see Chapter 6).
  3616. The run-time message has the layout described for procedure UserBreak (see above). However, if AAAA is outside the program, (e.g., if the program is aborted while executing a DOS function) the runtime message will have the following form:
  3617. Run Time Error [AAAA:OOOO] User Break
  3618. FatalError
  3619. PROCEDURE FatalError(S : ARRAY OF CHAR);
  3620. Writes the string S to standard output, and terminates program execution by a call to the procedure HALT.
  3621. Example:
  3622. FatalError ( 'Cannot continue, ending program.');
  3623. writes the string message if the procedure is called.
  3624. SetReturnCode
  3625. PROCEDURE SetReturnCode(code: SHORTCARD);
  3626. This procedure lets you specify the DOS return code to use when the program is terminated. This value is passed on to the parent program. If the program was activated from the command line, then you can also access this return code in the operating system — through the DOS code ErrorLevel.
  3627. Example:
  3628. SetReturnCode( 1);
  3629. would indicate to DOS that ||Ctrl||Breakl] was used to end the program.
  3630. Miscellaneous
  3631. There are several additional procedures in the Lib module, which do a variety of things.
  3632. Delay
  3633. PROCEDURE Delay(Time : CARDINAL);
  3634. Delays program execution by Time milliseconds.
  3635. Example:
  3636. Delay( 60000);
  3637. delays for one minute.
  3638. Sound
  3639. PROCEDURE Sound(FreqHz : CARDINAL);
  3640. Turns on the computer’s speaker with a sound of FreqHz Hz.
  3641. Example:
  3642. Sound( 1000);
  3643. creates a 1000Hz sound.
  3644. NoSound
  3645. PROCEDURE NoSound;
  3646. Turns off the computer’s speaker.
  3647. HashString
  3648. PROCEDURE HashString ( S : ARRAY OF CHAR;
  3649. Range : CARDINAL) : CARDINAL;
  3650. HashString computes a hash value in the range 0 to Range-1, of the string S.
  3651. Example:
  3652. VAR HashNr : CARDINAL;
  3653. HashNr := HashString( "Hello", 26); (* HashNr = 4 *)
  3654. HashNr := HashString( "hello", 26); (* HashNr = 14 *)
  3655. Terminate
  3656. PROCEDURE Terminate(P : PROC; VAR C : PROC);
  3657. Terminate is used to program actions which need to be performed when the program terminates. Terminate causes procedure P to be called when the program terminates, or by the HALT procedure. C is the procedure which HALT would call if Terminate had not been invoked. Normally, procedure P will call procedure C, and in this way a chain of procedures is built.
  3658. If HALT is called in P, program execution will stop.
  3659. Example:
  3660. MODULE TerminateEx;
  3661. IMPORT Lib,10;
  3662. VAR
  3663. Continual : PROC;
  3664. Continue2 : PROC;
  3665. PROCEDURE CloseDownl;
  3666. BEGIN
  3667. 10.WrStr ('CloseDown-1'); lO.WrLn;
  3668. Continual;
  3669. END CloseDownl;
  3670. PROCEDURE CloseDown2;
  3671. BEGIN
  3672. IO. WrStr ('CloaeDown-2'); IO.WrLn;
  3673. Continue2;
  3674. END CloseDown2;
  3675. BEGIN
  3676. IO.WrStr('Program starts');
  3677. IO.WrLn;
  3678. Lib.Terminate(CloseDownl,Continual);
  3679. Lib.Terminate(CloseDown2,Continue2);
  3680. HALT;
  3681. IO.WrStr('this statement is never executed'); END TerminateEx.
  3682. This program produces the following output:
  3683. Program starts
  3684. CloseDown-2
  3685. CloseDown-1
  3686. MODULE IO
  3687. This section describes the screen input/output library. The IO procedures work on the standard input/output devices (i.e., the keyboard and screen). You can also do screen I/O with the procedures in module FIO, by using the standard file handles (see “Global Variables in FIO,” page 182).
  3688. Global Variables in IO
  3689. The variables below control the behaviour of the I/O procedures. Several variables are also declared in module FIO,page 182 and have the same meaning in both modules. These are: OK, Eng, Separators and ChopOf f.
  3690. CONST
  3691. MaxRdLength = 256;
  3692. TYPE
  3693. WrStrType = PROCEDURE ( ARRAY OF CHAR );
  3694. RdStrType = PROCEDURE ( VAR ARRAY OF CHAR ) ;
  3695. CHARSET = SET OF CHAR;
  3696. VAR
  3697. RdLnOnWr : BOOLEAN; (* Clear buffered input after write *)
  3698. Prompt : BOOLEAN; (* Prompt '?' on read from empty line*)
  3699. WrStrRedirect : WrStrType;
  3700. RdStrRedirect : RdStrType;
  3701. Separators OK
  3702. ChopOff Eng
  3703. : CHARSET;
  3704. : BOOLEAN;
  3705. : BOOLEAN;
  3706. : BOOLEAN;
  3707. (* Engineering notation *)
  3708. The BOOLEAN variable OK is set by all the formatted input/output procedures, as well as by WrBin and RdBin. The value of the BOOLEAN indicates whether the attempted operation was successful.
  3709. Separators is a set of delimiters used by the Rdltem procedure. The default contents of Separators are shown in the following listing. You can change these values by changing assignment statements in FIO.MOD and IO.MOD.
  3710. CHARSET{CHR (9) , CHR (10) , CHR (13) , CHR (26) , ' ' } .
  3711. All the formatted I/O procedures call one of two procedure variables to do their worK: WrStrRedirect or RdStrRedirect. You can redirect I/O by replacing WrStrRedirect and RdStrRedirect with your own “write string” and “read string” procedures.
  3712. Formatted Output
  3713. A write procedure is available for each of the simple types of TopSpeed Modula-2.
  3714. Wr‘simple type’
  3715. PROCEDURE WrChar PROCEDURE WrBool ( V : ( V : : CHAR );
  3716. : BOOLEAN ; Length : INTEGER);
  3717. PROCEDURE WrShtlnt ( V : : SHORTINT ; Length : INTEGER);
  3718. PROCEDURE Wrlnt ( V : INTEGER ; Length : INTEGER);
  3719. PROCEDURE WrLnglnt ( V : : LONGINT ; Length : INTEGER);
  3720. PROCEDURE WrShtCard( V : : SHORTCARD; Length : INTEGER);
  3721. PROCEDURE WrCard ( V l : CARDINAL ; Length : INTEGER) ;
  3722. PROCEDURE WrLngCard( V : : LONGCARD ; Length : INTEGER) ;
  3723. PROCEDURE WrShtHex ( V : : SHORTCARD; Length : INTEGER);
  3724. PROCEDURE WrHex ( V : CARDINAL ; Length : INTEGER);
  3725. PROCEDURE WrLngHex ( V : : LONGCARD ; Length : INTEGER) ;
  3726. PROCEDURE WrReal ( V : : REAL ; Preci si or
  3727. Length : i: CARDINAL;
  3728. INTEGER);
  3729. PROCEDURE WrLngReal( V : : LONGREAL ; Precisiot i; CARDINAL;
  3730. Length : INTEGER);
  3731. These procedures write the value V (of the given type) to the standard output device. All procedures (except WrChar) also take a parameter (Length) which specifies the field width of the formatted data. If Length is negative, the formatted data will be left adjusted, otherwise the output is right adjusted.
  3732. All the procedures (except WrChar and WrBool) call a suitable conversion proce­dure from the Str module to get a string representation of the value V (see page 153); this string is then output using WrStrAdj.
  3733. Finally, WrReal and WrLngReal take an additional parameter, Precision, whose meaning is described in the procedure RealToStr (page 154).
  3734. The global variable Eng indicates whether real numbers are formatted using engi­neering notation (see RealToStr, page 154). The default value of Eng is FALSE.
  3735. Cardinal values can the written in hexadecimal format using procedures WrShtHex, WrHex and WrLngHex.
  3736. Examples: The following calls to the routines for writing simple types produce
  3737. the output following the calls.
  3738. WrChar( 'a');
  3739. WrLn;
  3740. WrBool( TRUE, -15);
  3741. WrLn;
  3742. WrBool( TRUE, 15);
  3743. WrLn; WrLn;
  3744. WrShtlnt( 7, -15);
  3745. Wrlnt( 27, -15);
  3746. WrLnglnt( 2777777, -15);
  3747. WrLn;
  3748. WrShtlnt( 7, 15);
  3749. Wrlnt( 27, 15);
  3750. WrLnglnt( 2777777, 15);
  3751. WrLn; WrLn;
  3752. WrShtCard( 35, -15);
  3753. WrCardf 3555, -15);
  3754. WrLngCardf 355555, -15);
  3755. WrLn;
  3756. WrShtCardf 35, 15);
  3757. WrCard( 3555, 15);
  3758. WrLngCardf 355555, 15);
  3759. WrLn; WrLn;
  3760. WrShtHex( 39, -15);
  3761. WrHex( 3999, -15);
  3762. WrLngHexf 399999, -15);
  3763. WrLn;
  3764. WrShtHex( 39, 15);
  3765. WrHex( 3999, 15);
  3766. WrLngHexf 399999, 15);
  3767. WrLn; WrLn;
  3768. WrReal( 35.5555, 5, -15);
  3769. WrLngReal( 356789.55556789, 5, -15);
  3770. WrLn;
  3771. WrReal( 35.5555, 5, 15);
  3772. WrLngReal( 356789.55556789, 5, 15);
  3773. WrLn;
  3774. (* Output from calls *) a
  3775. TRUE
  3776. TRUE
  3777. 7 27
  3778. 7 2777777
  3779. 27 2777777
  3780. 35 3555 355555
  3781. 35 3555 355555
  3782. 27 F9F 61A7F
  3783. 27 F9F 61A7F
  3784. 3.5556E+1 3.5679E+5
  3785. 3.5556E+1 3.5679E+5
  3786. WrStr
  3787. PROCEDURE WrStr(S: ARRAY OF CHAR);
  3788. This procedure writes the string S to standard output.
  3789. Example:
  3790. WrStr < "Hello there");
  3791. writes the two-word string.
  3792. WrStrAdj
  3793. PROCEDURE WrStrAdj(S: ARRAY OF CHAR; Length: INTEGER);
  3794. This pocedure writes the string S to standard output, using ABS (Length) as the field width. If ABS(Length) is smaller than Str. Length (S) and the global variable ChopOff is TRUE, then a sequence of *?’ characters is written instead of S. If ChopOff is FALSE the field is extended to the number of characters in the string, regardless of the original original field width. If ABS ( Length) is greater than or equal to Str. Length ( S), then the entire string is written.
  3795. The sign of Length determines whether S will be left adjusted (negative) or right adjusted (positive).
  3796. Example:
  3797. WrStrAdj( 'Hello', 10);
  3798. WrLn;
  3799. WrStrAdj( 'Hello', -10);
  3800. write the following output:
  3801. Hello
  3802. Hello
  3803. WrCharRep
  3804. PROCEDURE WrCharRep(V: CHAR; Count: CARDINAL);
  3805. Writes character V repeatedly to the standard output. The character is written Count times.
  3806. Example:
  3807. WrCharRep( 'g', 5);
  3808. writes the following:
  3809. ggggg
  3810. WrLn
  3811. PROCEDURE WrLn;
  3812. Writes a newline (CHR (13), CHR (10)) to standard output.
  3813. Formatted Input
  3814. A read procedure is available for each of the simple types of TopSpeed Modula-2.
  3815. Rd'simple type’
  3816. PROCEDURE PROCEDURE PROCEDURE PROCEDURE PROCEDURE PROCEDURE PROCEDURE PROCEDURE
  3817. RdChar() RdBool () RdShtlntO Rdlnt() RdLnglntO RdShtCard() RdCard() RdLngCard ()
  3818. : CHAR;
  3819. : BOOLEAN;
  3820. : SHORTINT;
  3821. : INTEGER;
  3822. : LONGINT;
  3823. : SHORTCARD;
  3824. : CARDINAL;
  3825. : LONGCARD;
  3826. PROCEDURE RdShtHex() : SHORTCARD;
  3827. PROCEDURE RdHex() : CARDINAL;
  3828. PROCEDURE RdLngHex() : LONGCARD;
  3829. PROCEDURE RdReal () : REAL;
  3830. PROCEDURE RdLngReal () : LONGREAL;
  3831. The Rd* simple type’ procedures read from the standard input and return a value of a ‘simple type’ as indicated by the declarations above.
  3832. All procedures (except RdChar) call Rdltem to get a character sequence which is delimited by characters from the global set variable Separators. The string read in this way is then converted to a value using one of the conversion procedures from the Str module (see page 153).
  3833. The procedures RdShtHex, RdHex and RdLngHex read cardinal values in hex­adecimal format.
  3834. The procedure RdBool returns TRUE if it reads the string ‘TRUE’ (but neither ‘true’ nor ‘True’); for all other input the procedure returns FALSE.
  3835. The syntax for valid REAL values can be found in Chapter 6.
  3836. The global variable OK is set to FALSE if a value of the required type cannot be read.
  3837. All input is buffered a line at a time. Therefore, it’s possible to prompt for more than one value on a given line of input.
  3838. RdStr
  3839. PROCEDURE RdStr(VAR V: ARRAY OF CHAR);
  3840. RdStr reads a string from the standard input, and returns it in V. Characters are read until either of the following conditions is met:
  3841. • the carriage return character (CHR (13)) is read, in which case V is zero termi­nated
  3842. • the string is full — that is, HIGH (V) +1 characters have been read, in which case V is not zero terminated
  3843. Example:
  3844. RdStr( CurrQn);
  3845. reads a string from the standard input, and assigns this value to the string variable
  3846. CurrQn.
  3847. Rdltem
  3848. PROCEDURE Rdltem VAR V: ARRAY OF CHAR);
  3849. Rdltem reads a string from the standard input. The procedure stops reading when any character from the global set variable Separators is read. The string is returned in V.
  3850. Example: Consider the following line in the standard input:
  3851. Hello there, how are you?
  3852. The call
  3853. Rdltem( CurrStr);
  3854. would read only the word ‘Hello’ into the string variable CurrStr. Procedure Rd- Str, on the other hand, would read all five words.
  3855. RdLn
  3856. PROCEDURE RdLn;
  3857. Skips the rest of the input on the current input line.
  3858. EndOfRd
  3859. PROCEDURE EndOfRd(Skip: BOOLEAN) : BOOLEAN;
  3860. If Skip is TRUE, then a sequence of characters, is skipped from the input line. In particular, characters belonging to the set Separators are skipped. EndOfRd returns TRUE if all characters on the current input line have been read.
  3861. EndOfRead can be used to determine whether there is more information on the line. The procedure can be used to skip over any delimiters. You can then read the next item on the line, if there is one. This is useful when reading more than one item of information from a line.
  3862. Example: For the input string,
  3863. Hello there, how are you? I'm fine, thanks.
  3864. the following loop produces the output below it.
  3865. Rdltem( First);
  3866. WHILE NOT EndOfRd( TRUE) DO
  3867. WrStr( First);
  3868. Rdltem( First);
  3869. END;
  3870. WrLn;
  3871. (* Output from preceding loop: *) hellothere,howareyou?!'mfine,
  3872. Basic Input Procedures
  3873. The following two procedures provide low-level services, such as deciding whether a key has been pressed.
  3874. KeyPressed
  3875. PROCEDURE KeyPressed() : BOOLEAN;
  3876. This procedure returns true if a character is available from the standard input. Note that this procedure is not valid for buffered input characters.
  3877. Example:
  3878. IF KeyPressed () THEN
  3879. END;
  3880. RdKey
  3881. PROCEDURE RdKey() : CHAR;
  3882. RdKey returns a character from standard input. If no character is available it waits for one. No buffering is involved and the character is not echoed on the screen.
  3883. Example:
  3884. TheChar :“ RdKey ();
  3885. reads a character into the CHAR variable, TheChar, without echoing the input.
  3886. Redirection
  3887. The following two procedures enable you to redirect the input and output streams.
  3888. Redirectlnput
  3889. PROCEDURE Redirectlnput(FileName: ARRAY OF CHAR);
  3890. Closes the current input stream and opens a new input stream specified by the string FileName. If this stream is closed later, input will be restored to the standard input (even if the input stream was redirected to a file on the command line).
  3891. Example:
  3892. Redirectlnput( "Newlnput");
  3893. opens a stream specified by “Newlnput” and gets input from this file instead of from standard input.
  3894. To close the current input stream (and return the standard input to its default stream), enter the following:
  3895. Redirectlnput( 'CON');
  3896. RedirectOutput
  3897. PROCEDURE RedirectOutput(FileName: ARRAY OF CHAR);
  3898. This procedure closes the current output stream and opens a new output stream specified by the string FileName. If this stream is closed later, output will be restored to the standard output (even if the output stream was redirected to a file on the command line).
  3899. Example:
  3900. Red!rectOutput( "NewOut");
  3901. opens a stream specified by “NewOut” and writes to this file instead of to standard output.
  3902. To close the current output stream (and return the standard output to its default), enter the following:
  3903. RedirectOutput( 'CON');
  3904. MODULE FIO
  3905. The procedures in this module are used for file handling and file input/output. FIO also contains procedures for directory handling.
  3906. A file has an associated file position, which is updated by write and read operations. The first position in a file is 0.
  3907. Files are sequential but direct access to individual elements in a file is possible using the Seek procedure.
  3908. Before a file can be read or written it must be opened using one of the procedures Open, Create or Append. These procedures all return a file handle, which is used in all subsequent references to that file. Open files should be closed with Close before the program terminates, or when they are no longer used.
  3909. By default, files are unbuffered. To do buffered I/O, use the procedure Assign- Buffer, as described below.
  3910. Global Variables in FIO
  3911. These variables are used to control the behavior, and to inspect the result of the file handling and input/output procedures. Some of these variables are also used in module IO, and have the same meaning in both modules.
  3912. CONST
  3913. MaxOpenFiles = 15;
  3914. (* Error if Write fails with disk full*) (* MSDOS standard file handles *)
  3915. DiskFull = 0F0H;
  3916. Standardinput - 0 ;
  3917. Standardoutput = 1 ;
  3918. ErrorOutput - 2 ;
  3919. AuxDevice = 3 ;
  3920. PrintarDavice = 4 ;
  3921. TYPE
  3922. File - CARDINAL; (* File handle type *)
  3923. VAR
  3924. EOF lOcheck
  3925. Separators OK ChopOff Eng
  3926. : BOOLEAN;
  3927. : BOOLEAN;
  3928. : Str.CHARSET;
  3929. : BOOLEAN;
  3930. : BOOLEAN;
  3931. : BOOLEAN;
  3932. (* if TRUE, errors terminate *) (* program with report *)
  3933. (* Engineering notation *)
  3934. The predefined MSDOS standard file handles are numbered from 0 to 4, as defined by the constants above; user files are numbered from 5 to MaxOpenFiles. The files denoted by the standard handles are defined when program execution starts. You need not open these files before using them.
  3935. The BOOLEAN variable OK is set by all the formatted input/output procedures, as well as by WrBin and RdBin. The value of the BOOLEAN indicates whether the attempted operation was successful.
  3936. If an attempt is made to write formatted data in less space than is required, then a sequence of *?’ is written if ChopOff is TRUE. If ChopOff is FALSE then the specified field width is exceeded. ChopOff has a default value of FALSE.
  3937. EOF indicates whether the end of file was reached during the last read operation.
  3938. Separators is a set of delimiters used by the Rdltem procedure. The default contents of Separators are shown in the following listing. You can change these values by changing assignment statements in FIO.MOD and IO.MOD.
  3939. CHARSET{CHR(9) ,CHR(10) ,CHR(13) ,CHR(26) , ' ' } .
  3940. Eng indicates whether real numbers are formatted using engineering notation (see RealToStr, page 154). The default value of Eng is FALSE.
  3941. If lOcheck is TRUE then errors that occur during execution of the procedures listed below will terminate the program with an error message. If lOcheck is FALSE, errors can be inspected by a call to the procedure lOresult. The default value of lOcheck is TRUE. The following procedures report errors if lOcheck is TRUE:
  3942. Open Append
  3943. Truncate GetPos Erase Rename ChDir MkDir
  3944. Create
  3945. Seek
  3946. ReadFirstEntry
  3947. RmDir
  3948. Close Size ReadNextEntry GetDir
  3949. File Handling
  3950. Files are unbuffered by default. Thus, DOS is accessed every time a read or write operation is done. To achieve more efficient input/output, you can associate a buffer with a file — using the procedure AssignBuf f er — so that larger chunks of data are passed to DOS.
  3951. Open
  3952. PROCEDURE Open(Name: ARRAY OF CHAR) : File;
  3953. This procedure opens the file specified by Name for reading or writing, and returns a handle for subsequent operations on the file. The file position is set to the begin­ning of the file. If lOcheck is FALSE and the specified file could not be opened, MAX (CARDINAL) is returned.
  3954. If you write to a nonempty file that has been opened using this procedure, data already in the file will be overwritten.
  3955. Example:
  3956. VAR QnFile, AnsFlle : File;
  3957. QnFile := Open( "Trivia.Qns");
  3958. AnsFlle := Open( "Trivia.Ans");
  3959. The preceding commands open two files (named “Trivia.Qns” and the other named “Trivia.Ans”). The file handles associated with these files are returned to the variables QnFile and QnsFile.
  3960. Append
  3961. PROCEDURE Append(Name: ARRAY OF CHAR) : File;
  3962. Append opens the file specified by Name, sets the file position to the end of the file, and returns a handle to the open file (or MAX (CARDINAL), if the file was not successfully opened). Doing write operations to a nonempty file opened with Append will add data to the end of the file, rather than overwriting data already in the file.
  3963. Example:
  3964. VAR QnFile, AnsFlle : File;
  3965. QnFile := Append( "Trivia.Qns");
  3966. AnsFile := Append( "Trivia.Ans");
  3967. The preceding commands open two files (named “Trivia.Qns” and “Trivia.Ans”). In each case, the file position is set to the end of the files so new material will be appended to the end of the files.
  3968. Create
  3969. PROCEDURE Create(Name: ARRAY OF CHAR) : File;
  3970. This procedure creates a file specified by Name, and returns a handle to the file (or MAX (CARDINAL), if the file was not successfully created). If the file already exists then the previous contents are lost. The created file is opened for read or write operations.
  3971. Example:
  3972. VAR NewQns : File;
  3973. NewQns := Create( "NewQ.Qns");
  3974. creates a new file (named “NewQ.Qns”).
  3975. Close
  3976. PROCEDURE Close (F: File);
  3977. Close flushes the buffer associated with the file F (if any), and then closes the file.
  3978. Example:
  3979. Close ( QnFile);
  3980. closes the file whose handle is stored in QnFile, which is of type File.
  3981. AssignBuffer
  3982. PROCEDURE AssignBuffer (F : File; VAR Buf: ARRAY OF BYTE);
  3983. This procedure assigns the buffer Buf to the file F. For most efficient use the size of the buffer should be: N * 512 + Bufferoverhead, where N is at least 2. The value of Bufferoverhead is specified in FIO.DEF.
  3984. Example:
  3985. VAR FBuff : ARRAY [ 0..2047] OF BYTE;
  3986. AnsFile : File;
  3987. AssignBuffer( AnsFile, FBuff);
  3988. assigns a 2K buffer, FBuff, to the file with handle AnsFile.
  3989. Exists
  3990. PROCEDURE Exists(Name: ARRAY OF CHAR) : BOOLEAN;
  3991. This procedure returns TRUE if the file specified by Name exists. Exists uses ReadFirstEntry to determine its result.
  3992. Example:
  3993. VAR QnFHandle : File;
  3994. IF Exists( "Current.Qns") THEN
  3995. QnFHandle := Append( "Current.Qns");
  3996. ELSE
  3997. QnFHandle := Create( "Current.Qns") ;
  3998. END;
  3999. Erase
  4000. PROCEDURE Erase(Name: ARRAY OF CHAR);
  4001. Thie procedure deletes the file specified by Name.
  4002. Example:
  4003. Erase( "Current.Qns");
  4004. deletes the file named “Current.Qns” from the current directory.
  4005. Rename
  4006. PROCEDURE Rename(Name,NewName : ARRAY OF CHAR);
  4007. This renames the file Name to NewName.
  4008. Example:
  4009. Rename( "Current.Qns", "Old.Qns");
  4010. changes the name of a file from the first to the second value.
  4011. Truncate
  4012. PROCEDURE Truncate(F: File);
  4013. This procedure truncates the file F to its current file position. Note that F is a file handle, not a file name.
  4014. Example:
  4015. VAR AnsFile : File;
  4016. Truncate ( AnsFile);
  4017. truncates the file with handle AnsFile at the current file position.
  4018. GetPos
  4019. PROCEDURE GetPos(F: File) : LONGCARD;
  4020. GetPos returns the current file position in the file F.
  4021. Example:
  4022. Where := GetPos( QnFile);
  4023. assigns the current file position of QnFile to the LONGCARD variable, Where.
  4024. QnFile is of type File.
  4025. Seek
  4026. PROCEDURE SeekfF: File; Pos: LONGCARD);
  4027. This procedure sets the file position associated with F to Pos.
  4028. Example:
  4029. Seek( QnFile, Where);
  4030. moves the file position to location Where in the file.
  4031. Size
  4032. PROCEDURE Size(F: File) : LONGCARD;
  4033. Returns the size in bytes of the file F.
  4034. Example:
  4035. VAR FSize : LONGCARD; QnFile : FILE;
  4036. FSize := Size( QnFile);
  4037. lOresult
  4038. PROCEDURE lOresult () : CARDINAL;
  4039. lOresult can be called after most operations to test the success of the operation. Zero means that the operation succeeded, otherwise lOresult returns the error code as defined by DOS. Note that the global variable lOcheck must be FALSE when using this function (see also lOcheck, page 182).
  4040. Example:
  4041. FileOpeningStatus lOresult();
  4042. assigns the DOS error code resulting from the last file operation.
  4043. Formatted Output
  4044. The procedures below perform formatted output to files. A write procedure is avail­able for each of the simple types of TopSpeed Modula-2.
  4045. All Wr'simple type’ procedures (except WrChar) call WrStrAdj.
  4046. Wr'simple type
  4047. PROCEDURE WrChar (F : File; V : CHAR );
  4048. PROCEDURE WrBool (F : File; V : BOOLEAN ; Length : INTEGER);
  4049. PROCEDURE WrShtlnt (F : File; V : SHORTINT ; Length : INTEGER);
  4050. PROCEDURE Wrlnt (F : File; V : INTEGER ; Length : INTEGER);
  4051. PROCEDURE WrLnglnt (F : File; V : LONGINT ; Length : INTEGER);
  4052. PROCEDURE WrShtCardfF : File; V : SHORTCARD; Length : INTEGER); PROCEDURE WrCard (F : File; V : CARDINAL ; Length : INTEGER);
  4053. PROCEDURE WrLngCard(F : File; V : LONGCARD ; Length : INTEGER);
  4054. PROCEDURE WrShtHex (F : File; V : SHORTCARD; Length : INTEGER);
  4055. PROCEDURE WrHex (F : File; V : CARDINAL ; Length : INTEGER);
  4056. PROCEDURE WrLngHex (F : File; V : LONGCARD ; Length : INTEGER);
  4057. PROCEDURE WrReal (F : File; V : REAL; Precision : CARDINAL;
  4058. Length : INTEGER);
  4059. PROCEDURE WrLngReal(F :
  4060. File;
  4061. LONGREAL; Precision: CARDINAL; Length : INTEGER);
  4062. The Wr’simple type’ procedures take the following parameters: a file handle F, the value V to be written, and the field width (Length) of the formatted data. (The last parameter does not apply to WrChar). If Length is negative, the formatted data will be left adjusted, otherwise the output is right adjusted.
  4063. All the procedures (except WrChar and WrBool) call a suitable conversion proce­dure from the Str module to get a string representation of the value V (see “Con­version Procedures,” page 153); this string is then output using WrStrAdj.
  4064. Cardinal values can be the written in hexadecimal format, using the procedures Wr- ShtHex, WrHex and WrLngHex.
  4065. WrReal and WrLngReal take an additional parameter, Precision, which has the same meaning as in the procedure RealToStr (see page 154). The global variable Eng indicates whether a real value is formatted in engineering notation.
  4066. Examples: The following calls to the routines for writing simple types produce
  4067. the output following the calls.
  4068. VAR OutFile : File;
  4069. WrChar( OutFile, 'a');
  4070. WrLn( OutFile);
  4071. WrBool( OutFile, TRUE, -15);
  4072. WrLn( OutFile);
  4073. WrBool( OutFile, TRUE, 15);
  4074. WrLn( OutFile); WrLn( OutFile);
  4075. WrShtlnt( OutFile, 7, -15);
  4076. Wrlnt( OutFile, 27, -15);
  4077. WrLnglnt( OutFile, 2777777, -15);
  4078. WrLn( OutFile);
  4079. WrShtlnt( OutFile, 7, 15);
  4080. Wrlnt( OutFile, 27, 15);
  4081. WrLnglnt( OutFile, 2777777, 15);
  4082. WrLn( OutFile); WrLn( OutFile);
  4083. WrShtCardf OutFile, 35, -15);
  4084. WrCard( OutFile, 3555, -15);
  4085. WrLngCard( OutFile, 355555, -15);
  4086. WrLn( OutFile);
  4087. WrShtCard( OutFile, 35, 15);
  4088. WrCard( OutFile, 3555, 15);
  4089. WrLngCard( OutFile, 355555, 15);
  4090. WrLn( OutFile); WrLn( OutFile);
  4091. WrShtHex( OutFile, 39, -15);
  4092. WrHex( OutFile, 3999, -15);
  4093. WrLngHex( OutFile, 399999, -15);
  4094. WrLn( OutFile);
  4095. WrShtHex( OutFile, 39, 15);
  4096. WrHex( OutFile, 3999, 15);
  4097. WrLngHex( OutFile, 399999, 15);
  4098. WrLn( OutFile); WrLn( OutFile);
  4099. WrReal( OutFile, 35.5555, 5, -15);
  4100. WrLngReal( OutFile, 356789.55556789, 5, -15);
  4101. WrLn( OutFile);
  4102. WrReal( OutFile, 35.5555, 5, 15);
  4103. WrLngReal( OutFile, 356789.55556789, 5, 15);
  4104. WrLn( OutFile);
  4105. (* Output from calls, written to file associated with OutFile handle *)
  4106. TRUE
  4107. TRUE
  4108. 7 27 7 2777777
  4109. 27 2777777
  4110. 35 3555 355555
  4111. 35 3555 355555
  4112. 27 F9F 61A7F
  4113. 27 F9F 61A7F
  4114. 3.5556E+1 3.5679E+5
  4115. 3.5556E+1 3.5679E+5
  4116. WrStr
  4117. PROCEDURE WrStr(F: File; V: ARRAY OF CHAR);
  4118. This procedure Writes the string V to the file F.
  4119. Example:
  4120. WrStr( AnsFile, "Excellent");
  4121. writes “Excellent” to the file associated with the handle AnsFile.
  4122. WrStrAdj
  4123. PROCEDURE WrStrAdj(F: File; S: ARRAY OF CHAR; Length: INTEGER);
  4124. WrStrAdj writes the string S to the file F, using ABS (Length) as the field width. If ABS (Length) is smaller than Str. Length (S) and the global variable ChopOff is TRUE, then a sequence of *?’ characters is written instead of S. If ChopOf f is FALSE then the field width is exceeded and the entire string is written. If Length is negative the formatted data will be left adjusted, otherwise it is right adjusted.
  4125. Example:
  4126. WrStrAdj(Standardoutput,'Hello',10);
  4127. WrLn(Standardoutput);
  4128. WrStrAdj(Standardoutput,'Hello',-10);
  4129. write the following output:
  4130. Hello
  4131. Hello
  4132. WrCharRep
  4133. PROCEDURE WrCharRep(F: File; V: CHAR ; Count: CARDINAL);
  4134. WrCharRep writes the character V repeatedly to the file F. Count specifies the number of times to write V.
  4135. Example:
  4136. WrCharRep( Standardoutput, ' g' , 5) ; writes the following:
  4137. ggggg
  4138. WrLn
  4139. PROCEDURE WrLn(F: File);
  4140. WrLn writes a newline (CHR(13) ,CHR (10)) to the file F.
  4141. Example:
  4142. WrLn( Standardoutput);
  4143. moves the cursor to the beginning of the next line on the standard output — generally the screen.
  4144. WrBin
  4145. PROCEDURE WrBin (F: File; Buf: ARRAY OF BYTE; Count: CARDINAL);
  4146. This procedure writes a block of “raw” unformatted data specified by Buf to the file F. Count is the size (in bytes) of the block.
  4147. Example:
  4148. VAR Code : ARRAY [ 0 .. 49] OF BYTE;
  4149. WrBin( CodeFile, Code, 50);
  4150. writes 50 bytes — contained in the array Code — to the file associated with the handle CodeFile.
  4151. Formatted Input
  4152. The global variable EOF is set to TRUE if the end-of-file character (CHR(26)) is read, or no more input can be read from a given file.
  4153. Rd‘simple type’
  4154. PROCEDURE RdChar ( F : : File ) : CHAR;
  4155. PROCEDURE RdBool ( F : : File ) : BOOLEAN;
  4156. PROCEDURE RdShtlnt ( F : : File ) : SHORTINT;
  4157. PROCEDURE Rdlnt ( F : : File ) : INTEGER;
  4158. PROCEDURE RdLnglnt ( F : File ) : LONGINT;
  4159. PROCEDURE RdShtCard( F : File ) : SHORTCARD
  4160. PROCEDURE RdCard ( F : File ) : CARDINAL;
  4161. PROCEDURE RdLngCard( F : File ) : LONGCARD;
  4162. PROCEDURE RdShtHex ( F : File ) : SHORTCARD
  4163. PROCEDURE RdHex ( F : : File ) : CARDINAL;
  4164. PROCEDURE RdLngHex ( F : File ) : LONGCARD;
  4165. PROCEDURE RdReal ( F : File ) : REAL;
  4166. PROCEDURE RdLngReal( F : File ) : LONGREAL;
  4167. The Rd‘simple type’ procedures all take a file handle, F, specifying the file from which to read. The procedures return a value of a ‘simple type’ as indicated by the declarations above.
  4168. All procedures (except RdChar) call Rdltem to get a character sequence which is delimited by characters from the global set variable, Separators. This string is then converted to a value using one of the conversion procedures from the Str module (see “Conversion Procedures,” page 153).
  4169. The procedures RdShtHex, RdHex and RdLngHex read cardinal values in hex­adecimal format.
  4170. The procedure RdBool returns TRUE if it reads the string ‘TRUE’ (but neither ‘true’ nor ‘True’), for all other input it returns FALSE.
  4171. The syntax for valid REAL values can be found in Chapter 6.
  4172. The global variable OK is set to FALSE if a value of the required type cannot be read, e.g. if the input has an illegal format or value.
  4173. RdStr
  4174. PROCEDURE RdStr (F: File; VAR V: ARRAY OF CHAR);
  4175. RdStr reads a string from the file F and returns it in V. Characters are read until one of the following conditions are met:
  4176. • the end-of-file character (CHR (26)) is read, in which case EOF is set to TRUE, and V is zero terminated
  4177. • the carriage return character (CHR (13)) is read, in which case V is zero termi­nated
  4178. • the string is full — that is, HIGH (V) +1 characters have been read, in which case V is not zero terminated
  4179. Example:
  4180. RdStr( QnFile, CurrQn);
  4181. reads a string from the file associated with the handle QnFile, and assigns this string to the string variable CurrQn.
  4182. Rdltem
  4183. PROCEDURE Rdltem(F: File; VAR V: ARRAY OF CHAR);
  4184. Rdltem reads a string (from the file F). The procedure stops reading when any character from the global set variable Separators is read. The string is returned in V.
  4185. Example: Consider the following line in a file (with handle QnFile):
  4186. Hello there, how are you?
  4187. The call
  4188. Rdltem( QnFile, CurrStr);
  4189. would read only the word ‘Hello’ into the string variable CurrStr. Procedure Rd­Str, on the other hand, would read all five words.
  4190. RdBin
  4191. PROCEDURE RdBin( F : File;
  4192. VAR Buf: ARRAY OF BYTE;
  4193. Count : CARDINAL) : CARDINAL;
  4194. RdBin reads a block of Count “raw” bytes from the file F, and returns this input in Buf. The procedure returns the number of bytes actually read.
  4195. Example:
  4196. VAR Code : ARRAY [ 0 .. 49] OF BYTE; NrRead : CARDINAL;
  4197. NrRead : = RdBin( CodeFile, Code, 50);
  4198. reads 50 bytes from the file with handle CodeFile, and stores these bytes in the array Code.
  4199. Directory Handling
  4200. ChDir
  4201. PROCEDURE ChDir(Name: ARRAY OF CHAR);
  4202. This procedure changes the current directory. Name specifies the new directory path and may include a drive name.
  4203. Example:
  4204. ChDir( "a:\jpi\src");
  4205. switches you to the directory \JPI\SRC on drive A. If lOcheck is TRUE, then this procedure displays an error message if the specified path doesn’t exist.
  4206. MkDir
  4207. PROCEDURE MkDir(Name: ARRAY OF CHAR);
  4208. This procedure creates a new subdirectory at the path specified by Name. If lOcheck is TRUE, then this procedure displays an error message if the specified directory can’t be created.
  4209. This might happen because a subdirectory on the path for your procedure has not yet been created. It might also happen because there is already a file with the specified name in the specified directory.
  4210. Example:
  4211. MkDir( "zasu");
  4212. creates a subdirectory named ZASU in the current directory.
  4213. RmDir
  4214. PROCEDURE RmDir(Name: ARRAY OF CHAR);
  4215. This procedure removes the directory specified by Name from the directory structure.
  4216. This directory must be empty. You cannot remove the cunent directory.
  4217. Example:
  4218. RmDir( "zasu");
  4219. removes the subdirectory, ZASU, from the current directory.
  4220. GetDir
  4221. PROCEDURE GetDir ( Drive : SHORTCARD;
  4222. VAR Name : ARRAY OF CHAR);
  4223. GetDir returns the full path name, in Name, for the current directory on the drive specified by Drive (O=default,l=drive A, etc.).
  4224. Example:
  4225. GetDir( 3, HDCurrDir);
  4226. returns the name of the current directory on drive C. The name is returned in the string HDCurrDir.
  4227. ReadFirstEntry
  4228. TYPE
  4229. PathTail = ARRAY[0..12] OF CHAR;
  4230. FileAttr = SET OF (readonly,hidden, system, volume,directory,archive);
  4231. DirEntry = RECORD
  4232. rsvd : ARRAY[O..2O] OF SHORTCARD; (* reserved *)
  4233. attr : FileAttr;
  4234. time : CARDINAL;
  4235. date : CARDINAL;
  4236. size : LONGCARD;
  4237. name : PathTail;
  4238. END;
  4239. PROCEDURE ReadFirstEntry( DirName : ARRAY OF CHAR;
  4240. Attr : FileAttr;
  4241. VAR D : DirEntry) : BOOLEAN;
  4242. This procedure searches a directory for a file that matches the string specified in DirName. The string DirName contains the drive, path and file name of the file to be found. The file name may contain wildcard characters (**’, *?’).
  4243. The Attr parameter requires some explanation. If Attr is the empty set, then only normal file entries are found. (The same applies if the readonly and archive attributes are set.) If hidden files, system files or directory entries are to be taken into account, then the corresponding attribute must be set. Finally, if the volume attribute is set, then only the volume name is returned.
  4244. If a matching entry is found ReadFirstEntry will return TRUE, and D will contain the directory entry for the first match.
  4245. See also the procedure ReadNextEntry, which can be used to find subsequent matches.
  4246. Examples:
  4247. FoundEntry := ReadFirstEntry( "c:\com\*.,
  4248. FileAttr{hidden,system,directory), Ent);
  4249. will match all files in the directory c: \corn, and Ent will contain the first entry (if the function result is TRUE, that is, if any matches were found).
  4250. FoundEntry:= ReadFirstEntry( "a:*.mod", FileAttr{), Ent);
  4251. will match all normal files with the extension “mod” in the root directory on drive A. Ent will contain the first entry (if the function result is TRUE).
  4252. ReadNextEntry
  4253. PROCEDURE ReadNextEntry(VAR D: DirEntry) : BOOLEAN;
  4254. This procedure works together with ReadFirstEntry. Procedure ReadNextEn­try takes a directory entry, D, which is the result of a previous call to Read­FirstEntry or ReadNextEntry, and finds the next entry that matches the given specification (DirName). This procedure works only after ReadFirstEntry has already been called.
  4255. Example:
  4256. FoundEntry:= ReadFirstEntry( "a:*.mod", FileAttr{), Ent);
  4257. FoundEntry:= ReadNext( Ent);
  4258. will find the first two entries that match the string specified in ReadFirstEntry. After the calls, you will have information only about the second entry.
  4259. MODULE Storage
  4260. This section describes the storage handling functions, which allow you to allocate and deallocate blocks of memory dynamically on a heap. Programs that import the module Storage get a default heap, called the MainHeap, but other heaps can be defined.
  4261. Global Variables in Storage
  4262. TYPE
  4263. HeapRecPtr = POINTER TO HeapRec;
  4264. HeapRec = RECORD
  4265. size : CARDINAL;
  4266. next : HeapRecPtr;
  4267. END;
  4268. VAR
  4269. MainHeap : HeapRecPtr;
  4270. ClearOnAllocate : BOOLEAN;
  4271. MainHeap is the predefined default main heap, and can be used in calls to proce­dures that use heaps other than the main one. ClearOnAllocate specifies whether procedure ALLOCATE zero-fills the allocated block of memory. ClearOnAllo­cate is by default FALSE (see also the (*$Z*) compiler directive in Chapter 7).
  4272. Main Heap Procedures
  4273. The procedures ALLOCATE, DEALLOCATE and Available all operate on the main heap, and therefore need no heap reference.
  4274. ALLOCATE
  4275. PROCEDURE ALLOCATE (VAR a: ADDRESS; size: CARDINAL);
  4276. Allocates a block of size bytes from the main heap. The reference to the allocated block is returned in a. The block is zero filled if the global variable ClearOnEntry is TRUE. If the allocation does not succeed, the error message
  4277. 'Heap overflow'
  4278. is given and program execution terminates. The maximum size of a block that can be allocated by ALLOCATE is MAX ( CARDINAL) (65,535) bytes; larger blocks can be allocated by the general heap procedure HeapAllocate.
  4279. Example:
  4280. VAR HeapSrc : ADDRESS;
  4281. ALLOCATE ( HeapSrc, 2000) ;
  4282. allocates 2000 bytes from MainHeap (if available), and sets HeapSrc to reference these 2000 bytes.
  4283. DEALLOCATE
  4284. PROCEDURE DEALLOCATE (VAR a: ADDRESS; size: CARDINAL);
  4285. Deallocates the memory block of size bytes given by the address a; a is then set to NIL. The deallocated block again becomes part of the main heap’s free storage.
  4286. Example:
  4287. VAR HeapSrc : ADDRESS;
  4288. DEALLOCATE ( HeapSrc, 2000);
  4289. deallocates 2000 bytes accessible through HeapSrc, sets HeapSrc to NIL, and returns the 2000 bytes to MainHeap.
  4290. Available
  4291. PROCEDURE Available(size : CARDINAL) : BOOLEAN;
  4292. Returns TRUE if a block of size bytes can be allocated from the main heap.
  4293. Example: If there are only 2000 bytes of heap space available, the call
  4294. VAR outcome : BOOLEAN;
  4295. outcome : = Available ( 3000);
  4296. would return FALSE.
  4297. General Heap Procedures
  4298. The following procedures can apply to heaps other than MainHeap. For example, you might need to build several trees or other dynamic data structures in a program. A convenient way of distinguishing these trees is to keep them in separate heaps, which you can allocate and use by calling the following procedures. These procedures either require a HeapRecPtr as an argument or they return such a pointer.
  4299. Whereas the main heap procedures used parameters representing bytes, the general heap procedures use paragraphs to specify block sizes.
  4300. MakeHeap
  4301. PROCEDURE MakeHeap(Source: CARDINAL; (* base segment of heap *) Size : CARDINAL (* size in paragraphs *) ) : HeapRecPtr;
  4302. This procedure defines a new heap. Source specifies the storage segment where the new heap is located. This storage must have been allocated — for example, by a storage allocation procedure. Size is the size, in paragraphs (16 bytes), of the given storage. MakeHeap returns a pointer to the new heap. This pointer can subsequently be used in calls to the general heap procedures: HeapAllocate, HeapDeallocate, etc.
  4303. Example:
  4304. VAR TPort : HeapRecPtr;
  4305. BaseSeg : CARDINAL;
  4306. TPort :« MakeHeap ( BaseSeg, 200);
  4307. defines a heap of 200 paragraphs (3200 bytes) in the base segment specified by BaseSeg. It’s assumed that you’ve already allocated storage in that segment — for example, through a call to ALLOCATE to “steal”’ storage from the main heap. The call to MakeHeap simply reserves (some of) that storage for the heap accessed through TPort.
  4308. HeapAllocate
  4309. PROCEDURE HeapAllocate
  4310. (* source heap *) (* result *) (* size in paragraphs *)
  4311. ( Source: HeapRecPtr;
  4312. VAR A : ADDRESS;
  4313. Size : CARDINAL);
  4314. HeapAllocate allocates a block of 16 * Size bytes on the heap given by Source. A pointer to the allocated block is returned in A. If the allocation does not succeed, the error message 'Heap overflow' is given and program execu­tion stops.
  4315. Example:
  4316. VAR HeapSrc : ADDRESS;
  4317. TPort : HeapRecPtr;
  4318. HeapAllocate ( TPort, HeapSrc, 50);
  4319. allocates a memory block of 800 bytes (if available) from the heap defined by TPort.
  4320. This storage will be accessible through HeapSrc.
  4321. HeapDeallocate
  4322. PROCEDURE HeapDeallocate
  4323. (* source heap *)
  4324. (* block to deallocate *) (* size in paragraphs *)
  4325. ( Source: HeapRecPtr;
  4326. VAR A : ADDRESS;
  4327. Size : CARDINAL);
  4328. This procedure deallocates the memory block of 16 * Size bytes starting at the address A. This storage is from the heap specified by Source. After the deallocation, A is set to NIL. The deallocated block becomes part of the (Source) heap’s free storage. Note that you must always deallocate a block into the heap from which it was allocated.
  4329. Example:
  4330. VAR HeapSrc : ADDRESS;
  4331. TPort : HeapRecPtr;
  4332. HeapDeallocate( TPort, HeapSrc, 50);
  4333. deallocates 800 bytes of storage accessible through HeapSrc, sets HeapSrc to NIL, and returns the freed memory to the the heap defined by TPort.
  4334. Heap Aval I
  4335. PROCEDURE HeapAvail(Source : HeapRecPtr) : CARDINAL;
  4336. HeapAvail returns the size, in paragraphs of the largest block available for allo­cation from the heap Source.
  4337. Example:
  4338. VAR result : CARDINAL;
  4339. TPort : HeapRecPtr;
  4340. result := HeapAvail ( TPort);
  4341. After the assignment in the example, result represents the largest block of storage you can allocate from the heap defined by TPort.
  4342. HeapTotalAvail
  4343. PROCEDURE HeapTotalAvail(Source : HeapRecPtr) : CARDINAL;
  4344. Returns the size, in paragraphs, of the total amount of storage available for allocation from the heap Source. This storage is all in one block only if the value returned is equal to the value returned by a call to HeapAvail.
  4345. Example:
  4346. VAR Res : CARDINAL;
  4347. Res : = HeapTotalAvail( MainHeap);
  4348. will return the amount of available storage at the top of memory.
  4349. HeapChangeSize
  4350. PROCEDURE HeapChangeSize
  4351. (* source heap *)
  4352. (* block to change *)
  4353. (* old size of block *)
  4354. (* new size in paragraphs*)
  4355. ( Source : HeapRecPtr;
  4356. VAR A : ADDRESS; OldSize, NewSize : CARDINAL ) ;
  4357. This procedure changes the size of the memory block specified by A. OldSize and NewSize are the sizes, in paragraphs, of the existing block and the desired new block. Source indicates the heap on which the block is allocated. HeapChange­Size avoids any copying of the block if possible. If such a move is necessary, the pro­cedure finds a new area of the heap for the desired block, which causes A to change.
  4358. Example:
  4359. VAR TPort : HeapRecPtr; HeapSrc : ADDRESS;
  4360. HeapChangeSize( TPort, HeapSrc, 200, 400);
  4361. doubles the size of the memory block accessible through HeapSrc. This procedure calls HeapAllocate, so you will get a
  4362. 'Heap overflow'
  4363. error message is there is not enough available storage on the heap specified by TPort.
  4364. HeapChangeAlloc
  4365. PROCEDURE HeapChangeAlloc
  4366. ( Source : HeapRecPtr;
  4367. A : ADDRESS;
  4368. OldSize,
  4369. NewSize : ) : BOOLEAN,
  4370. CARDINAL
  4371. (* source heap *) (* block to change *) (* old size of block *) (* new size of block *) (* If successful *)
  4372. This procedure tries to change the size of the block A, allocated on the heap Source — but only if this change does not require relocating the block. If the resizing is possible, the procedure carries it out and returns TRUE; otherwise the block is not resized, and the procedure returns FALSE. Thus, HeapChangeAlloc never moves a block. Note that only expansions can fail.
  4373. Example:
  4374. VAR TPort : HeapRecPtr;
  4375. HeapSrc : ADDRESS;
  4376. Bigger : BOOLEAN;
  4377. Bigger : = HeapChangeAlloc( TPort, HeapSrc, 400, 200);
  4378. sets Bigger to TRUE, since the new block is smaller than the original, and size reduction never causes block relocation.
  4379. MODULE SYSTEM
  4380. The module SYSTEM plays a special role in the TopSpeed Modula-2 compiler, in that it contains compiler dependent features (such as Ofs and Seg). In fact some of the procedures are built-in to the compiler. Fbr this reason, the module is also called a pseudo-module.
  4381. SYSTEM also contains data types that are of interest in this particular implementation. For example, the Registers type is used to access the 80x86 registers when making
  4382. DOS calls and interrupts (see “DOS Procedures,” page 164), because access to the individual machine registers is necessary when making such calls.
  4383. The type PROCESS is explained below.
  4384. TYPE
  4385. PROCESS = ADDRESS;
  4386. Registers = RECORD
  4387. CASE : BOOLEAN OF
  4388. • TRUE : AX, BX, CX, DX, BP, SI, DI, DS, ES: CARDINAL;
  4389. Flags : BITSET;
  4390. • FALSE : AL, AH, BL, BH, CL, CH, DL, DH : SHORTCARD;
  4391. END;
  4392. END;
  4393. CONST
  4394. CarryFlag = 0;
  4395. ZeroFlag = 6;
  4396. VAR
  4397. HeapBase : CARDINAL ; (* Base segment of heap *)
  4398. Low-level Processes
  4399. Since the IBM PC/AT and compatibles are single-processor computers, true concur­rent processes cannot be implemented. However processes can be implemented by means of coroutines.
  4400. A coroutine is a sequential program that can be suspended by transferring execution to another coroutine (which will resume from its state when last suspended). When a coroutine is suspended its current state is saved, so it can resume execution later when another coroutine transfers execution back to it. In the following we will use the term process instead of coroutine.
  4401. Module Priorities in TopSpeed Modula-2 Module priorities control the handling of hardware interrupts. The priorities are based on the hardware in­terrupt controller in the PC/AT computer. The priority is interpreted as a mask (BITSET) that enables and disables individual interrupts. An interrupt is disabled if its corresponding bit in the mask is 1. See the Technical Reference Manual for your machine for information about its interrupt controller — in order to use these priori­ties effectively.
  4402. Priority is defined for an entire module, and holds for any procedures defined in the module. The priority is in effect for the entire module, or until replaced by a new module with different priority.
  4403. On entry to a block (a PROCEDURE body or a MODULE body), the priority mask in the interrupt controller and the priority mask for the block are logically or-ed together. On exit from the block the mask in the interrupt controller is restored to the contents it had on entry to the block.
  4404. The AT and the PC differ in that the AT has two interrupt controllers and the PC has only one. For the AT, the full 16 bits of the priority mask are used; the 8 lower bits are used to set the mask in the primary interrupt controller and the upper 8 bit are used to set the slave controller. In case of the PC only the lower 8 bits are used to set the mask in the interrupt controller.
  4405. The masks in the interrupt controller are considered to be a part of the state of a process, so these are saved and restored on TRANSFER and IOTRANSFER operations (see these procedures below). If an IOTRANSFER is associated with a hardware interrupt handled by an interrupt controller, a non-specific End-Of-Interrupt is issued.
  4406. The interrupts requests (IRQs) handled by the hardware are vectored through the DOS interrupt vectors 08H to OFH for the primary controller and 7 OH to 77H for the slave controller. These correspond to IRQ 0 - IRQ 15.
  4407. Example of an interrupt handler:
  4408. MODULE T;
  4409. FROM SYSTEM IMPORT NEWPROCESS, IOTRANSFER, TRANSFER, Currentpriority, NewPriority, ADDRESS;
  4410. VAR IntProc : ADDRESS;
  4411. MODULE Int[CARDINAL({3})]; (* IRQ 3 is disabled *)
  4412. IMPORT IOTRANSFER;
  4413. EXPORT IntHandler;
  4414. PROCEDURE IntHandler;
  4415. BEGIN
  4416. IOTRANSFER( . . ., OBH); (* IOTRANSFER on IRQ 3 (Int. OBH) *)
  4417. END IntHandler;
  4418. END Int;
  4419. BEGIN
  4420. NEWPROCESS( ..., IntProc );
  4421. TRANSFER( ..., IntProc );
  4422. NewPriority(CARDINAL(BITSET(Currentpriority())-{3}));
  4423. (* enable IRQ 3 *)
  4424. END T.
  4425. NEWPROCESS
  4426. PROCEDURE NEWPROCESS ( P : PROC;
  4427. A : ADDRESS;
  4428. S : CARDINAL;
  4429. VAR Pl: ADDRESS);
  4430. This procedure creates a new process. P is a parameterless procedure which will constitute the new process. A is a pointer to the workspace for the process. The workspace is needed for local variables and to store the state of the process when it is suspended. S is the size in bytes of this workspace, and should be at least IK. NEWPROCESS returns a reference to the newly created process in Pl. Note that NEWPROCESS only prepares the process for execution, it does not cause it to begin execution.
  4431. Example:
  4432. VAR Newp : PROC;
  4433. ProcAddr, ProcRef : ADDRESS;
  4434. NEWPROCESS ( NewP, ProcAddr, 2000, ProcRef);
  4435. creates a new process. The new process is accessed through ProcRef, and its workspace starts at ProcAddr. The workspace is 2000 bytes. After this call, the process ProcRef is accessible but not active.
  4436. TRANSFER
  4437. PROCEDURE TRANSFER(VAR P1,P2 : ADDRESS);
  4438. This procedure transfers execution from one process to another. The current process is suspended and assigned to Pl. Then process P2 is resumed (at its current point of suspension).
  4439. P2 must be the result of a previous call to NEWPROCESS or TRANSFER. The process Pl will be resumed later, when another process transfers execution back to it.
  4440. Note that assignment to Pl occurs after identification of the new process P2. This means that the actual parameters for the processes can be the same variable.
  4441. This kind of transfer is called synchronous transfer, as opposed to the asyn­chronous transfer which is done by the procedure IOTRANSFER.
  4442. Example:
  4443. VAR ProclRef, Proc2Ref : ADDRESS;
  4444. TRANSFER ( ProclRef, Proc2Ref);
  4445. suspends the current process and assigns it to ProclRef, and then activates the process references by Proc2Ref — at whatever point that process was suspended.
  4446. IOTRANSFER
  4447. PROCEDURE IOTRANSFER(VAR Pl,P2: ADDRESS; I: CARDINAL);
  4448. IOTRANSFER is an interrupt driven (or asynchronous) transfer. It associates the current process with the interrupt number specified by I. The procedure then suspends the current process and assigns it to Pl and activates the process specified by P2.
  4449. When the processor receives an interrupt it checks if that interrupt has been associated with a process. If this is the case, the current process is suspended and assigned to P2, and the (suspended) process Pl is resumed.
  4450. Once an interrupt and a resultant transfer have occurred, the interrupt is no longer associated with that process.
  4451. If there are more processes associated with the interrupt I, they will be treated in a stack like manner. That is, the last process associated with I will be activated when the first interrupt I occurs, the second to last associated process will be activated when the next interrupt I occurs, etc.
  4452. Example:
  4453. VAR PRefl, PRef2 : ADDRESS;
  4454. IOTRANSFER( PRefl, PRef2, OBH);
  4455. associates the current process with interrupt OBH (IRQ 3), and assigns this process to PRefl. The procedure then activates the process specified by PRef2. If an interrupt OBH is received, the current process wil be suspended and the process assigned to PRefl will be reactivated — because that process had been associated with IRQ3.
  4456. InterruptRegisters
  4457. PROCEDURE InterruptRegisters(P: ADDRESS) : ADDRESS;
  4458. InterruptRegisters can be used to access the contents of the registers when an interrupt has taken place. It is only meaningful to call the procedure after an IOTRANSFER to the process P has taken place. InterruptRegisters returns a pointer to a record (on the stack) with the following layout:
  4459. TYPE
  4460. ExtendedRegisters
  4461. = RECORD
  4462. r : Registers;
  4463. IP : CARDINAL;
  4464. CS : CARDINAL;
  4465. RetFlags : CARDINAL;
  4466. END;
  4467. (* as defined above *) (* instruction ptr *) (* code segment *)
  4468. Example:
  4469. VAR Reginfo, ProcRef : ADDRESS;
  4470. Reginfo := InterruptRegisters( ProcRef);
  4471. If the preceding statement follows a call to IOTRANSFER with an interrupt as a parameter, the call returns a pointer to the state of the process after the interrupt.
  4472. CurrentProcess
  4473. PROCEDURE CurrentProcess() : ADDRESS;
  4474. This procedure returns a reference to the current process.
  4475. Example:
  4476. VAR ProcAddr : ADDRESS;
  4477. ProcAddr := CurrentProcess ();
  4478. Currentpriority
  4479. PROCEDURE Currentpriority() : CARDINAL;
  4480. This procedure returns the (MODULE) priority of the current process.
  4481. Example:
  4482. VAR Prior : CARDINAL;
  4483. Prior := Currentpriority () ;
  4484. NewPriority
  4485. PROCEDURE NewPriority(PR : CARDINAL);
  4486. This process gives the the current process a new (MODULE) priority specified by PR.
  4487. (See description of priorities above.)
  4488. Example:
  4489. NewPriority( (3));
  4490. gives the current process a priority specified by the BITSET, {3}.
  4491. Listen
  4492. PROCEDURE Listen(Mask: BITSET);
  4493. Listen temporarily enables the interrupts specified by Mask. This allows pending interrupts to be accepted. The procedure then restores the interrupt mask to its pre­vious state.
  4494. Example:
  4495. Listen( {3});
  4496. temporarily enables the interrupt specified by bit 3.
  4497. Miscellaneous
  4498. The compiler generates inline code for all the procedures in this section.
  4499. DI
  4500. PROCEDURE DI();
  4501. DI disables hardware interrupts. This is useful when accessing data which is shared among several processes.
  4502. El
  4503. PROCEDURE EI();
  4504. El enables hardware interrupts.
  4505. Ofs
  4506. PROCEDURE Ofs ( A: WORD) : CARDINAL;
  4507. Ofs returns the offset part of the address of A. Note that addresses consist of an offset part (ofs) and a segment part (seg), and the physical address is calculated as seg * 16 + ofs.
  4508. Please note that certain values don’t have an offset — for example, simple constants and simple expressions do not have memory locations.
  4509. Example:
  4510. VAR TestSpot : LONGCARD;
  4511. Offset : CARDINAL;
  4512. Offset := Ofs( TestSpot);
  4513. returns the offset portion of the address at which TestSpot is stored.
  4514. Seg
  4515. PROCEDURE Seg( A: WORD) : CARDINAL;
  4516. Seg returns the segment part of the address of A. Please note that the segment of an expression returns the stack segment. Simple constants do not have a segment.
  4517. Example:
  4518. VAR Testspot : LONGCARD;
  4519. Segmt : CARDINAL;
  4520. Segmt : = Ofs( TestSpot);
  4521. returns the segment portion of the address at which TestSpot is stored.
  4522. Out
  4523. PROCEDURE Out(P: CARDINAL; V: SHORTCARD);
  4524. This procedure outputs the value V to the hardware port specified by P.
  4525. Example:
  4526. Out( 4, 111);
  4527. sends ASCII character 111 (‘o’) to hardware port 4 (printer port).
  4528. In
  4529. PROCEDURE In(P: CARDINAL) : SHORTCARD;
  4530. In Returns a value from the hardware port specified by P.
  4531. Example:
  4532. VAR Vai : SHORTCARD;
  4533. Vai := In( 4);
  4534. reads a value from port 4 (printer port), and assignes the value to Vai.
  4535. GetFlags
  4536. PROCEDURE GetFlags() : CARDINAL;
  4537. This procedure returns the contents of the processor’s flags register.
  4538. Example:
  4539. VAR FSet : CARDINAL;
  4540. FSet := GetFlags ();
  4541. stores the current flags settings in FSet.
  4542. SetFlags
  4543. PROCEDURE SetFlags(F: CARDINAL);
  4544. This procedure sets the processor’s flags register to the value specified by F. Procedures SetFlags and GetFlags are especially useful when disabling and enabling interrupts — to save and restore previous interrupt flag values.
  4545. Example:
  4546. VAR FSet : CARDINAL;
  4547. SetFlags ( FSet);
  4548. stores the value of FSet as the new flags register settings.
  4549. The GetFlags and SetFlags can be used together to help in writing critical code, which cannot be interrupted. First, call GetFlags just before the critical code, to save the current flags values. Then call DI to disable interrupts during the critical code. After the code, call El to enable interrupts again. Finally, call SetFlags to restore the flags register to its values before the critical code. The following exmaple illustrates this:
  4550. VAR CurrFlags : CARDINAL;
  4551. CurrFlags := GetFlags ();
  4552. DI
  4553. ... (* critical code goes here *)
  4554. El
  4555. SetFlags( CurrFlags);
  4556. MODULE MATHLIB
  4557. The procedures in this module perform common mathematical calculations. In addi­tion, the module contains some 8087 specific procedures.
  4558. Error Handling
  4559. In the case of invalid arguments, some of the procedures call the error handling functions defined below:
  4560. VAR
  4561. MathError : PROCEDURE (LONGREAL, ARRAY OF CHAR);
  4562. MathError2 : PROCEDURE (LONGREAL, LONGREAL, ARRAY OF CHAR);
  4563. Note that the error procedures are procedure variables, which means that they can be replaced by user defined procedures. By default they are assigned to the procedures MathError and MathError2 in the module Lib (see “Error Handling,” page 169).
  4564. Error procedure called by
  4565. MathError Sin, Cos, Tan, Asin, Acos, Log, LoglO and Sqrt.
  4566. MathError2 ATan2
  4567. Trigonometric functions
  4568. PROCEDURE Sin (A : LONGREAL) : LONGREAL;
  4569. PROCEDURE Cos (A : LONGREAL) : LONGREAL;
  4570. PROCEDURE Tan(A : LONGREAL) : LONGREAL;
  4571. PROCEDURE ASin (A : LONGREAL) : LONGREAL;
  4572. PROCEDURE ACos (A : LONGREAL) : LONGREAL;
  4573. PROCEDURE Alan(A : LONGREAL) : LONGREAL;
  4574. PROCEDURE ATan2(X,Y : LONGREAL) : LONGREAL;
  4575. Sin, Cos and Tan implement the corresponding mathematical functions. The argu­ment A to these procedures is specified in radians. Sin and Cos return values in the range -1 to 1.
  4576. ASin, ACos and ATan return the arc sine, arc cosine and arc tangent, respectively. The argument A to ASin and ACos must be in the range -1 to 1. ASin and ATan return values in the range -tt/2 to tt/2. ACos returns values in the range 0 to tt.
  4577. ATan2 returns the arc tangent of Y/X. The result is in the range — tt to tv
  4578. Example:
  4579. CONST PIOver6 = .5235988; (* pi/6 == 30 degrees *)
  4580. VAR asres, sres, acres, cres, atres, atres2, tres : LONGREAL;
  4581. sres := Sin( PI0ver6) ; (* sres = 0.5 *)
  4582. cres := Cos( PI0ver6) ; tres := Tan( PI0ver6); asres : = ASin( sres); acres :■ ACos( cres); atres : = ATan( tres); (* cres = 0.866 *)
  4583. (* tres = 0.577 *)
  4584. (* asres = 0.5236 *)
  4585. (* acres = 0.5236 *)
  4586. (* atres = 0.5236 *)
  4587. atres2 := Atan2( sres, cres); (* atres2 = 1.047 *)
  4588. Hyperbolic Functions
  4589. PROCEDURE SinH(A : LONGREAL) : LONGREAL;
  4590. PROCEDURE CosH(A : LONGREAL) : LONGREAL;
  4591. PROCEDURE TanH(A : LONGREAL) : LONGREAL;
  4592. These procedures return the hyperbolic sine, hyperbolic cosine, and hyperbolic tan­gent, respectively, of the given argument A.
  4593. Example:
  4594. VAR sres, cres, tres : LONGREAL;
  4595. sres : = SinH( 0.5); (* 8res = 0.5478 *)
  4596. cres : = CosH( 0.5);
  4597. tres : = TanH( 0.5); (* cres = 1.1402 *)
  4598. (* tres = 0.4805 *)
  4599. Log
  4600. PROCEDURE Log (A : LONGREAL) : LONGREAL;
  4601. Log returns the natural logarithm (log to base e) of A. The argument must be positive.
  4602. Example:
  4603. VAR Ires : LONGREAL;
  4604. Ires := Log( 2); (*
  4605. Ires := Log( 1); (*
  4606. Ires := Log( 0.5); (* Ires = 0.6931 *)
  4607. Ires = 0.0 *)
  4608. Ires = -0.6931 *)
  4609. Log10
  4610. PROCEDURE LoglO(A : LONGREAL) : LONGREAL;
  4611. LoglO returns the logarithm (base 10) of A. The argument must be positive.
  4612. Example:
  4613. VAR Ires : LONGREAL;
  4614. Ires := LoglO( 2); (* Ires = 0.3010 *)
  4615. Ires := LoglO( 1); (* Ires = 0.0 *)
  4616. Ires := LoglO( 0.5); (* Ires = -0.3010 *)
  4617. Pow
  4618. PROCEDURE Pow(X,Y : LONGREAL) : LONGREAL;
  4619. Returns X raised to the power Y.
  4620. Example:
  4621. VAR pres : LONGREAL;
  4622. pres := Pow( 2.5, 3.5); (* pres = 24.705 *)
  4623. pres := Pow( 2.5, -3.5); (* pres = 0.04048 *)
  4624. Exp
  4625. PROCEDURE Exp (A : LONGREAL) : LONGREAL;
  4626. Returns the result of raising e to the power A. (This function is the inverse of Log.)
  4627. Example:
  4628. VAR eres : LONGREAL;
  4629. eres := Exp( 3.5); (* eres = 33.115 *)
  4630. eres := Exp( -3.5); (* eres = 0.0302 *)
  4631. Mod
  4632. PROCEDURE Mod(X,Y: LONGREAL) : LONGREAL;
  4633. Returns the remainder after “removing” Y from X as often as possible. More specif­ically, the function returns the result of evaluating the following expression:
  4634. X - Y * [ABS (X / Y) j
  4635. where [..] is the floor function, and represents the largest integer less than or equal to the expression between the bracket — in this case, the quotient from X/Y. The absolute value is used to make sure the integer returned by the floor function is rounded toward 0. (For example, floor( -12.5) would be -13, but in the formula above, the result would be 12.)
  4636. Examples:
  4637. VAR mres : LONGREAL;
  4638. mres := Mod( 0.3, 0.65);
  4639. (* mres = 0.3 *)
  4640. (* mres = -1.5 *)
  4641. (* mres = 4.0 *)
  4642. mres := Mod( -73.0, 6.5);
  4643. mres := Mod( 23.5, 6.5);
  4644. Rexp
  4645. PROCEDURE Rexp(VAR I: INTEGER;A: LONGREAL) : LONGREAL;
  4646. Rexp splits the value A into its exponent and mantissa parts. The exponent (for base two) is returned in I, and the mantissa is the function’s return value.
  4647. Example:
  4648. VAR Exponent : INTEGER; result : LONGREAL;
  4649. result := Rexp( Exponent, 79.37);
  4650. After this call, result = 1.24016 and Exponent = 6. To check this, multiply 1.24016 by 64 (26).
  4651. Sqrt
  4652. PROCEDURE Sqrt (A: LONGREAL) : LONGREAL;
  4653. This procedure returns the square root of A. The argument must be positive or zero.
  4654. Example:
  4655. VAR sres : LONGREAL;
  4656. sres := Sqrt( 3.5); (* sres = 1.8708 *)
  4657. sres := Sqrt ( 237.68); (* sres = 15.4169 *)
  4658. Conversion Procedures
  4659. The two procedures below convert the integer part of real values to binary coded decimals and vice versa. Binary coded decimals are represented by the type Packed- Bed:
  4660. TYPE PackedBcd = ARRAY [0..9] OF SHORTCARD;
  4661. Two decimal digits are packed into each element of the array. Element number 9 is the sign.
  4662. LongToBcd
  4663. PROCEDURE LongToBcd(A: LONGREAL) : PackedBcd;
  4664. This procedure returns the value A in a PackedBcd representation. A is rounded to the nearest integer.
  4665. Example: If BcdVal is a variable of type PackedBcd, then
  4666. BcdVal := LongToBcd(-12345.67);
  4667. puts the following values in the cels of BcdVal:
  4668. element : 9 87654321 0
  4669. value in hex : 80 0 0 0 0 0 0 1 23 46
  4670. BcdToLong
  4671. PROCEDURE BcdToLong(A: PackedBcd) : LONGREAL;
  4672. Returns the LONGREAL representation of the PackedBcd value given by A.
  4673. Example: If BcdVal has the same cell values as in the example for procedure
  4674. LongToBcd, then
  4675. Result : = BcdToLong ( BcdVal);
  4676. assigns the value -12346.0 to Result.
  4677. 8087 Procedures
  4678. For a description of the 8087 control word and environment, consult your 8087 documentation.
  4679. LoadControlWord
  4680. PROCEDURE LoadControlWord(C: BITSET);
  4681. This loads the 8087 coprocessor with the control word specified by C.
  4682. Example:
  4683. LoadControlWord( {0, 6..8, 13});
  4684. would load the coporcessor with a control word having five bits turned on.
  4685. StoreControlWord
  4686. PROCEDURE StoreControlWord() : BITSET;
  4687. StoreControlWord returns the 8087’s control word.
  4688. Example:
  4689. VAR bst : BITSET;
  4690. bst := StoreControlWord ();
  4691. returns the current control word and assigns this BITSET to bst.
  4692. ClearExceptions
  4693. PROCEDURE ClearExceptions();
  4694. This procedure clears the 8087’s exception flags, the interrupt request flag and the busy flag in the status word.
  4695. StoreEn viron merit
  4696. TYPE Environment = RECORD Controlword : BITSET; StatusWord : BITSET; TagWord : BITSET; IP : CARDINAL;
  4697. Opcode : CARDINAL; DataPointer : CARDINAL; R80287 : CARDINAL;
  4698. END;
  4699. PROCEDURE StoreEnvironment() : Environment;
  4700. This returns the 8087 processor’s current environment as specified by the record type Environment. See also the 8087 documentation.
  4701. Example:
  4702. VAR CurrEnv : Environment;
  4703. CurrEnv : = StoreEnvironment ();
  4704. After the call to StoreEnvironment, CurrEnv contains the environment setting in the 8087 at the time of the call.
  4705. MODULE FloatExc
  4706. This module enables floating point exception handling. If an 8087 exception occurs, program execution will stop (by a call to FatalError), and a message of the following form is given:
  4707. [AAAAA-OOOO] Float Error : 'message'
  4708. The address AAAAA is an absolute address in hexadecimal. OOOO is the offset from the start of the program. Thus, the procedure in error can be found in the mapfile: first you need to normalize OOOO to get ssss: oooo, then find the largest segment value SSSS in the map file which is less than or equal to ssss; now subtract ssss from SSSS to get dddd. To convert the segment difference dddd to an offset f f f f, multiply by 16. The address you should look for in the map is:
  4709. SSSS:ffff+oooo
  4710. Easy, isn’t it!
  4711. EnableException Handling
  4712. PROCEDURE EnableExceptionHandling;
  4713. This procedure enables 8087 exception handling.
  4714. DisableExceptionHandling
  4715. PROCEDURE DisableExceptionHandling;
  4716. This procedure disables 8087 exception handling.
  4717. MODULE ProcTrace
  4718. This module enables you to trace procedure calls in your programs. You can also monitor the values of specified variables.
  4719. The module contains two procedure variables, Entry and Exit, which are used if you specify the (*$Q+*) directive. When this directive is specified, these procedures are called when your program enters or exits a procedure being traced.
  4720. If you turn procedure tracing on — by calling the Install procedure in Proc­Trace — messages will be displayed upon entry to and exit from all procedures to which the (*$Q+*) directive applies.
  4721. Monitor
  4722. PROCEDURE Monitor(VAR W: WORD);
  4723. (* Monitor variable W *)
  4724. This procedure lets you monitor the value of a specified variable at a specific point in your program. The procedure takes a WORD parameter. When called, Monitor changes two global values delcared in PROCTRACE.DEF:
  4725. MonWrd This WORD variable contains the value of the variable being monitored.
  4726. MonAdr This ADDRESS variable contains the location of the variable being
  4727. monitored.
  4728. Example:
  4729. VAR MyVal : INTEGER;
  4730. MyVal := -2345;
  4731. Monitor( WORD ( MyVal)); (* check value of MyVal *)
  4732. Wrlnt ( INTEGER( MonWrd), 10); (* display current value of MonWrd, *)
  4733. (* which = -2345 *)
  4734. At the call to Monitor, the variable MonWrd is assigned the current value of MyVal, and the address of MyVal is stored in MonAdr.
  4735. Check
  4736. PROCEDURE Check(S: ARRAY OF CHAR); (* check current monitored variable *)
  4737. This procedure checks the value of the variable currently being monitored, to deter­mine whether its value has changed since the last time Monitor was called. If so, the procedure prints a message, and assigns the new value to MonWrd.
  4738. Example:
  4739. VAR MyVal : INTEGER;
  4740. MyVal := -2345;
  4741. Monitor( WORD( MyVal)); Wrlnt( INTEGER( MonWrd)
  4742. (* check value of MyVal *)
  4743. 10); (* display current value of MonWrd, *) (* which = -2345 *)
  4744. MyVal := 2345; (* change value of the variable being monitored *)
  4745. Check( 'MyVal');
  4746. Wrlnt( INTEGER( MonWrd), 10); (* display current value of MonWrd, *) (* which has been updated to 2345 '*)
  4747. Get_Name
  4748. PROCEDURE Get_Name() : Name; (* returns name of current procedure *)
  4749. This procedure returns the name of the procedure executing when Get_Name is called. You must call ProcTrace. Install before calling this procedure, and you must have the (*$Q+*) directive set in order for this procedure to work properly.
  4750. Example: In the prog3 case study from Chapter 4 (see page 20), the following
  4751. statement in the body of PlayScale produces the output below it.
  4752. WrStr( Get_Name()); WrLn;
  4753. (* output from calls in PlayScale *)
  4754. Entering ProcTrace reading MAP-file...
  4755. prog3$PlayScale
  4756. prog3$PlayScale
  4757. This output illustrates the TopSpeed Modula-2 nameing convention: module name (prog3, followed by delimiter (here, $, indicating a FAR call), followed by procedure name (PlayScale).
  4758. GetCsIp
  4759. PROCEDURE GetCsIp () : ADDRESS;
  4760. This proceudre returns the current code segment and instruction pointer in an AD­DRESS variable.
  4761. Example:
  4762. VAR CurrLoc : ADDRESS;
  4763. CurrLoc := GetCsIp ();
  4764. Install
  4765. PROCEDURE Install;
  4766. (* Install procedure-trace traps *)
  4767. This procedure installs the traps needed to trace program execution and procedure calls. This procedure must be installed before any of the other procedure tracing routines is called.
  4768. MODULE Process
  4769. The procedures in this module handle “concurrent” processes. TopSpeed Modula-2 is implemented on a single processor computer, so processes share the processor’s time by means of time-slicing.
  4770. Other (more low-level) procedures relating to processes can be found in the module SYSTEM, see “Low Level Processes,” page 203.
  4771. Scheduler
  4772. The following procedures let you control the time-sliced scheduler, which will control the sequence in which processes are allocated time-slices for their execution. An example at the end of the discussion of the Process module shows how these procedures are used.
  4773. Startscheduler
  4774. PROCEDURE Startscheduler;
  4775. This procedure starts the time-sliced scheduler. If the scheduler is already active this call has no effect.
  4776. StopScheduler
  4777. PROCEDURE StopScheduler;
  4778. This stops the time sliced scheduler. Note that SEND and WAIT operations still function when the scheduler is stopped (see “Signals” below).
  4779. StartProcess
  4780. PROCEDURE StartProcess(P: PROC; N: CARDINAL; Pr: CARDINAL);
  4781. Creates a new process which is specified by the procedure P. The process will be allocated a workspace of N bytes (N should be at least IK). Each process has a priority (not to be confused with MODULE priority). Pr is the priority of the process, and should be greater than zero. If Pr is greater than or equal to the priority of the cunent process, then the newly created process will become active.
  4782. Example:
  4783. StartProcess( NewProc, 4096, 2);
  4784. creates a new process, specified by procedure NewProc. This prcess is allocated 4096 bytes, and has priority 2.
  4785. Signals
  4786. Processes can communicate in two different ways: either via global shared variables, or via signals. Signals are used for synchronization among processes.
  4787. Apart from initialization, the following operations can be done on signals: SEND, WAIT, Notify and Awaited. A signal consists of two entities: a counter and a queue. The counter is used to determine whether any processes are waiting for the signal or whether there are signals waiting for processes to use them; the queue is used to determine the order in which any waiting processes are activated.
  4788. Init
  4789. TYPE SIGNAL;
  4790. PROCEDURE Init(VAR s: SIGNAL);
  4791. Initializes the signal s — that is, sets its counter to zero and its queue to empty. A SIGNAL is defined as a pointer to a record containing counter and queue information. See the implementation file, PROCESS .MOD, for details.
  4792. Example:
  4793. VAR MySignal : SIGNAL;
  4794. Init( MySignal);
  4795. initializes the counter and queue for MySignal.
  4796. SEND
  4797. PROCEDURE SEND(s: SIGNAL);
  4798. A call to SEND with s as argument will cause the first process waiting for s to become active. If no processes are waiting, the call will be queued.
  4799. The SEND operation works by incrementing the counter associated with s. If the counter is less than or equal to zero, then at least one process is waiting for s and the first one in the queue will become ready for execution. This process will also start execution if its priority is greater than or equal to the priority of the current process.
  4800. Example:
  4801. VAR KeyReady : SIGNAL;
  4802. SEND( KeyReady);
  4803. causes the first process in the queue waiting for a KeyReady signal to become active, or causes the signal to be queued if no process is waiting for the signal.
  4804. WAIT
  4805. PROCEDURE WAIT(s: SIGNAL);
  4806. A call to WAIT causes the calling process to wait for a corresponding SEND unless the signal s has previously queued SEND operations — that is, unless the counter for s is greater than zero.
  4807. The WAIT procedure decrements the counter associated with s. If the counter is less than zero, it means that the calling process has to wait for a corresponding SEND to s, and another process will be activated. If the counter is greater than or equal to zero then the calling process will continue.
  4808. Example:
  4809. VAR KeyReady : SIGNAL;
  4810. WAIT( KeyReady);
  4811. causes the sending process to wait for a SEND with KeyReady as its argument, unless previous SEND operations have already been queued for KeyReady.
  4812. Notify
  4813. PROCEDURE Notify(s: SIGNAL);
  4814. Notify causes a task waiting on signal s to be scheduled when possible, for ex­ample, at the next time-slice. If no process is waiting for s, the call has no effect. This call does not cause rescheduling, so it may be used by an interrupt handler (see Chapter 7) to safely notify another process of an event’s occurrence.
  4815. Example:
  4816. VAR MySignal : SIGNAL;
  4817. Notify( MySignal);
  4818. causes a task waiting for MySignal to be scheduled for activation.
  4819. Awaited
  4820. PROCEDURE Awaited(s: SIGNAL): BOOLEAN;
  4821. This procedure returns TRUE if any process is waiting on the signal s — that is, if the counter associated with s is negative).
  4822. Example:
  4823. VAR MySignal : SIGNAL;
  4824. IF Awaited( MySignal) THEN
  4825. END;
  4826. Miscellaneous
  4827. The following procedures enable you to control how a particular process fits into the time-slice scheme. You can use these procedures to keep a process from being scheduled as well as from being descheduled.
  4828. Delay
  4829. PROCEDURE Delay(t : CARDINAL);
  4830. This delays the current process for at least t timeslices. A timeslice is approximately 1/18 second . If t is zero, rescheduling takes place without a delay, allowing another process with the same or higher priority to become active.
  4831. Example:
  4832. Delay( 54);
  4833. delays the current process for about 3 seconds.
  4834. Lock
  4835. PROCEDURE Lock;
  4836. Lock prevents the current process from being descheduled by time-slicing, until a call to Unlock. This is useful when a process is accessing data which is shared among several processes. Calls to Lock may be nested, but must always be paired with calls to UnLock.
  4837. Unlock
  4838. PROCEDURE Unlock;
  4839. Unlock allows time-slice rescheduling, and must always be paired with a Lock call. The current process will be descheduled if there is a ready process with the same or higher priority.
  4840. Example: A keyboard process.
  4841. MODULE KBP;
  4842. IMPORT Process,10;
  4843. VAR (*$W+*)
  4844. KBbuff : ARRAY[0..1023] OF CHAR; (* cyclic buffer *)
  4845. KBhead : CARDINAL;
  4846. KBtail : CARDINAL;
  4847. KeyReady : Process.SIGNAL;
  4848. (*$W=*)
  4849. PROCEDURE KBProcess; VAR k : CHAR; p : CARDINAL;
  4850. BEGIN LOOP
  4851. Process.Lock; (* DOS and shared variables are used *)
  4852. IF IO.KeyPressed() THEN k := I0.RdKey(); p := (KBhead+1)MOD SIZE(KBbuff); IF p <> KBtail THEN
  4853. KBbuff[KBhead] := k; KBhead := p;
  4854. END;
  4855. Process.Unlock;
  4856. IF Process.Awaited(KeyReady) THEN Process.SEND(KeyReady) END;
  4857. ELSE
  4858. Process.Unlock;
  4859. END;
  4860. END;
  4861. END KBProcess;
  4862. PROCEDURE GetKeyO : CHAR;
  4863. VAR k : CHAR;
  4864. BEGIN LOOP
  4865. Process.Lock; (* global shared variables are used *) IF KBtailOKBhead THEN k := KBbuff[KBtail];
  4866. KBtail := (KBtail+1)MOD SIZE(KBbuff);
  4867. Process.Unlock;
  4868. RETURN k;
  4869. END;
  4870. Process.Unlock;
  4871. Process.WAIT(KeyReady) ; END;
  4872. END GetKey;
  4873. PROCEDURE InitKBProcess;
  4874. BEGIN
  4875. KBhead : = 0;
  4876. KBtail := 0;
  4877. Process.Init(KeyReady) ;
  4878. Process.StartProcess(KBProcess, 1000,1);
  4879. Process.Startscheduler;
  4880. END InitKBProcess;
  4881. VAR c : CHAR;
  4882. BEGIN
  4883. InitKBProcess;
  4884. LOOP
  4885. c := GetKeyO;
  4886. Process.Lock; (* because IO.WrChar calls DOS *) IO.WrChar(c);
  4887. Process.Unlock;
  4888. IF c=CHR(27) THEN EXIT END;
  4889. END;
  4890. END KBP.
  4891. MODULE Graph
  4892. The module Graph implements basic graphics for IBM PCs and true compatibles. The module makes it possible to use TopSpeed Modula-2 for doing graphics on several commonly available graphics boards: CGA, EGA, VGA, Hercules, and the board used in AT&T and Olivetti computers.
  4893. In graphics mode, the screen resolution will depend on the graphics board you are using. Certain features are the same, regardless of graphics board. For example, the upper left hand comer of the screen is coordinate 0, 0. The X coordinates go to the right from 0..N, where N is one less than the horizontal resolution possible with your graphics board; the Y coordinates go downwards from 0..M, where M depends on the vertical resolution of the graphics board. Any attempt to draw outside these coordinates is ignored.
  4894. Global Constants
  4895. The following declarations provide the data structures and the procedures used to do graphics using various boards.
  4896. TYPE
  4897. PlotProc = PROCEDURE ((* x *) CARDINAL,(* y *)CARDINAL,(* c *)CARDINAL);
  4898. PointProc = PROCEDURE ((* x *) CARDINAL,(* y *)CARDINAL) : CARDINAL ;
  4899. HLineProc = PROCEDURE ( (* X *) CARDINAL, (* y *)CARDINAL, (* x2 *) CARDINAL,
  4900. (* FillColor *)CARDINAL);
  4901. VAR
  4902. Width : CARDINAL ; (* X values are 0..Width-1 *)
  4903. Depth : CARDINAL ; (* y values are 0..Depth-1 *)
  4904. NumColor : CARDINAL ; (* Colors are 0..NumColor-1 *)
  4905. (*
  4906. procedure variables for device dependent routines *)
  4907. GraphMode,TextMode Plot
  4908. Point
  4909. HLine
  4910. : PROC ;
  4911. : PlotProc ;
  4912. : PointProc ;
  4913. : HLineProc ;
  4914. The following declarations contain procedures and constants, defined specifically for each graphics board supported. When the program is initialized to use a particular board, the appropriate declarations from the following collection are used.
  4915. (*
  4916. Device specific constants and routines
  4917. equivalent to the variables Width, Depth and NumColors *)
  4918. PROCEDURE CGAGraphMode;
  4919. PROCEDURE CGATextMode;
  4920. PROCEDURE CGAPlot(x,y:CARDINAL;c:CARDINAL) ;
  4921. PROCEDURE CGAPoint(x,y:CARDINAL) : CARDINAL;
  4922. PROCEDURE CGAHLine ( x,y,x2 : CARDINAL; c:CARDINAL );
  4923. PROCEDURE EGAGraphMode;
  4924. PROCEDURE EGAPlot( x,y,c : CARDINAL);
  4925. PROCEDURE EGAPoint(x,y:CARDINAL) : CARDINAL;
  4926. PROCEDURE EGAHLine ( x,y,x2 : CARDINAL; c:CARDINAL );
  4927. PROCEDURE HercGraphMode;
  4928. PROCEDURE HercTextMode;
  4929. PROCEDURE HercPlot(x,y:CARDINAL;c:CARDINAL) ;
  4930. PROCEDURE HercPoint(x,y:CARDINAL) : CARDINAL;
  4931. PROCEDURE HercHLine ( x,y,x2 : CARDINAL; c:CARDINAL );
  4932. PROCEDURE ATTGraphMode;
  4933. PROCEDURE ATTPlot(x,y:CARDINAL;c:CARDINAL);
  4934. PROCEDURE ATTPoint(x,y:CARDINAL) : CARDINAL;
  4935. PROCEDURE ATTHLine ( x,y,x2 : CARDINAL; c:CARDINAL );
  4936. CONST VGAGraphMode VGAPlot VGAPoint VGAHLine EGATextMode VGATextMode ATTTextMode
  4937. = EGAGraphMode ;
  4938. = EGAPlot ;
  4939. = EGAPoint ;
  4940. = EGAHLine ;
  4941. = CGATextMode ;
  4942. = CGATextMode ;
  4943. = CGATextMode ;
  4944. CONST
  4945. CGAWidth CGADepth CGANumColor EGAWidth EGADepth EGANumColor VGAWidth VGADepth VGANumColor HercWidth HercDepth HercNumColor ATTWidth ATTDepth ATTNumColor
  4946. END Gr.
  4947. = 320 ;
  4948. = 200 ;
  4949. = 4 ;
  4950. = 640 ;
  4951. = 350 ;
  4952. = 16 ;
  4953. = 640 ;
  4954. = 480 ;
  4955. = 16 ;
  4956. = 720 ;
  4957. = 348 ;
  4958. = 2 ;
  4959. = 640 ;
  4960. = 400 ;
  4961. = 2 ;
  4962. The module substitutes the appropriate constants for the general values (such as Width, Depth, etc.) used by the procedures. Similarly, the procedures appropriate for a specific graphics board are used once you initialize for a particular board. The default initialization is for the CGA board.
  4963. For the CGA board, the colors are numbered as follows: black = 0, blue = 1, red = 2 and white = 3. The color assignments will differ for other boards.
  4964. For the CGA board, filling functions fill with dots of two alternate colors, which are encoded as Colorl + NumColor * Color2. For example, if you want to fill with the color blue the fill color is: 1 + NumColor *1 = 5. You can use this same expression for other boards; the second part of the expression will not be used in determining the color, however.
  4965. Graphics Procedures
  4966. When you call the following procedures, the system will actually call the procedure appropriate for your graphics board. For example, if you have a Hercules board, and you have initialized your program for this board with a call to InitHerc, then a call to GraphMode in your program will actually be a call to HercGraphMode. This is all done automatically, based on the initialization code that is executed for the Graph module.
  4967. GraphMode
  4968. PROCEDURE GraphMode;
  4969. Selects the graphics mode for the board being used.
  4970. TextMode
  4971. PROCEDURE TextMode;
  4972. Returns to text mode.
  4973. Plot
  4974. PROCEDURE Plot(x,y: CARDINAL; Color: CARDINAL);
  4975. This procedure sets the dot at coordinates x, y to the the color specified by Color.
  4976. Example: On a CGA board, the following statement would set the specified
  4977. dot to blue:
  4978. Plot( 200, 100, 1);
  4979. Point
  4980. PROCEDURE Point (X,y: CARDINAL) : CARDINAL;
  4981. Returns the color of the dot at the coordinates x, y.
  4982. Example: On a CGA, the following function returns 2 to CurrColor, a
  4983. CARDINAL, if the specified point is red:
  4984. CurrColor := Point( 220, 120);
  4985. Line
  4986. PROCEDURE Line(xl,yl,x2,y2: CARDINAL; Color: CARDINAL);
  4987. Draws a line between the coordinates xl, yl and x2, y2 in the color specified by Color.
  4988. Example: On a CGA board, the following statement would draw a vertical
  4989. line in blue between the specified points:
  4990. Line( 200, 50, 200, 150, 1) ;
  4991. Circle
  4992. PROCEDURE Circle(x0,y0,r: CARDINAL; c: CARDINAL);
  4993. Draws a circle with center at positiion x0,y0 and radius r. The circle is drawn in the color given by c.
  4994. Example: On a CGA board, the following statement draws a blue circle, having
  4995. the specified center and radius:
  4996. Circlet 200, 100, 20, 1);
  4997. Disc
  4998. PROCEDURE Disc(xO,yO,r: CARDINAL; FillColor: CARDINAL);
  4999. Draws a filled circle with center at position x0,y0 and radius r. The color of the circle is given by FillColor; for the CGA, note that the fill color is a combination of two colors encoded as Colorl + NumColor * Color2.
  5000. Example: The following statement draws a filled blue circle, having the spec­
  5001. ified center and radius.
  5002. Disc( 200, 100, 20, 5) ;
  5003. Ellipse
  5004. PROCEDURE Ellipse(xO, yO : CARDINAL; aO, bO : CARDINAL; c : CARDINAL; fill : BOOLEAN);
  5005. (* center *)
  5006. (* semi-axes *)
  5007. (* color *)
  5008. (* whether filled *)
  5009. Draws an ellipse having its center at position xO, yO, and having aO and bO as the length of the semimajor and semiminor axes, respectively. The BOOLEAN, fill, specifies whether the interior of the ellipse should be filled, and c specifies the color to use for the ellipse.
  5010. Example:
  5011. VAR MyColor : CARDINAL;
  5012. Ellipse( 0, 0, 5, 3, MyColor, TRUE);
  5013. draws a filled ellipse, with its center at the origin (0,0), and with semimajor and semiminor axes of length 5 and 3, respectively. The ellipse is drawn in whatever color is specified in MyColor.
  5014. Polygon
  5015. PROCEDURE Polygon(n : CARDINAL;
  5016. px,py : ARRAY OF CARDINAL;
  5017. FillColor : CARDINAL);
  5018. Draws a filled polygon with n edges. The two arrays px and py specify the corners of the polygon (px [ 0 ], py [ 0 ] is the first comer, px[1],py[1] is the second comer, and so forth). FillColor is the color of the polygon.
  5019. Example:
  5020. TYPE Coordinate = ARRAY [0..2] OF CARDINAL;
  5021. VAR Xs,Ys : Coordinate;
  5022. Xs Coordinate(160,80,240);
  5023. Ya := Coordinate(25,175,175);
  5024. Polygon (3,Xa, Ya, 5);
  5025. The call above draws a blue triangle, with vertices at
  5026. 160, 25 80, 175
  5027. 240, 175
  5028. HLine
  5029. PROCEDURE HLine(x,y,x2: CARDINAL; FillColor: CARDINAL);
  5030. Draws a horizontal line at the Y coordinate given by y. Values x and x2 specify where the line starts and stops, respectively. The color of the line is specified by FillColor.
  5031. Example:
  5032. CGA board:
  5033. The following statement draws a red line, 100 pixels wide, using a
  5034. HLine( 50, 100, 150, 10);
  5035. Initialization Procedures
  5036. There is a separate initalization procedure for each graphics board supported by TopSpeed Modula-2. You need to use the procedure appropriate for your graphics board when compiling programs to run on your machine. The routines are:
  5037. Initialization routines.
  5038. Called to setup display output type.
  5039. PROCEDURE InitCGA ; (* Default *)
  5040. PROCEDURE InitEGA ;
  5041. PROCEDURE InitVGA ;
  5042. PROCEDURE InitHero ;
  5043. PROCEDURE InitATT ;
  5044. By default, the initialization code for the Graph module calls InitCGA. You can change this in your module implementation or you can simply call a different initial­ization procedure at the start of your programs.
  5045. MODULE Window
  5046. This section describes the powerful window management module that comes with TopSpeed Modula-2. Window allows you to display several virtual screens, or win­dows, on the physical screen. Multiple windows are treated in a stack like man­ner. Two kinds of windows are supported, “normal” windows, and palette windows which are described on page 242.
  5047. An example of window programming (windemo. mod) is included on the disks supplied with your compiler. Take a look at the source, and then compile and run the program. The environment that comes with TopSpeed Modula-2 is another example of the use of the Window module.
  5048. Window Constants and Types
  5049. CONST
  5050. Screenwidth = 80;
  5051. ScreenDepth = 25;
  5052. TYPE WinType = POINTER TO WinDescriptor; (* internal *) RelCoord = CARDINAL;
  5053. AbsCoord = CARDINAL; Color = ( Black, Blue, Green, Cyan,
  5054. Red, Magenta, Brown, LightGray,
  5055. DarkGray, LightBlue, LightGreen, LightCyan,
  5056. LightRed, LightMagenta, Yellow, White );
  5057. X1,Y1,
  5058. X2,Y2
  5059. Foreground, : AbsCoord; (* outer coordinates of
  5060. opposite corners *)
  5061. Background : Color; (* not used if Palette *)
  5062. CursorOn : BOOLEAN; (* if cursor active *)
  5063. WrapOn : BOOLEAN; (* if EOL wrap enabled *)
  5064. Hidden : BOOLEAN; (* if window on view *)
  5065. FrameOn : BOOLEAN; (* if frame *)
  5066. FrameDef FrameFore, : FrameStr; (* only used if frame *)
  5067. FrameBack : Color; (* only used if frame and not Palette Window *)
  5068. FrameStr = ARRAY[0..8] OF CHAR; (* Characters for frame *)
  5069. (* 0 1 2 *)
  5070. (* 3 4 *)
  5071. (*
  5072. TitleStr = ARRAY[0..ScreenWidth-1] OF 5 CHAR; 6 7 *)
  5073. WinDef = RECORD
  5074. END;
  5075. TitleMode = (NoTitle,
  5076. LeftUpperTitle,CenterUpperTitle,RightUpperTitle, LeftLowerTitle,CenterLowerTitle,RightLowerTitle);
  5077. CONST
  5078. SingleFrame = FrameStr (' I I II ।—। ') ;
  5079. DoubleFrame = FrameStr (' IttI IIII LJ=U ') ;
  5080. FullScreenDef = WinDef ( 0,0, ScreenWidth-1,ScreenDepth-1,
  5081. White, Black, TRUE, TRUE, FALSE, FALSE, ' ',Black,Black );
  5082. VAR
  5083. Fullscreen : WinType;
  5084. A window is defined by the type WinDef, and a variable or constant of this type is used to create a window. In WinDef, XI, Y1 are the coordinates of the upper left comer and X2, Y2 represent lower right hand comer of the window. If Hidden is TRUE, the window will not be displayed until the procedure PutOnTop is called. FrameOn specifies whether the window has a frame.
  5085. A frame is specified by the type FrameStr — an array of 9 characters — where element 0 denotes the character of the upper left comer, element 1 is the character that denotes the upper bar, etc., as outlined in the declaration above. Two predefined frames are declared by the constants SingleFrame and DoubleFrame.
  5086. A window is created using the procedure Open, which returns a handle of type WinType. Any subsequent reference to that window is made by using this handle. WinType is a pointer to an internal window descriptor, which should be regarded as private to the Window MODULE.
  5087. The window manager operates with two different kinds of coordinates — coordinates relative to a window (RelCoord) and coordinates relative to the screen (AbsCo- ord). Coordinate 0,0 is the upper left comer of the screen when using AbsCoord, and coordinate (1,1) is the upper left comer of a window when using RelCoord.
  5088. Output to windows is accomplished by using the output procedures in the IO module. (Window redefines WrStrRedirect, see MODULE IO).
  5089. Window Management
  5090. Open
  5091. PROCEDURE Open(WD: WinDef) : WinType;
  5092. Given a window definition, WD, Open creates a new window, clears the window and puts it on top of any existing windows. All subsequent output will be appear in this window. Open returns a handle which is to be used in further operations on the window.
  5093. Example:
  5094. Leftwindow := Open( WinDef( 0,0,
  5095. Screenwidth DIV 2-1, ScreenDepth - 1, White, Black, TRUE, TRUE, FALSE, TRUE, SingleFrame, Black, Black));
  5096. opens a window that is about half as wide as the entire screen. This window is on the left half of the screen and becomes the currently active window.
  5097. SetTitle
  5098. PROCEDURE SetTitle( W : Winiype;
  5099. Title : ARRAY OF CHAR;
  5100. Mode : TitleMode);
  5101. SetTitle updates the window title within the window frame of window W. The parameter Mode gives the position of the title.
  5102. Example:
  5103. SetTitle( Leftwindow, "Left Side", CenterLowerTitle);
  5104. specifies that Leftwindow is to have the title “Left Side” and that this title should be written at the bottom of the window, and should be centered.
  5105. SetFrame
  5106. PROCEDURE SetFrame ( W : WinType;
  5107. Frame : FrameStr;
  5108. Fore, Back : Color);
  5109. This procedure changes the frame around the window W, redisplaying any title if necessary. Frame specifies the new frame, Fore and Back give the colors of the frame.
  5110. Example:
  5111. SetFrame( Leftwindow, DoubleFrame, Black, White);
  5112. specifies that the frame for Leftwindow should use double lines. The foreground color will be Black and the background collor will be White.
  5113. Use
  5114. PROCEDURE Use(W: WinType);
  5115. Use causes all subsequent output (by the current process) to appear in window W. W does not not have to be on the screen. This procedure is useful if you have more than one process. See Process, page 220.
  5116. Example:
  5117. Use( Leftwindow);
  5118. PutOnTop
  5119. PROCEDURE PutOnTop(W : WinType);
  5120. This procedure puts the window W on top of the window stack, ensuring it is fully visible. All subsequent output will appear in this window (except for output redirected by Use).
  5121. Example:
  5122. PutOnTop( Fullscreen);
  5123. makes the entire screen the active window. The variable Fullscreen is defined as FullScreenDef in file WINDOW.MOD.
  5124. PutBeneath
  5125. PROCEDURE PutBeneath(W: WinType; WA: WinType);
  5126. This procedure puts the window W beneath the window WA on the window stack.
  5127. Example:
  5128. PutBeneath( Fullscreen, Leftwindow);
  5129. puts Fullscreen under Leftwindow on the window stack.
  5130. Hide
  5131. PROCEDURE Hide(W: WinType);
  5132. Hide removes the window W from the screen and the window stack. However, the contents of the window are saved so they can be redisplayed later, if required. Any window obscured by W will be uncovered as a result of the call to Hide. Any material written to a hidden window, W, is recorded, and will appear when the window is made visible.
  5133. Example:
  5134. Hide( Leftwindow);
  5135. Change
  5136. PROCEDURE Change(W: WinType; X1,Y1,X2,Y2: AbsCoord);
  5137. Changes the size and/or position of the window W, as specified by the new comer coordinates Xl,Yl, X2 and Y2. The contents of the window will be moved with it. If the window is expanded, blanks are filled in; if the window is contracted, text is clipped.
  5138. The comer coordinates specify the upper left (Xl, Yl) and lower right (X2, Y2) comers, respectively.
  5139. Example:
  5140. Change( Leftwindow, 0, 0, Screenwidth DIV 2-1, ScreenDepth DIV 2 - 1);
  5141. makes Leftwindow half its original size — so that it takes up roughly the upper left quadrant of the screen.
  5142. Close
  5143. PROCEDURE Close(VAR W: WinType);
  5144. Close removes the window w from the screen, deletes its window descriptor and deallocates any buffers previously allocated for W. Finally, W is set to NIL to prevent further use.
  5145. Example:
  5146. Close ( Leftwindow);
  5147. removes Leftwindow and effectively deallocates the storage set aside for the win­dow.
  5148. Used
  5149. PROCEDURE Used(): WinType;
  5150. This procedure returns the window currently being used for output by the current process. If no window has been assigned by Use then the top window is returned.
  5151. Example:
  5152. CurrWin := Used();
  5153. makes CurrWin (which is of type WinType) reference the window that is currently active.
  5154. Top
  5155. PROCEDURE Top() : WinType;
  5156. This procedure returns the current top window.
  5157. Example:
  5158. NewTop := Top();
  5159. Info
  5160. PROCEDURE Info(W: WinType; VAR WD: WinDef);
  5161. Given the window W, Info returns the definition of the window in parameter WD.
  5162. Example:
  5163. Info( Leftwindow, Windinfo);
  5164. returns the values for Leftwindow to the WinDef variable, Windinfo.
  5165. Coordinate Handling
  5166. The following procedures enable you to check the status of a window at particular coordinates, and also to set the current window position. Notice that some procedures use RelCoord, whereas others use AbsCoord.
  5167. Obscured At
  5168. PROCEDURE ObscuredAt(W : WinType; X,Y: RelCoord) : BOOLEAN;
  5169. This procedure returns TRUE if the window w is obscured at the position given by the relative coordinates, X and Y.
  5170. Example:
  5171. IF ObscuredAt( Leftwindow, 5, 5) THEN
  5172. WrStr( 'Cannot see your point');
  5173. END;
  5174. At
  5175. PROCEDURE At(X,Y: AbsCoord) : WinType;
  5176. This procedure returns a handle for the window currently displayed at the absolute position X, Y. If no window is displayed at this position NIL is returned.
  5177. Example:
  5178. CurrWind At( 5, 5);
  5179. returns the handle associated with the window currently being displayed at position 5,5.
  5180. GotoXY
  5181. PROCEDURE GotoXY(X,Y: RelCoord);
  5182. This procedure sets the current X, Y position for the cursor in the window currently being used. If X or Y are outside the window frame they will be clipped.
  5183. Example: The following statement makes 5,5 the current cursor position of
  5184. the active window:
  5185. GoToXY( 5, 5);
  5186. WhereX
  5187. PROCEDURE WhereX() : RelCoord;
  5188. WhereX returns the X position of the cursor in the window currently being used.
  5189. Example:
  5190. VAR VP : RelCoord;
  5191. VP :=WhereX();
  5192. returns the cunent horizontal position of the cursor in the active window.
  5193. WhereY
  5194. PROCEDURE WhereY() : RelCoord;
  5195. WhereY returns the Y position of the cursor in the window currently being used.
  5196. Example:
  5197. VAR YP : RelCoord;
  5198. YP.:- WhereY () ;
  5199. returns the current vertical position of the cursor in the active window.
  5200. ConvertCoords
  5201. PROCEDURE ConvertCoords( W : WinType;
  5202. X,Y : RelCoord;
  5203. VAR XO,YO : AbsCoord)
  5204. This procedure converts the relative coordinates X, Y in window W to absolute screen coordinates. The results go in XO, YO.
  5205. Example:
  5206. VAR AbsX, AbsY : AbsCoord;
  5207. ConvertCoord( Leftwindow, 5, 5, AbsX, AbsY);
  5208. returns the absolute coordinates corresponding to the relative coordinates 5,5 in Leftwindow.
  5209. Window Output Procedures
  5210. Output to windows is accomplished by using the output procedures in the IO module. The procedures in this section also affect the output to windows. These procedures work in the currently active window.
  5211. InsLine
  5212. PROCEDURE InsLine;
  5213. This procedure inserts a blank line at the current cursor position. The screen below this line scrolls downward.
  5214. DelLine
  5215. PROCEDURE DelLine;
  5216. This procedure deletes the line at the current cursor position. The screen below the line scrolls upward.
  5217. ClrEol
  5218. PROCEDURE ClrEol;
  5219. ClrEol clears from the current cursor position to the end of line.
  5220. TextColor
  5221. PROCEDURE TextColor(c: Color);
  5222. This procedure sets the text foreground color to c in the current window.
  5223. Example:
  5224. TextColor( Magenta);
  5225. sets the foreground text color in the cunent window to Magenta.
  5226. TextBackground
  5227. PROCEDURE TextBackground(c: Color);
  5228. This procedure sets the text background color to c in the current window.
  5229. Example:
  5230. TextBackground( Black);
  5231. sets the background text color in the cunent window to Black.
  5232. DirectWrite
  5233. PROCEDURE DirectWrite(X,Y: RelCoord; (* start coords *)
  5234. A : ADDRESS; (* address of char array*) Len: CARDINAL); (* length to be written *)
  5235. This procedure writes the string A directly to the cunent window, beginning at the position specified by X, Y. The Len parameter specifies the length to write. No check is made for special characters or end-of-line wrap.
  5236. Example:
  5237. DirectWrite ( 1, 5, ADR ( First), 5);
  5238. writes five characters to the cunently active window. The characters are taken from the area of memory beginning with the location of First, and are written starting from the leftmost column on the fifth line in the window.
  5239. SetWrap
  5240. PROCEDURE SetWrap(on: BOOLEAN);
  5241. SetWrap enables/disables automatic wrap — depending on the value of on — when writing beyond the right end of the current window.
  5242. Example:
  5243. SetWrap( FALSE);
  5244. turns automatic wrap off.
  5245. Clear
  5246. PROCEDURE Clear;
  5247. This procedure clears the current window.
  5248. CursorOn
  5249. PROCEDURE CursorOn;
  5250. This turns the cursor on in the current window. Note that the cursor in a particular window is visible only when the cursor is turned on and the window is on top.
  5251. CursorOff
  5252. PROCEDURE CursorOff;
  5253. This procedure turns the cursor off in the current window.
  5254. Multi-Process Support
  5255. By default, the Window module assumes that only one process calls it. If more processes use this module, the procedure SetProcessLocks should be called, to ensure that all window operations are performed consistently.
  5256. SetProcessLocks
  5257. PROCEDURE SetProcessLocks(LockProc,UnlockProc: PROC);
  5258. This procedure enables process locking in the window system. The LockProc and UnlockProc procedures specify the lock and unlock procedures, respectively. SetProcessLocks also notifies the Window module that concurrent processes are used. If the module PROCESS is being used then the procedures Lock and Un­lock may be passed as LockProc and UnlockProc see page 224, and see also Use, page 235.
  5259. Example:
  5260. SetProcessLocks( MyLock, MyUnlock);
  5261. specifies MyLock and MyUnlock as the procedures to lock and unlock processes, respectively.
  5262. See also Use, page 235.
  5263. Palette Windows
  5264. A special kind of window, a palette window, allows you to use several color sets within the sam ewindow, and to change these color sets dynamically.
  5265. Palette Constants and Types
  5266. CONST
  5267. PaletteSize = 10;
  5268. PaletteMax = PaletteSize-1;
  5269. NonnalPaletteColor = 0; (* see procedure PaletteOpen *)
  5270. FramePaletteColor - 1;
  5271. TYPE
  5272. PaletteRange = SHORTCARD [ 0..PaletteMax ];
  5273. PaletteColorDef = RECORD Fore,Back : Color END;
  5274. PaletteDef = ARRAY PaletteRange OF PaletteColorDef;
  5275. A palette (PaletteDef) is 0 to PaletteMax entries of color sets (Palet­teColorDef). Each color set specifies a foreground and a background color.
  5276. PaletteOpen
  5277. PROCEDURE PaletteOpen(WD : WinDef; Pal: PaletteDef) : WinType;
  5278. PaletteOpen creates a new palette window, as specified by Wd and Pal. The window is cleared to the colors given by Pal [NormalPaletteColor] and the frame is drawn in the colors given by Pal [FramePaletteColor]. Finally the window is put on view on top of any existing windows. The current palette color is given by NormalPaletteColor.
  5279. Example:
  5280. VAR W : WinDef;
  5281. PWind : WinType;
  5282. PalToUse : PaletteDef;
  5283. PWind := PaletteOpen( W, PalToUse);
  5284. creates a new palette window, having the window characteristics specified in W and the palette settings in PalToUse.
  5285. SetPalette
  5286. PROCEDURE SetPalette(W: WinType; Pal: PaletteDef);
  5287. SetPalette changes the palette of the specified window W to Pal, redisplaying the changed colors.
  5288. Example:
  5289. VAR PWind : WinType;
  5290. PalToUse : PaletteDef;
  5291. SetPalette( PWind, PalToUse);
  5292. changes the palette for PWind to the settings in PalToUse.
  5293. PaletteColor
  5294. PROCEDURE PaletteColor() : PaletteRange;
  5295. This procedure returns the current palette color set of the current window.
  5296. Example:
  5297. VAR WhatPalColor: PaletteRange;
  5298. WhatPalColor := PaletteColor() ;
  5299. returns the current palette color set to WhatPalColor.
  5300. SetPaletteColor
  5301. PROCEDURE SetPaletteColor(pc: PaletteRange);
  5302. This procedure sets the current palette color set in the current window to the color set specified by pc. Any subsequent output will now appear in the colors specified by entry pc.
  5303. Example:
  5304. VAR NewPalColor: PaletteRange;
  5305. SetPaletteColor( NewPalColor);
  5306. changes the palette color set in the current window to those specified in the variable
  5307. NewPalColor.
  5308. PaletteColorUsed
  5309. PROCEDURE PaletteColorUsed(W: WinType;pc: PaletteRange) : BOOLEAN;
  5310. Returns TRUE if the color set pc is in use anywhere in the palette window W.
  5311. Example:
  5312. VAR IsUsed : BOOLEAN;
  5313. MyWind : WinType;
  5314. MyPalette : PaletteRange;
  5315. IsUsed := PaletteColorUsed( MyWind, MyPalette);
  5316. returns TRUE if the color set specified by MyPalette is used anywhere in MyWind.
  5317. Str IO RdLnglnt
  5318. Append 149 EndOfRd 179 RdLngReal
  5319. Caps 149 KeyPressed 180 IxCuxCdl
  5320. RdShtCard
  5321. CardToStr 154 RdBool 177
  5322. Compare 149 RdCard 177 RuShcHex RdShtlnt RdStr
  5323. Concat 150 RdChar 177
  5324. Copy 150 RdHex 177
  5325. Delete 152 Rdlnt 177 ReadFirstEntry
  5326. FixRealToStr 155 Rdltem 179 ReadNextEntry
  5327. Insert 152 RdKey 180 Rename
  5328. IntToStr 154 RdLn 179 XxIlUJir
  5329. Item 151 RdLngCard 177 Seek
  5330. S 3.
  5331. Items
  5332. Length 152
  5333. 150 RdLngHex
  5334. RdLnglnt 177
  5335. 177 Truncate WrBin WrBool
  5336. Match 153 RdLngReal 177
  5337. Pos 151 RdReal 177
  5338. RealToStr 154 RdShtCard 177 WrC ard
  5339. Slice 151 RdShtHex 177
  5340. StrToCard 156 RdShtlnt 177 WrCharRep
  5341. StrToInt 155 RdStr 178 WrHex Wrlnt WrT.n
  5342. StrToReal 156 RedirectInput 181
  5343. Lib RedirectOutput
  5344. WrBool
  5345. WrCard 181
  5346. 174
  5347. 174 WrLngCard WrLngHex
  5348. AddAddr 166 WrChar 174 WrLnglnt
  5349. Compare 164 WrCharRep 177 WrLngReal WrReal
  5350. DecAddr 167 WrHex 174
  5351. Delay 171 Wrlnt 174 WrShtCard
  5352. Di sableBreakCheck 170 WrLn 177 WrShtHex
  5353. Dos
  5354. EnahleBreakCheck 164
  5355. 170 WrLngCard WrLngHex 174
  5356. 174 WrShtlnt WrStr
  5357. Environment 159 WrLnglnt 174 WrStrAdj
  5358. Execute 165 WrLngReal 174 Storage
  5359. FatalError 170 WrReal 174
  5360. Fill 161 WrShtCard 174
  5361. HashString 172 WrShtHex 174 ALLOCATE
  5362. HSort 158 WrShtlnt 174 Avaiiaoie
  5363. IncAddr 167 WrStr 176 DEALLOCATE
  5364. Intr 165 WrStrAdj 176 HeapAllocate
  5365. MathError and MathError2 169 HeapAvail
  5366. Move 160 FIO He apChangeAl10c
  5367. No Sound 172 He apChange S i z e
  5368. ParamCount 160 Append 184 HeapDeallocate
  5369. ParamStr QSort 160
  5370. 157 AssignBuffer ChDir 185
  5371. 194 HeapTotalAvail MakeHeap
  5372. RAND 158 Close 185 SYSTEM
  5373. RANDOM 158 Create 184
  5374. RANDOMIZE 158 Erase 186
  5375. ScanL 162 Exists 185 Currentpriority
  5376. ScanNeL 163 GetDir 195 Currentprocess
  5377. ScanNeR 163 GetPos 187 DI El GetFlags In
  5378. ScanR 162 lOresult 188
  5379. SetJmp and LongJmp 168 MkDir 194
  5380. SetReturnCode 171 Open RdBin 183
  5381. Sound 171 194 InterruptRegisters
  5382. SubAddr 167 RdBool 192 IOTRANSFER Listen
  5383. Terminate 172 RdCard 192
  5384. UserBreak 169 RdChar 192 NewPriority
  5385. WordFill 162 RdHex 192 NEWPROCESS
  5386. WordMove 161 Rdlnt 192 UZS
  5387. Out
  5388. Rdltem 193
  5389. RdLngCard RdLngHex 192
  5390. 192 Seg SetFlags TRANSFER
  5391. 192 192 192 192
  5392. 192 192
  5393. 193 195
  5394. 196 186 195 187
  5395. 187 186 191
  5396. 188 188
  5397. 188 191
  5398. 188 188
  5399. 191 188 188
  5400. 188 188 188 188
  5401. 188 188 190 190
  5402. 198
  5403. 198
  5404. 198
  5405. 200
  5406. 201
  5407. 202
  5408. 201
  5409. 200
  5410. 201
  5411. 199
  5412. 207
  5413. 207
  5414. 208
  5415. 208
  5416. 210
  5417. 209
  5418. 206
  5419. 206
  5420. 208
  5421. 207
  5422. 204
  5423. 208
  5424. 209
  5425. 209
  5426. 210
  5427. 205
  5428. MATHUB TextMode 228
  5429. ACos 211
  5430. ASln 211 Window
  5431. ATan 211
  5432. ATan2 211 At 238
  5433. BcdToLong ClearExceptions Cos 216
  5434. 217
  5435. 211 Change Clear Close 236
  5436. 242
  5437. 236
  5438. CosH 212 ClrEol 240
  5439. Exp
  5440. LoadControlWord 213
  5441. 216 ConvertCoords CursorOff 239
  5442. 242
  5443. Log 212 CursorOn DelLine 242
  5444. 240
  5445. LoglO
  5446. LongToBcd 213
  5447. 215 DirectWrite GotoXY 241
  5448. 238
  5449. Mod 214 Hide
  5450. T T"1 236 O o '■»
  5451. Bow 213
  5452. Rexp 214 inio
  5453. InsLine 240
  5454. oin
  5455. SinH 212 ObscuredAt 238
  5456. Sqrt
  5457. StoreControlWord 215
  5458. 216 Open
  5459. PaletteColor 233
  5460. 244
  5461. 245
  5462. StoreEnvironment 217 cdietL6LO1OIUS6Q
  5463. 211 PaletteOpen 244
  5464. TanH 91 9 PutBeneath 235
  5465. 414 PutOnTop 235
  5466. FloatExc SetFrame SetPalette 234
  5467. 244
  5468. DisableExceptionHandllng 218 SetPaletteColor 245
  5469. EnableExcept1onHandling 218 SetProcessLocks 243
  5470. SetTitle 234
  5471. ProcTrace SetWrap
  5472. TextBackground 242
  5473. 241
  5474. Check 219 TextColor 241
  5475. GetCsIp 220 Top 237
  5476. Get_Name 219 Use 235
  5477. Install 220 Used 237
  5478. Monitor 218 WhereX 239
  5479. WhereY 239
  5480. Process
  5481. Awaited 224
  5482. Delay 224
  5483. Init 222
  5484. Lock 224
  5485. Notify 223
  5486. SEND 222 -
  5487. Startprocess 221
  5488. Startscheduler 221
  5489. StopScheduler 221
  5490. Unlock 225
  5491. WAIT 223
  5492. Graph
  5493. Circle 229
  5494. Disc 230
  5495. Ellipse 230
  5496. GraphMode 228
  5497. HLine 231
  5498. Line 229
  5499. Plot 228
  5500. Point 229
  5501. Polygon 230
  5502. Index
  5503. 8086
  5504. Architecture, 95
  5505. 8087 specific procedures, 216
  5506. 8087
  5507. emulation, 140
  5508. exceptions, 140, 217, 217
  5509. support, 140
  5510. $X directive, 136
  5511. ABS function, 120
  5512. Absolute variables, 106
  5513. ACos, 211
  5514. AddAddr, 166
  5515. Adding, 110
  5516. ADDRESS type, 105
  5517. Address
  5518. arithmetic, 166
  5519. of object, 120
  5520. offset procedure, 208 physical, 95, 104, 106, 109,
  5521. 138, 95
  5522. segment procedure, 209
  5523. ADR function, 120
  5524. Alias directive, 134, 135
  5525. ALLOCATE, 198
  5526. Allocation of storage, 197
  5527. AND operator, 110
  5528. Append, 149, 184
  5529. ARRAY type, 105
  5530. representation, 129
  5531. Array, 102
  5532. aggregate, 107
  5533. index, 102
  5534. indexing, 108
  5535. open, 116, 117, 118
  5536. ASin, 211
  5537. AsmLib module, 144
  5538. Assembler, 136
  5539. AssignBuf fer, 185
  5540. At, 238
  5541. ATan, 211
  5542. ATan2, 211
  5543. Available, 198
  5544. Awaited, 224
  5545. BcdToLong, 216
  5546. BIOS scrolling, 76
  5547. BITSET type, 102
  5548. Block commands, 64
  5549. BOOLEAN type, 101
  5550. Bottom scroll zone, 76
  5551. Break directive, 134
  5552. BYTE type, 27, 105, 118
  5553. C convention, 135
  5554. C, 136
  5555. Calculator
  5556. example program, 38
  5557. Call
  5558. characteristics, 119 conventions, 130 infix, 118
  5559. recursive, 116
  5560. CAP function, 120
  5561. Caps, 149
  5562. CARDINAL type, 100
  5563. representation, 128
  5564. CardToStr, 154
  5565. CASE
  5566. keyword, 104 statement, 42, 112
  5567. Case study, 15
  5568. Change, 236
  5569. ChDir, 194
  5570. Check, 219
  5571. Checking index, 135
  5572. NIL dereferencing, 136 overflow, 135 stack overflow, 136 subrange, 136
  5573. CHR function, 120
  5574. Circle, 229
  5575. Class, 138
  5576. Clear, 242
  5577. ClearExceptions, 217
  5578. Close, 185, 236
  5579. ClrEol, 240
  5580. Code segment, 135
  5581. Comment, 97
  5582. Compare, 149, 164
  5583. Comparing, 110
  5584. Compatibility type, 105, 118
  5585. Compiler, 127
  5586. Compiler batch, 78 environment, 67 line numbers, 73 options, 73 segments, 138
  5587. Compound type, 105
  5588. Concat, 150 Configuration error file, 92 load, 77 menu, 79 options, 76 save, 77 segment names, 138
  5589. CONST declaration, 99, 107
  5590. Constant, 106
  5591. Constant aggregate, 107
  5592. case study, 21
  5593. choices, 104
  5594. declaration, 107 expression, 109 literals, 106 named, 107
  5595. Control variable, 114 Conversion
  5596. float to BCD, 215
  5597. ConvertCoords, 239
  5598. Copy, 150
  5599. Coroutines, 203
  5600. Cos, 211
  5601. CosH, 212
  5602. Create, 184
  5603. Currentpriority, 207
  5604. CurrentProcess,207
  5605. Cursor movement, 63
  5606. CursorOff, 242
  5607. CursorOn, 242
  5608. Data segment, 135
  5609. DEALLOCATE, 198
  5610. Debug
  5611. generate information, 73
  5612. DEC procedure, 121
  5613. DecAddr, 167
  5614. Decimal numbers, 97
  5615. Declaration, 98
  5616. constant, 107 enumeration, 101 forward, 116
  5617. full, 116, 122
  5618. global, 122
  5619. importing, 123
  5620. label, 115
  5621. local, 116
  5622. nested, 99
  5623. parameter, 116
  5624. Procedure, 115
  5625. type, 100
  5626. TYPE,122
  5627. variable, 106
  5628. DEF-file, See File
  5629. Default
  5630. extensions, 75
  5631. filenames, 75
  5632. DEFINITION keyword, 122
  5633. Delay, 20, 171, 224
  5634. Delete, 152
  5635. Delimiter, 96
  5636. DelLine, 240
  5637. DI, 208
  5638. Directive, 134
  5639. See also: Options
  5640. Directory
  5641. change directory, 57
  5642. files dir, 57
  5643. handling, 194
  5644. DirectWrite, 241
  5645. DisableBreakCheck, 170
  5646. DisableExceptionHandling,
  5647. 218
  5648. Disc, 230
  5649. DISPOSE procedure, 121
  5650. Div operator, 110
  5651. Dividing, 110
  5652. Dos, 164
  5653. DOS
  5654. command line, 159
  5655. environment, 159
  5656. execute program, 58
  5657. menu commands, 82, 88
  5658. procedures, 164
  5659. quit to, 58
  5660. Shell, 58
  5661. Editor, 59
  5662. block commands, 64
  5663. commands, 62
  5664. correct case, 66
  5665. cursor movement, 63
  5666. deletion and insertion, 63
  5667. insertion and deletion, 63
  5668. keys, 62
  5669. load file, 55, 59
  5670. menu definition, 84
  5671. menu, 59
  5672. options, 65, 75
  5673. pick file, 56
  5674. save File, 57
  5675. save file, 61
  5676. search and replace, 66
  5677. El, 208
  5678. Ellipse, 230
  5679. EnableBreakCheck,170
  5680. EnableExcept ionHandling, 218
  5681. EndOfRd, 179
  5682. Entity, 98
  5683. Enumeration type, 101
  5684. Enumeration
  5685. case study, 41
  5686. importing, 123
  5687. literal, 101
  5688. representation, 129
  5689. Environment, 159
  5690. changing windows, 90
  5691. compiling, 67
  5692. editor, 59
  5693. file menu, 55
  5694. information, 77
  5695. input, 52
  5696. keys, 48, 50, 62, 84
  5697. linker, 71
  5698. make, 69
  5699. running programs, 70
  5700. windows, 51
  5701. Erase, 186
  5702. Error
  5703. linker, 71
  5704. message file, 92
  5705. run-time, 70
  5706. stop on first, 73
  5707. syntax, 95
  5708. type, 95
  5709. EXCL procedure, 121
  5710. EXE-file, See File
  5711. Execute, 165
  5712. Execute program, 58
  5713. Exists, 185
  5714. EXIT statement, 113
  5715. Exp, 213
  5716. Expression, 109
  5717. context, 109
  5718. literal, 109
  5719. External names, 139
  5720. FAR, 135, 139
  5721. FatalError, 170
  5722. File menu, 54
  5723. File
  5724. 7BJ-file, 140
  5725. auto save, 75
  5726. backup, 76 configuration, 77 DEF-file, 127, 136 environment, 47 error messages, 92
  5727. EXE-file, 127, 140, 141
  5728. handling, 183
  5729. load, 55, 59
  5730. MAP-file, 74, 137
  5731. menu definition, 83
  5732. OBJ-file, 127, 133, 136, 137, 139, 140
  5733. pick, 56
  5734. redirection, 76, 77
  5735. save, 57, 61
  5736. selection window, 53
  5737. session, 58
  5738. Fill, 161
  5739. FIO module, 35, 146, 182
  5740. FixRealToStr, 155
  5741. FLOAT function, 120
  5742. FloatExc module, 147, 217
  5743. FOR statement, 18, 114
  5744. Formal parameter, 116
  5745. FORWARD declaration, 116
  5746. FROM importing, 123
  5747. Full declaration, 116, 122
  5748. Function procedure
  5749. case study, 28
  5750. predefined, 119
  5751. Function
  5752. body, 116
  5753. call, 118
  5754. return value, 117
  5755. returning conventions, 132
  5756. Generic tokens, 96
  5757. GetCsIp, 220
  5758. GetDir, 195
  5759. GetFlags, 210
  5760. GetPos, 187
  5761. Get_Name, 219
  5762. GOTO statement, 115
  5763. GotoXY, 238
  5764. Graph module, 30. 146, 226
  5765. GraphMode, 228
  5766. Group, 137
  5767. HALT procedure, 121
  5768. Hashstring, 172
  5769. HeapAllocate, 200
  5770. HeapAvail, 201
  5771. HeapChangeAlloc, 202
  5772. HeapChangeSize,201
  5773. HeapDeallocate,200
  5774. HeapSort, 36, 156
  5775. HeapTotalAvail, 201
  5776. Help lines, 82, 84
  5777. Hexadecimal numbers, 97
  5778. Hide, 236
  5779. HIGH function, 116, 120
  5780. HLine, 231
  5781. HSort, 158
  5782. Hyperbolic Functions, 212
  5783. Identifier, 95, 96
  5784. Identifier
  5785. declaration, 98
  5786. predefined, 100
  5787. visibility, 98
  5788. IF statement, 19, 111
  5789. IMPLEMENTATION keyword,
  5790. 121
  5791. IMPORTing, 123
  5792. In, 209
  5793. IN operator, 110
  5794. INC procedure, 121
  5795. IncAddr, 167
  5796. INCL procedure, 121
  5797. Indenting
  5798. program text, 19
  5799. Index checking, 135
  5800. Infix calls, 118
  5801. Info, 237
  5802. Init,222
  5803. Initialization, 122
  5804. Input
  5805. direct, 180
  5806. file, 146, 182
  5807. formatted from files, 191
  5808. formatted, 177
  5809. keyboard, 146, 173
  5810. redirection, 180
  5811. Insert,152
  5812. InsLine, 240
  5813. Install, 220
  5814. INTEGER type, 101
  5815. representation, 128
  5816. Interrupt directive, 135
  5817. Interrupt handlers, 140
  5818. InterruptRegisters, 206
  5819. Interrupt
  5820. disable, 208
  5821. Intr, 165
  5822. IntToStr, 154
  5823. IO module, 146, 173
  5824. lOresult, 188
  5825. IOTRANSFER, 206
  5826. Item, 151
  5827. Item, 137
  5828. Items, 152
  5829. KeyPressed, 180
  5830. Keys, 48, 50, 62, 84
  5831. Label declaration, 115
  5832. Language, 95
  5833. Length, 150
  5834. Lib module, 145, 156
  5835. Libraries
  5836. suppress, 73
  5837. Library modules
  5838. FIO, 182
  5839. FloatExc, 217
  5840. Graph, 226
  5841. IO, 173
  5842. Lib, 156
  5843. MATHLIB, 211
  5844. Process, 220
  5845. ProcTrace, 218
  5846. Storage, 197
  5847. Str, 148
  5848. SYSTEM, 202
  5849. Window, 231
  5850. Library
  5851. /J option, 133
  5852. Line, 229
  5853. Line number
  5854. /N option, 133
  5855. Linker, 71
  5856. Linker
  5857. batch, 78
  5858. case sensitive, 74
  5859. errors, 71
  5860. line numbers, 73
  5861. map file, 74
  5862. options, 74, 79
  5863. segments, 137
  5864. suppress warnings, 74
  5865. trace references, 74
  5866. Listen, 208
  5867. Literal expression, 109
  5868. Load file, 59
  5869. LoadControlWord, 216
  5870. Local declaration, 116
  5871. Lock, 224
  5872. Log, 212
  5873. LoglO, 213
  5874. LONGCARD type, 100
  5875. LONGINT type, 101
  5876. LongJmp, 168
  5877. LONGREAL type, 101
  5878. LongToBcd, 215
  5879. LONGWORD type, 105, 118
  5880. LOOP statement, 25, 113
  5881. Main menu, 50
  5882. Main module, 68
  5883. Make, 69
  5884. /M option, 133
  5885. main module, 57, 68
  5886. MakeHeap,199
  5887. MAP-file, See File
  5888. Match, 153
  5889. MathError and MathError2, 169
  5890. MATHLIB module, 144, 211
  5891. MAX function, 120
  5892. Memory models, 137
  5893. Menu
  5894. actions, 86
  5895. customization, 79
  5896. definition file, 83
  5897. definition, 85
  5898. editor, 59
  5899. external commands, 82, 88
  5900. keys, 48
  5901. main, 50
  5902. options, 72
  5903. pop up, 59, 80, 83, 90
  5904. pull down, 83
  5905. MIN function, 120
  5906. MkDir, 194
  5907. Mod, 214
  5908. MOD operator, 110
  5909. MODULE keyword, 121
  5910. Module
  5911. case study, 25
  5912. initialization, 122
  5913. local, 124
  5914. priority, 122, 203, 207
  5915. Modulus, 110
  5916. Monitor, 218
  5917. Move, 160
  5918. Multiplying, 110
  5919. Name, 99
  5920. qualified, 123
  5921. Named constant, 107
  5922. NEAR, 135, 139
  5923. Nesting, 99
  5924. NEW procedure, 121
  5925. NewPriority, 207
  5926. NEWPROCESS, 204
  5927. NIL pointer checking, 136
  5928. NIL value, 107
  5929. NoSound, 172
  5930. NOT operator, 110
  5931. Notify, 223
  5932. NULLPROC
  5933. procedure value, 119 Number
  5934. decimal, 97
  5935. hexadecimal, 97
  5936. octal, 97
  5937. real, 97
  5938. OBJ-file, See File
  5939. ObscuredAt, 238
  5940. Octal numbers, 97
  5941. ODD function, 120
  5942. Ofs, 208
  5943. Open, 183, 233
  5944. Open array parameter, 27
  5945. Open array, 116, 131
  5946. Operands
  5947. Compatible, 110
  5948. Option, 132
  5949. See also: Directive
  5950. compiler, 73
  5951. editor, 65. 75
  5952. linker, 74, 79
  5953. load, 77
  5954. menu, 72
  5955. run, 74
  5956. save, 77
  5957. setup, 76
  5958. OR operator, 110
  5959. ORD function, 120
  5960. Out, 209
  5961. Output
  5962. file, 146, 182
  5963. formatted to files, 188
  5964. formatted, 174
  5965. redirection, 180
  5966. screen, 146, 173
  5967. Overflow checking, 135
  5968. Palette Constants and Types, 243
  5969. PaletteColor, 244 PaletteColorUsed, 245
  5970. PaletteOpen, 244 ParamCount, 160 ParamCount, 34 Parameter, 115
  5971. actual, 118
  5972. case study, 24 compatible, 118 declaration, 116 formal, 116
  5973. passing conventions, 131
  5974. string, 118
  5975. value, 116
  5976. VAR, 116
  5977. ParamStr, 34, 160 Permutations
  5978. of a string, 22
  5979. Plot, 228
  5980. Point, 229
  5981. POINTER, 105
  5982. keyword, 104
  5983. representation, 129 Pointer
  5984. absolute, 104
  5985. based, 104
  5986. case study, 35 constructor, 109 designate type, 99 normalized, 166 opaque, 122
  5987. Polygon, 230
  5988. Pop up menus, 48, 59, 80, 83
  5989. Pop up, 90
  5990. Pos, 151
  5991. Pow, 213
  5992. Predefined identifier, 100
  5993. Priority
  5994. module, 122
  5995. Procedure declaration, 115
  5996. Procedure, 28
  5997. activation, 130
  5998. body, 116
  5999. case study, 21, 24, 37
  6000. FAR/NEAR directive, 135 predefined, 119 representation, 129
  6001. type, 119
  6002. Process module, 145, 220
  6003. Process
  6004. high-level, 220
  6005. low-level, 203
  6006. priority, 221
  6007. scheduler, 220
  6008. signals, 221
  6009. ProcTrace module, 147, 218
  6010. Production, 98
  6011. Program
  6012. terminate, 172
  6013. Pull down menus, 83
  6014. PutBeneath, 235
  6015. PutOnTop, 235
  6016. Pythagorean triples, 18
  6017. QSort, 157
  6018. Quicksort, 37, 156
  6019. Quit
  6020. to DOS, 58
  6021. RAND,158
  6022. RANDOM, 158
  6023. RANDOMIZE, 158
  6024. Range, See subrange
  6025. RdBin, 194
  6026. RdBool, 178, 192
  6027. RdCard, 178, 192
  6028. RdChar, 178, 192
  6029. RdHex, 178, 192
  6030. Rdlnt, 178, 192
  6031. Rdltem, 179, 193
  6032. RdKey, 180
  6033. RdLn, 179
  6034. RdLngCard, 178, 192
  6035. RdLngHex, 178, 192
  6036. RdLnglnt, 178, 192
  6037. RdLngReal, 178, 192
  6038. RdReal, 178, 192
  6039. RdShtCard, 178, 192
  6040. RdShtHex, 178, 192
  6041. RdShtlnt, 178, 192
  6042. RdStr, 178, 193
  6043. Rd'simple type’, 177, 192
  6044. ReadFirstEntry, 195
  6045. ReadNextEntry, 196
  6046. REAL type, 101
  6047. representation, 128
  6048. Real
  6049. Number, 97
  6050. RealToStr, 154
  6051. Recoloring
  6052. help lines, 91
  6053. RECORD keyword, 103
  6054. RECORD type, 105
  6055. representation, 129 Record
  6056. aggregate, 107
  6057. case study, 32, 41
  6058. field selection, 108
  6059. variant, 104
  6060. RedirectInput, 181
  6061. Redirection file, 77
  6062. RedirectOutput, 181
  6063. Register
  6064. segment, 139
  6065. $C directive, 135
  6066. Registers, 130
  6067. Remainder, 110
  6068. Rename, 186
  6069. REPEAT statement, 25, 113
  6070. Representation
  6071. data types, 128
  6072. Resident programs, 141
  6073. RETURN statement, 117
  6074. Rexp, 214
  6075. RmDir, 195
  6076. Run-time
  6077. default checks, 73
  6078. error, 70 Segment, 137
  6079. based pointer, 104
  6080. code, 135
  6081. compiler generated, 138
  6082. data, 135
  6083. register, 139
  6084. SEND, 222
  6085. Separator, 97
  6086. Session file, 58
  6087. SET keyword, 102
  6088. SET type, 105
  6089. representation, 129
  6090. Set
  6091. element, 102
  6092. operations, 110
  6093. SetFlags, 210
  6094. SetFrame, 234
  6095. SetJmp and LongJmp, 168
  6096. SetJmp, 168
  6097. SetPalette, 244
  6098. SetPaletteColor, 245
  6099. SetProcessLocks,243
  6100. SetReturnCode,171
  6101. SetTitle, 234
  6102. Setup
  6103. options, 76
  6104. SetWrap, 242
  6105. Shifting, 110
  6106. SHORTADR type, 105
  6107. SHORTCARD type, 100
  6108. ShortCut keys, 84
  6109. SHORTINT type, 101
  6110. Sin, 211
  6111. SinH, 212
  6112. Size, 187
  6113. SIZE function, 120
  6114. Slice, 151
  6115. Save file, 61
  6116. ScanL, 162
  6117. ScanNeL, 163
  6118. ScanNeR, 163
  6119. ScanR, 162
  6120. Scope, 124
  6121. Seek, 187
  6122. Seg, 209 Snow check, 76
  6123. Sorting
  6124. lines of a text file, 32
  6125. Sound, 20, 171
  6126. Sqrt, 215
  6127. Stack
  6128. checking, 136
  6129. frame, 130
  6130. $S directive, 136
  6131. StartProcess, 221
  6132. Startscheduler, 221
  6133. StopScheduler, 221
  6134. Storage module, 145, 197
  6135. Storage
  6136. heaps, 145, 197
  6137. segment lay out, 137
  6138. StoreControlWord, 216 StoreEnvironment, 217 Str module, 144, 148 String
  6139. assignment, 111
  6140. constant, 107 conversions, 148, 153 handling, 144
  6141. literal, 97
  6142. parameter, 118 permutations, 22 procedures, 149 zero-termination, 148
  6143. StrToCard, 156
  6144. StrToInt, 155
  6145. StrToReal,156
  6146. SubAddr, 167
  6147. Subprogram, See procedure
  6148. Subrange checking, 136
  6149. Subrange
  6150. case study, 29
  6151. Subroutines, See procedure
  6152. Substring, 151
  6153. Subtracting, 110
  6154. Suffix, 107
  6155. Syntax, 95, 98
  6156. Syntax error, 95
  6157. SYSTEM module, 144, 202
  6158. Tail recursion, 38
  6159. Tan, 211
  6160. TanH, 212
  6161. Terminate,172
  6162. TextBackground, 241
  6163. TextColor, 241
  6164. TextMode, 228
  6165. Token
  6166. alternatives, 97 definition of, 96 generic, 96 Top, 237 Top scroll zone, 76 Trace directive, 136 TRANSFER, 205 Tree
  6167. data structure, 38 Trigonometric functions, 211 TRUNC function, 120 Truncate, 186 Type
  6168. ARRAY, 102 base, 102 BOOLEAN, 101 CARDINAL, 100 case study, 20 cast, 120 compatibility, 105, 118 compound, 105 designated, 104, 99 enumeration, 101 INTEGER, 101 numeric, 101 ordinal, 101 POINTER, 104 procedure, 119 REAL, 101 RECORD,103 SET, 102 subrange, 102 transfer, 120
  6169. Type conversion case study, 22
  6170. TYPE declaration, 100, 122
  6171. Unlock, 225 Use, 235 Used, 237 UserBreak, 169
  6172. VAL conversion, 120 VAL function, 120 Value parameter, 116
  6173. VAR declaration, 106
  6174. WrLngCard, 174, 188
  6175. WrLngHex, 174, 188
  6176. WrLnglnt, 174, 188
  6177. WrLngReal, 174, 188
  6178. WrReal, 174, 188
  6179. WrShtCard, 174, 188
  6180. WrShtHex, 174, 188
  6181. WrShtlnt, 174, 188
  6182. WrStr, 176, 190
  6183. WrStrAdj, 176, 190
  6184. VAR parameter, 116 Variable absolute, 106 control, 114 declaration, 106 global, 122 local, 116 procedure, 119 volatile /V option, 133 volatile option, 73 volatile $W directive, 136
  6185. Visibility, 123
  6186. Volatile, 133, 136
  6187. VS I ZE function, 120
  6188. WAIT, 223
  6189. WhereX, 239
  6190. WhereY, 239
  6191. WHILE statement, 25, 112
  6192. Window module, 147, 231 Window
  6193. changing, 90
  6194. classes, 91 definition, 233 frame, 233 management, 233 output, 240
  6195. palette, 243 recoloring, 91 repositioning, 90 resizing, 90
  6196. zoom, 52
  6197. WITH statement, 32, 114
  6198. WORD type, 105, 118
  6199. WordFill, 162 WordMove, 161 WrBin, 191 WrBool, 174, 188 WrCard, 174, 188 WrChar, 174, 188 WrCharRep, 177, 191 WrHex, 174, 188 Wrlnt, 174, 188 WrLn, 177, 191
  6200. Jensen & Partners UK Ltd. 63 Clerkenwell Road London EC1M 5NP England
  6201. Jensen & Partners International, Inc.
  6202. 1101 San Antonio Road. Suite 301 Mountain View. CA 94043
  6203. • Press |lAfil|[R]| to Run a program
  6204. • Type
  6205. prog7 followed by ||Enter||.
  6206. FIGURE 4-2 TopSpeed Modula-2 screen after specifying command line arguments
  6207. The system will compile, make, and link your program, and will then execute it — as if you had typed
  6208. prog7 stest.raw stest.srt
  6209. at the main DOS command line.
  6210. The program uses an array of pointers to represent the file. If x is a pointer variable, xA denotes the object which x points at — that is, the object whose address is the current value of x. Each line of the file is allocated the exact amount of storage it requires. The FIO module (file input/output) is used to read and write disk files. The calls to FIO.AssignBuffer could be omitted, but this would cause the program to run much more slowly. The size of the buffer supplied has been chosen to optimize the disk accesses.
  6211. Note that you need to close the output file, using FIO. Close, as otherwise the buffer assigned for this file would not be flushed.
  6212. The procedure Lib. HSort sorts information using an algorithm known as a Heap­sort. This procedure takes three parameters: the number of elements in the array to be sorted, and two procedure parameters, which are routines to compare and ex­change elements.
  6213. Another sorting routine, Lib. QSort, could have been used instead. This procedure uses Quicksort, a different sorting algorithm, which is faster than Heapsort on the average, but is much slower in its worst case performance than Heapsort.
  6214. Implementing Quicksort The implementation of Lib. QSort is instruc­tive because it uses a recursive (nested) procedure. Let’s take a look at it. Here are the relevant extracts from lib. def:
  6215. DEFINITION MODULE Lib;
  6216. TYPE
  6217. CompareProc = PROCEDURE(CARDINAL, CARDINAL):BOOLEAN;
  6218. SwapProc » PROCEDURE(CARDINAL, CARDINAL);
  6219. PROCEDURE QSort(n:CARDINAL; Less:CompareProc; Swap:SwapProc);
  6220. END Lib.
  6221. And here is the relevant material from the implementation module, lib .mod:
  6222. IMPLEMENTATION MODULE Lib;
  6223. The module definition contains type definitions for two procedure types. These are used as parameters for QSort. Notice that the actual procedure definitions are not provided in the Lib module. You must provide these two procedures when you call QSort (or Lib. QSort). The procedure parameter enables you to pass in the information needed for QSort to use your procedures.
  6224. ShortCut |Alt||R||
  6225. To run your completed program within the environment do either of the following:
  6226. • Select the Run command on the Main Menu
  6227. • Use the ShortCut command |Alt||[R||
  6228. Providing the Auto Make Option is set ON, this function will first perform an auto­matic Make, if any editing has taken place since the last Make. Then a full screen window is opened in which your program is executed. When your program has fin­ished, you are prompted to press IIEscll to return to the environment. This environ­ment will be in exactly the same state as it was when you left. You may move the prompt window using |ScrollLock|| if you need to view beneath (see “Repositioning Windows,” on page 90).
  6229. To time the execution of your program exactly, you can set the Timed Run option (see “Timed Run,” page 75).
  6230. Run-Time Errors You can get TopSpeed Modula-2 to report run-time errors when running your program — by setting the appropriate compiler directives. If you are running within the environment then you can be taken to the exact position in your source where the error occurred. This powerful feature allows you to quickly find and correct common run-time errors.
  6231. Here is a list of the compiler directives that enable it to report the run-time errors, and a brief description of the check performed:
  6232. (* *$!+*) Index Out Of Range
  6233. Checks for out of range array index values.
  6234. (*$O+*) Arithmetic Overflow
  6235. Checks on arithmetical operations for overflow.
  6236. (* $ S+*) Stack Overflow
  6237. Checks for stack overflow on procedure calls. (NOTE: you cannot continue the program after such an error).