mr Ribi Samir_ dipl

Document Sample
mr Ribi Samir_ dipl Powered By Docstoc
					ELEKTROTEHNIĈKI FAKULTET
UNIVERZITETA U SARAJEVU



mr Ribić Samir, dipl.el. ing




                               PROJEKTOVANJE
                                 SISTEMSKOG
                                  SOFTVERA




                                   (radna skripta)
                                   (treće izdanje)



                                   Sarajevo, 2005
2
                                                                 3
1. VRSTE SISTEMSKOG SOFTVERA
Prije uĉenja razvoja sistemskog softvera potrebno je upoznati se sa osnovnim vrstama sistemskog softvera

1.1.        Sistemski softver
Sistemski softver je svaki softver namijenjen za izvršenje aplikativnih programa, ali koji nije specifiĉan ni za jednu posebnu
aplikaciju. Sistemski softver tipiĉno ukljuĉuje operativne sisteme za kontrolu izvršenja programa, softver za korisniĉko
okruţenje kao što su interpretatori komandne linije, prozorski sistemi i desktopi, razvojne alate kao što su asembleri,
kompajleri, linkeri biblioteke, interpreteri, generatori unakrsnih referenci, kontrolori verzija, make programi, debageri,
profajleri i softver za praćenje te pomoćne alatke za sortiranje, štampanje i editovanje i mnogi drugi softver.

1.2.        Sistemski softver za kontrolu izvršenja programa
       - Operativni sistemi
       Operativni sistem je softver koji kontroliše izvršenje raĉunarskih programa i pruţa pored toga razliĉite servise.
       - BIOSi i ROM monitori
        Softver koji se obiĉno nalazi u fiksnoj memoriji ROM i omogućuje minimalni rad raĉunara zakljuĉno sa uĉitavanjem
       operativnog sistema dijeli se na BIOSe i monitore. BIOS obiĉno sadrţi samo pasivne rutine koje operativni sistemi koriste
       i koje omogućuju rad sa osnovnim periferijskim ureĊajima, dok ROM monitori imaju i neke primitivne metode za
       interakciju s korisnicima.
       - Loaderi
       Loader (punilac) smješta korisniĉki program smješten na periferijskom ureĊaju u fiziĉku memoriju obavljajući pri tome
       relokaciju programa na odgovarajuće adrese i uĉitavanje dinamiĉkih biblioteka ako ih program koristi.
       - Simulatori
       Simulator je mašina ili program koji simulira ţeljeno okruţenje (moţe biti drugi raĉunar, hemijski proces, sociološki
       sistem ili bilo šta drugo) u svrhu uĉenja ili istraţivanja.
       - Emulatori
       Specijalizovani simulator koji simulira drugu mašinu i arhitekturu u odnosu na onu na kojoj se izvršava omogućivši
       upotrebu gotovo svog softvera namijenjenog za drugu mašinu naziva se emulator.
       - Drajveri
       Drajver je program koji odreĊuje kako će kompjuter komunicirati sa periferijskim ureĊajem u svrhu standardiziranog rada
       aplikativnih programa sa periferijskim ureĊajima.
       - DBMS Serveri
       Programi koji brinu o centralizovanom ĉuvanju podataka u cilju brzog dobivanja podataka nazivaju se serveri za
       upravljanje bazom podataka (DataBase Management Server)
       - Spuleri
       Vrše rasporeĊivanje slanja podataka na printere kako bi se izbjeglo miješanje podataka na papiru
       - Mreţni serveri
       Programi koji omogućavaju pristup raznim vrstama informacija preko mreţe

1.3.        Softver za korisničko okruţenje
       - Interpreteri komandne linije
       Interpreter komandne linije je program koji ĉita tekstualne komande od strane korisnika ili iz datoteke i izvršava. Neke od
       ovih komandi se izvršavaju unutar samog interpretera, dok druge izazivaju startovanje drugih datoteka.
       - Grafički sistemi prozora
       Grafiĉki sistem prozora je softver koji omogućuje da se ekran radne stanice podijeli u pravougaona podruĉja koja se
       ponašaju kao odvojeni ulazno/izlazni ureĊaji pod kontrolom razliĉitih aplikativnih programa, što daje korisniku mogućnost
       da vidi izlaz iz razliĉitih procesa istovremeno i odabere koji će primati ulaz, obiĉno pokazavši na njega mišem.

1.4.        Razvojni alati
       - Asembleri
       Asembleri prevode program u asemblerskom jeziku u mašinski jezik.
       - Kompajleri
       Kompajler dekodira instrukcije napisane u jeziku višeg nivoa i proizvodi program u asemblerskom ili mašinskom jeziku.
       - Linkeri
       Linkeri kombinuju jednu ili više datoteka koje sadrţe objektni kod iz separatno prevedenih modula u jedinstvenu datoteku
       koja sadrţi uĉitljiv ili izvršni kod. Ovaj proces zahtijeva razrješenje referenci meĊu modulima i popravku informacija o
       relokaciji koje koristi jezgro operativnog sistema prilikom uĉitavanja datoteke u memoriju radi izvršenja programa koji je
       u njoj.
       - Parseri
       Parseri su programi koji dijele kod u funkcionalne komponente. Obiĉno su sastavni dio kompajlera.
       - Kompajler kompajleri
                                                                   4
       Kompajler kompajleri su alatke koje generišu izvorni kod parsera, interpretera ili kompajlera iz navedenog opisa jezika
       (obiĉno u BNF formi)
       - Disasembleri
       Disasembleri prevode program u mašinskom jeziku u program u asemblerskom jeziku.
       - Dekompajleri
       Dekompajleri prevode program u mašinskom jeziku ili pseudomašinskom kodu u jezik visokog nivoa.
       - Kros asembleri
       Krosasembleri su asembleri koji se izvršavaju na drugoj vrsti raĉunarske arhitekture od one ĉiji se mašinski kod generiše.
       - Kros kompajleri
       Krosakompajleri su kompajleri koji se izvršavaju na drugoj vrsti raĉunarske arhitekture od one ĉiji se mašinski kod
       generiše.
       - Interpreteri
       Interpreteri su programi koji prevoĊenje izvornog jezika i izvršavanje prevedenog koda obavljaju u istom ciklusu obiĉno
       obraĊujući po jednu liniju u vremenu.
       - Pseudokompajleri
       Pseudokompajleri su varijanta kompajlera koja ne generiše pravi mašinski kod, nego pseudomašinski kod koji je niţeg
       nivoa od izvornog jezika, ali zahtijeva poseban interpreter za svoje izvršavanje.
       - Pseudoasembleri
       Pseudoasebmleri su varijanta asemblera koja ne generiše pravi mašinski kod, nego pseudomašinski kod koji je niţeg nivoa
       od izvornog jezika, ali zahtijeva poseban interpreter za svoje izvršavanje.
       - Profajleri i monitori performansi
       Profajleri mjere vrijeme provedeno u pojedinaĉnim dijelovima korisniĉkog programa u svrhu poboljšanja brzine
       aplikacije. Monitori performansi mjere zauzeće raznih vrsta resursa (procesora, memorije, diska, mreţe...) u sistemu.
       - Generatori unakrsnih referenci
       Generatori unakrsnih referenci prikazuju odnose izmeĊu razliĉitih procedura u razliĉitim modulima.
       - Kontrolori verzija
       Da bi se izbjegli konflikti izmeĊu razliĉitih programera koji rade nad istim datotekama izvornog koda, uvode se kontrolori
       verzija koji ĉuvaju centralizovano sve datoteke iz navedenog projekta ukljuĉivo i njihove ranije verzije.
       - Translatori izvornog koda
       Translatori izvornog koda prevode program napisan u jednom programskom jeziku višeg nivoa u drugi programski jezik
       višeg nivoa.
       - Generatori izvornog koda i CASE alati
       Generatori izvornog koda automatski generišu izvorni kod u višem programskom jeziku ili asemblerskom jeziku na bazi
       navedenih parametara. Integrisani sa softverom za projektovanje ĉine CASE alate (Computer Aided Software
       Engineering)
       - make
       Make je program koji odreĊuje, zavisno od vremena zadnje izmjene datoteka, da li je potrebno pokretati asemblere,
       kompajlere i linkere nad odreĊenim datotekama.
       - Debageri
       Debageri su programi koji pomaţu u lociranju i ispravci grešaka u programima. Mogu da prate programe na nivou
       izvornog i izvršnog koda
       - Biblioteke
       Skup potprograma namijenjenih programerima koji obavljaju odreĊene funkcije

1.5.        Pomoćne alatke
       - Editori
        Programi koji obavljaju funkcije ureĊivanja, modifikacije i brisanja podataka zovu se editori. Editori mogu biti
       specijalizovani za tekstualne ili binarne podatke.
       - Sortirači
       Sortiraĉi su programi za ureĊivanje podataka odreĊenim redoslijedom
       - Backup programi
       Backup programi kopiraju podatke na pomoćni medij radi njihovog ĉuvanja u sluĉaju gubitka
       - Kriptografski programi
       Kriptografski programi šifriraju podatke u neĉitljiv oblik radi spreĉavanja neovlaštene analize
       - Kompresioni programi
       Kompresioni programi konvertuju podatke u formate koji zauzimaju manje memorijskih resursa
       - Mreţni klijenti
       Mreţni klijenti koriste usluge mreţnih servera u svrhu prijema i obrade podataka

1.6.        Rezime poglavlja
         Navedeno je dosta definicija razliĉitih vrsta sistemskog softvera koji obuhvata softver za kontrolu izvršenja programa,
korisniĉko okruţenje, razvojne i pomoćne alatke.
                                                                                  5
2. PROCESOR I OPERATIVNI SISTEM ZA KOJE SE GENERIŠE KÔD
         Intelov Pentium je danas apsolutno dominantan mikroprocesor, pa će se i u navedenim primjerima on koristiti u
razvoju kompajlera. Slijedi upoznavanje sa najvaţnijim registrima i instrukcijama ovog procesora:

2.1.          Registri
              Za aplikativne programe na mikroprocesorima 486 i Pentium bitni su sljedeći 32 bitni registri:
                 EAX, donjih 16 bita se zove AX, donjih 8 bita se zove AL
                 EBX, donjih 16 bita se zove BX, donjih 8 bita se zove BL
                 ECX, donjih 16 bita se zove CX, donjih 8 bita se zove CL
                 EDX, donjih 16 bita se zove DX, donjih 8 bita se zove DL
                 ESI, donjih 16 bita se zove SI
                 EDI, donjih 16 bita se zove DI
                 ESP, donjih 16 bita se zove SP
                 EBP, donjih 16 bita se zove BP
                 EFLAGS koji se sastoji od flegova (jednobitnih vrijednosti), od kojih su najvaţniji:
              CF – postavlja se na 1 ako se desio aritmetiĉki prijenos,
              ZF - postavlja se na 1 ako je rezultat operacije jednak 0,
              DF – odreĊuje da li će se registri SI i DI uvećavati ili umanjivati nakon svake instrukcije koje operišu sa memorijskim
              blokovima (MOVS, SCAS itd),
              OF – postavlja se na 1 ako je rezultat operacije izmeĊu dva predznaĉena broja broj netaĉnog predznaka,
              SF – postavlja se na 1 ako je rezultat operacije negativan broj
                 FP koprocesor posjeduje osam 128 bitnih registara koji su organizovani u formi kruţnog bafera i zovu se ST(0),
                  ST(1) , ST(2) , ST(3) , ST(4) , ST(5) , ST(6) , ST(7) .

2.2.          Adresni reţimi
                 Ako se u instrukciji navodi samo ime registra, tada se pristupa vrijednosti koju on sadrţi, npr. INC EAX.
                 Navodi li se ime registra u uglastoj zagradi, uz eventualni pomak, npr.
                  MOV ESI,[EBP+12] , pristupa se vrijednosti koja se nalazi na adresi koju bi pokazivao navedeni registar kada bi
                  bio uvećan za navedeni pomak. Ako je pomak jednak 0, tada se on ne navodi, npr. ADD ECX,[EBX]
                 Umjesto apsolutnih adresa, mogu se u asemblerskom kodu navoditi labele, npr.
                  MOV GLOBALV[20],EAX
                 Za distinkciju veliĉine varijable navode se modifikatori BYTE PTR, WORD PTR , DWORD PTR i QWORD
                  PTR, koji predstavljaju 8, 16, 32 ili 64 bit.
                 Dekadne konstante se navode jednostavno, npr. MOV EDX,1221. Heksadekadne konstante imaju znak h
                  naveden iza konstante. Ako instrukcije imaju dva operanda, rezultantni je obiĉno prvi navedeni operand i on ne
                  moţe biti konstanta. Nisu dopuštene ni instrukcije koje operišu izmeĊu dvije memorijske lokacije. Moraju se u
                  tim sluĉajevima koristiti registri za meĊurezultate.

2.3.          Instrukcije
        U tabeli na slici Sl. 2.3.1 dat je spisak korištenih instrukcija. Argumenti instrukcija su navedeni kao $C1 i $C2 i
umjesto njih se navode imena registara ili memorijske lokacije kao u podpoglavlju 2.2.
Opšti oblik         Opis                                                                                          Primjer

ADD $C1,$C2         Sabira $C1 sa $C2 i rezultat smješta u $C1                                                    ADD EAX,[ESI]

AND $C1,$C2         Logički konjuguje bit po bit $C1 sa $C2 i rezultat smješta u $C1                              AND SI,3

CALL $C1            Poziva potprogram na navedenoj adresi                                                         CALL PODPROGRAM

CDQ                 Predznačno proširuje EAX u EDX. Najviši bit registra EAX se kopira u sve bite registra EDX.   CDQ
CLD                 Briše directional flag, potrebno za instrukcije blokova                                       CLD
                                                                               6
CMP $C1,$C2     Poredi $C1 sa $C2 i ažurira flegove                                                            CMP EAX,PODATAK[8]

FADD            Sabira dva broja na vrhu FP steka i rezultat smješta na vrh FP steka umjesto njih              FADD

FCHS            Mijenja predznak broju na vrhu FP steka                                                        FCHS

FCOMPP          Poredi dva broja na vrhu FP steka, briše ih, a postavlja flegove koprocesora                   FCOMPP

FDIVR           Dijeli broj ispod vrha FP steka sa brojem na vrhu FP steka i rezultat stavlja umjesto njih     FDIVR

FILD $C1        Cjelobrojnu vrijednost sa memorijske lokacije stavlja na vrh FP steka                          FILD DWORD PTR [EBX]

FINIT           Inicijalizira matematički koprocesor                                                           FINIT

FISTP $C1       Vrijednost sa vrha FP steka konvertuje u cjelobrojnu i stavlja u navedenu memorijsku           FISTP DWORD PTR [ESP]
                lokaciju
FLD $C1         FP vrijednost iz memorije stavlja na vrh steka                                                 FLD QWORD PTR [EBP+2]

FMUL            Množi dva broja na vrhu steka i rezultat smješta na vrh steka umjesto njih.                    FMUL

FSTP $C1        Vrijednost sa vrha FP steka stavlja u navedenu memorijsku lokaciju                             FSTP REZULTAT

FSTSW AX        Flegove koprocesora prebacuje u AX registar                                                    FSTSW AX
FSUBR           Od broja ispod vrha FP steka oduzme broj na vrhu FP steka i rezultat stavlja umjesto njih      FSUBR

IDIV $C1        Predznačno dijeli 64 bitni broj čija je viša riječ u EDX a niža u EAX sa navedenim 32 bitnim   IDIV ECX
                registrom ili sadržajem memorijske lokacije, rezultat stavlja u EAX, ostatak u EDX

IMUL $C1        Predznačno množi EAX sa navedenim registrom. Viša riječ 64-bitnog rezultata je u EDX a         IMUL ECX
                niža u EAX
JMP $C1         Program nastavlja izvršavanje od adrese navedene.                                              JMP LABELA2

JNE $C1         Skače na navedenu adresu ako Zero flag nije jednak 1                                           JNE NETACNO

LEA $C1,$C2     U registar $C1 se smješta adresa operanda $C2                                                  LEA EAX,[ESI+5]

MOV $C1,$C2     U registar $C1 se smješta vrijednost operanda $C2                                              MOV ECX,EDI

MUL $C1         Nepredznačno množi EAX sa navedenim registrom. Viša riječ 64-bitnog rezultata je u EDX a       MUL ESI
                niža u EAX
NEG $C1         Mijenja predznak cijelog broja                                                                 NEG EAX

NOT $C1         Logički invertuje sve bitove cijelog broja                                                     NOT DWORD PTR [EDI]
OR $C1,$C2      Logička disjunkcija bit po bit $C1 sa $C2 i rezultat smješta u $C1                             OR EAX,EDX

POP $C1         Sa adrese koju pokazuje ESP uzima vrijednost, smješta je u navedeni registar i uveća ESP       POP ESI
                za 4
PUSH $C1        Umanji ESP za 4 i na adresu koju pokazuje ESP smješta navedenu vrijednost                      PUSH EBP

REP MOVSB       Prebacuje blok velik ECX bajtova sa adrese navedene u ESI na adresu koju pokazuje EDI          REP MOVSB

RET $N1         Smjesti broj sa vrha steka u programski brojač, čime se vraća iz potprograma i uveća ESP       RET 8
                za navedenu vrijednost
SAHF            Prebacuje bite iz AH u Flag registar                                                           SAHF

SAL EAX,$N1     Pomjera ulijevo EAX za navedeni broj bita                                                      SAL EAX,4

SETA AL         Postavlja AL na 1 ako je CF =1, ZF=0 , inače AL postaje 0                                      SETA AL

SETB AL         Postavlja AL na 1 ako je CF =1, ZF=0 , inače AL postaje 0                                      SETB AL

SETE AL         Postavlja AL na 1 ako je ZF=1 , inače AL postaje 0                                             SETE AL
SETG AL         Postavlja AL na 1 ako je SF<>OF, ZF=0, inače AL postaje 0                                      SETG AL

SETL AL         Postavlja AL na 1 ako je SF =OF, ZF=0 , inače AL postaje 0                                     SETL AL

SETNE AL        Postavlja AL na 1 ako je CF =1, ZF=0 , inače AL postaje 0                                      SETNE AL

SUB $C1,$C2     Oduzima $C2 od $C1 i rezultat smješta u $C1                                                    SUB ECX,2

XOR $C1,$C2     Logička ekskluzivna disjunkcija $C1 sa $C2 i rezultat smješta u $C1                            XOR EAX,8

                            Sl. 2.3.1.                 Instrukcije Intel Pentium korištene u generisanju koda

2.4.        Operativni sistem
         Operativni sistem za koji se generiše kôd u kompajleru koji slijedi je 32 bitni Windows. Generisani programi su
predviĊeni da rade na njegovim verzijama poĉevši od Windows 3.1 sa Win32s, Windows 95, 98, ME, NT (sve verzije – 3.1,
3.5, 3.51 i 4.0),Windows 2000 i Windows XP.
          Generisani kôd je za korisniĉki reţim rada i omogućava pozive izuzetno velikog broja sistemskih funkcija. Na ovaj
naĉin, jezik ima bogatu podršku u bibliotekama procedura. Sistemske funkcije se nalaze u dinamiĉkim DLL datotekama.


2.5.        Rezime poglavlja
        Intelovi mikroprocesori 486 i Pentium imaju veliki broj instrukcija i umjeren broj registara. U ovom poglavlju su
navedene samo one instrukcije i adresni reţimi koje su zaista korištene u generisanju asemblerskog koda. Generisani kôd je
predviĊen za korisniĉki reţim rada pod operativnim sistemom Windows-32.
                                                                  7
3. UOBIČAJENI PRISTUPI U RAZVOJU KOMPAJLERA
        Osoba zainteresovana za pisanje novog ili analizu postojećeg kompajlera, bilo opisanog u udţbenicima, bilo iz
izvornog kôda, uglavnom ima na raspolaganju ĉetiri pristupa:
                Iterativni pristup
                Primjena generatora koda
                Analiza gotovog kompajlera
                Crenshawova netehnička metoda




3.1.           Iterativni pristup
         Ovaj pristup je najĉešće opisan u udţbenicima. Kompajler se dijeli na glavne cjeline: leksiĉki analizator, sintaksni
analizator, semantiĉki analizator, virtuelna mašina, generator koda, interpreter virtuelne mašine i optimizator koda. Cijeli
programski jezik i kompajler se prethodno projektuju, a zatim se razvijaju cjeline navedene gornjim redoslijedom, uz
objašnjenje teoretskih osnova parsiranja. Prednosti pristupa su
          Ovaj pristup je vrlo sistematiĉan i uglavnom ne divergira od izvorne ideje kako bi konaĉna verzija jezika trebala da
           izgleda. Konaĉna verzija je najĉešće podskup nekog klasiĉnog programskog jezika.
          Pristup je primjenjiv za širok dijapazon kompajlera za razne programske jezike, ali i razvoj drugih sistemskih
           programa: interpretera, translatora, asemblera, uljepšivaĉa izvornog koda, itd.
Mane pristupa su:
          Nepogodan je za kratke kurseve. Ono ĉemu kompajler sluţi, generisanje koda, dolazi tek na kraju knjige ili kursa, pa
           je potrebno preći oko 150-200 strana ili gotovo cijeli semestar da bi cijela tema imala smisla.
          Već u startu se operiše sa velikim listinzima, jer je odmah zamišljeno praćenje sintakse cijelog jezika.
          Obiĉno se generiše kôd za virtuelnu, a ne realnu mašinu. Virtuelne mašine zahtijevaju poseban interpreter (uz to
           nepreglednog) pseudo koda, što umanjuje kvalitet kompajlera (spor i odvojen od sistema prevedeni program). Te
           mašine su obiĉno stek orijentisane, za razliku od realnih mašina koje su registarski orijentisane.
          Realizacija pojedinih jeziĉkih koncepata nije u skladu sa njihovim prioritetima. Koncept slogova je manje bitan od
           koncepta cijelih brojeva, ali se ovim pristupom oba uĉe istovremeno.


3.2.           Primjena generatora koda
         Vrlo su popularni programi koji se zovu kompajler-kompajleri. Ovi programi (LEX, YACC, Bison, COCO/R) iz
Bacus-Naurove forme generišu izvorni kôd leksiĉkog i sintaksnog analizatora koji se kasnije ruĉno proširuje. Prednosti ovog
pristupa su:
          Skraćeno vrijeme razvoja, jer su dvije faze kompajliranja, leksiĉka i semantiĉka analiza, korektno već uraĊene.
          Prednosti iterativnog pristupa su zadrţane.
Mane pristupa su:
          Automatski generisani kôd moţe biti priliĉno nepregledan, pa je potrebno vrijeme za njegovo shvaćanje.
          Upotrebom ovih alata se ne nauĉi kako se piše kompajler, nego kako se koriste ti alati.
          Prevelika je razlika izmeĊu veliĉine kompaktne BNF forme i generisanog sintaksnog analizatora nastalog iz te BNF
           forme.
          Ostaje problem jeziĉkih koncepata razliĉitog prioriteta.




3.3.           Analiza gotovog kompajlera
         Mnogi kompajleri se mogu naći na Internetu sa kompletnim izvornim kodom, a ĉesto i propratnom knjigom koja
objašnjava rad kompajlera. Najpoznatiji takvi programi su GNU C i Small C. Izvorni kôd se moţe slobodno analizirati i
modifikovati, mada se iz njega obiĉno ne smiju praviti komercijalni kompajleri. Prednosti pristupa su:
          Mnogi besplatni kompajleri predstavljaju pune implementacije programskih jezika po ISO ili ANSI standardima.
                                                                8
           Gotovi kompajleri su posebno upotrebljivi za brzi razvoj kros-kompajlera (koji generišu kôd za druge platforme) ili
            popravak optimizatora koda.
            Mane pristupa su:
           Odštampani listinzi ovih kompajlera zauzimaju nekoliko stotina strana. Praćenje takvih listinga je izuzetno teško.
           Veliki listing ne daje mnogo informacija o tome kojim putem je on nastao.
           Ostaje problem jeziĉkih koncepata razliĉitog prioriteta.


3.4.        Crenshaw-ova netehnička metoda
         Ova metoda je predloţena u seriji ĉlanaka na Internetu “Let‟s build a compiler”, autora dr Jacka Crenshawa u periodu
1988-1993. Kreće se sa daleko manjim ambicijama, npr. varijable su jednoslovne i nema kljuĉnih rijeĉi, ali se odmah ide u
generisanje koda, dok se sam jezik postepeno razvija. Prednosti pristupa su:
           Ako je vremenski faktor problem, ĉitalac moţe da odustane dosta rano, a da je ipak nauĉio suštinu procesa.
           Jeziĉki koncepti se uvode prema svom znaĉaju.
           Listinzi su u poĉetku vrlo mali i jezgroviti (100-200 linija) a rastu dosta linearno.
           Odmah se razvija kôd za realnu mašinu i to generisanjem preglednog asemblerskog koda umjesto nepreglednog
            mašinskog koda ili pseudokoda.
Mane pristupa su
           Moţe doći do divergencije u razvoju. U originalnoj seriji ĉlanaka se to i dogodilo zbog zauzetosti autora i velikog
            vremenskog trajanja serije ĉlanaka, tako da serija nije dovedena do kraja, a tri puta se poĉinjalo iz poĉetka.
           Ponekad prelazak u narednu fazu implementacije nije moguć zbog koncepata koje je nametnula prethodna faza. Na
            primjer, ako je prethodna faza jezika definisala da se varijable deklarišu na odreĊeni naĉin, koji nije kompatibilan s
            tipom podataka planiranom za uvoĊenje u narednoj fazi, tada treba ili odustati od tog tipa ili nanovo napisati dio koda
            koji implementira deklaraciju varijabli.
           Originalna metoda, ne podrţava neke bitne elemente savremenih programskih jezika, kao što su slogovi, nizovi,
            višedimenzionalni nizovi i veze s operativnim sistemom.
           Metoda ne podrţava optimizaciju koda i oporavak od grešaka.


         Pristup objašnjen u ovom radu je, u osnovi, Crenshaw-ov pristup, ali doveden do kraja, bez divergiranja, sa logiĉnim
koracima iz faze u fazu, te sa originalnim programskim jezikom koji se razvija u fazama. Sam kompajler je pisan bez
korištenja Crenshawov-og izvornog koda i pruţa znatno veće mogućnosti.


3.5.        Waterfall i spiralni pristup razvoju informacionih sistema
       Klasiĉne“waterfall” metodologije razvoja zasnivaju se na lancu: Analiza, Dizajn, Programiranje, Testiranje,
Odrţavanje, Napuštanje( Sl. 3.5.1),



           Analiz
                             Dizajn
           a                                    Progra
                             D                                    Test
           A                                    m                                    Odrţa
                                                                  T                                  Napušt
                                                P                                    va
                                                                                                     a
                                                                                     O
                                                                                                     N
                                   Sl. 3.5.1.         Klasični “Waterfall” pristup razvoju softvera




          Spiralni pristupi (Sl. 3.5.2) podrazumijevaju da se ove faze obavljaju svaki put kada se razvija nova verzija programa,
proizišla iz stare. Tako se razvija sve moćniji i moćniji softver. Geometrijska forma spirale vjerno predstavlja ovo širenje
softvera.
                                                                9

                                         A                  O


                                              T         P           T
                               D
                                          O                 D
                                                   A
                                                                     P
                                               A                              O
                                                            D
                                          P
                                                            T
                                      Sl. 3.5.2.        Spiralni pristup u razvoju softvera



3.6.      Programski jezik u kome se razvija kompajler
         Pošto je svrha razvoja kompajlera za FILDZAN-32 njegova primjena u nastavi, odluĉeno je da se sam kompajler piše
u programskom jeziku Pascal. Ta odluka danas zvuĉi neobiĉno, jer se sistemski softver obiĉno piše u jezicima C ili C++, ali
bitna prednost Pascala je u njegovoj preglednosti, što je od velike vaţnosti za nastavu. Treba reći da za Pascal već postoji
mnogo dobrih komercijalnih i besplatnih kompajlera kao što su Delphi, Kylix, FreePascal, TurboPascal, Virtual Pascal 2 i
P2C. Kompajler za FILDZAN-32 je napisan tako da se lako prevodi bilo kojim od navedenih Pascal-skih kompajlera.




3.7.      Hardversko i softversko okruţenje za koje se razvija kompajler
        Jedan od glavnih ciljeva ove metode je razvoj kompajlera koji generiše kôd za konkretno, a ne virtuelno okruţenje. S
obzirom da na našem i svjetskom trţištu prevladavaju PC raĉunari sa Intel 486 i Intel Pentium procesorima, izbor ovih
mikroprocesora za generisanje koda je sasvim logiĉan. Ovi procesori ukljuĉuju i instrukcije za rad sa realnim brojevima.
         IzmeĊu dva vodeća operativna sistema za ove procesore, Windows i Linux, izabran je Windows kao, u ovom
trenutku, popularniji. Potrebne modifikacije kompajlera da generiše kôd za Linux su male.
        Oĉekuje se da će operativni sistemi bazirani na kompatibilnosti s Microsoft Windows platformama i Intelovim
mikroprocesora biti aktuelni bar do 2010 godine.



3.8.      Rezime poglavlja
         Uobiĉajeni pristupi, koji se mogu naći u literaturi, za uĉenje razvoja kompajlera su iterativni pristup, analiza gotovih
kompajlera, primjena generatora koda i Crenshaw-ov netehniĉki pristup. Svi pristupi imaju svojih prednosti i nedostataka. Za
kratke kurseve, koji trebaju da brzo daju konkretne rezultate najpogodniji je Crenshaw-ov pristup, ali je on ĉesto nepotpun. U
ovom prikazu razvoja kompajlera je korištena unapreĊena Crenshawova metoda.
                                                                10
4. PROSTI ARITMETIČKI IZRAZI
         Svaki programer koji je imao iskustva u radu s asemblerskim i višim programskim jezicima prvo uoĉava drastiĉnu
razliku u pristupu raĉunanju aritmetiĉkih izraza. U višim programskim jezicima se oponaša klasiĉna forma matematiĉkih
izraza, kakva je u upotrebi još od 18. vijeka. Ova forma je, doduše, prilagoĊena raĉunarskim tastaturama (kosa crta
umjesto razlomaĉke i zvjezdica umjesto podrazumijevanog mnoţenja), ali su prioriteti raĉunanja saĉuvani. Unutar jednog
izraza mnoţenje ima prioritet nad sabiranjem, a zagrade nad ostalim operacijama.


4.1.     Struktura tipičnih aritmetičkih izraza
         Asemblerski jezici (ali i neki viši programski jezici kao što su FORTH, Lisp, Befunge i rane verzije COBOL-a), s
druge strane, imaju instrukcije za istovremeno obavljanje samo jedne aritmetiĉke operacije nad dva argumenta. Programer
mora sam da odredi redoslijed izvršavanja ovakvih instrukcija da bi se dobio taĉan rezultat izraza. MeĊurezultati se moraj u
ĉuvati u registrima, memorijskim lokacijama ili na steku. Koliko ovo moţe biti komplikovano, svjedoĉi ĉinjenica da je
znaĉenje imena prvog višeg programskog jezika FORTRAN zapravo skraćenica od “prevodilac formula”.
        Stoga se i u ovom pristupu razvoju kompajlera kreće od prevoĊenja aritmetiĉkog izraza sa prioritetima               u
asemblerski program.
        Dva su uobiĉajena naĉina rješavanja ovog problema, nerekurzivni i rekurzivni. Nerekurzivni naĉin podrazumijeva
prevoĊenje iz aritmetiĉke (infiksne) u obrnutu poljsku notaciju (postfiksnu). U ovom radu je primijenjen rekurzivni naĉin, jer
on dovodi do kraćih listinga programa i konzistentniji je sa opisom sintakse jezika u proširenoj BNF formi ili sintaksnim
dijagramima.
        Nakon gledanja jednog tipiĉnog aritmetiĉkog izraza 2+3*4-8+(7-6*2) sa jednocifrenim brojevima, ali sa prioritetima i
zagradama, uoĉavaju se cjeline prikazane na slici Sl. 4.1.1.

                                           C1=2     C2=3       C3=4     C4=C2*C3
                                           C5=8     C6=7       C7=6
                                           C8=2 C9=C7*C8                C10=7
                                           C11=(C10-C9)
                                           C12=C1+C4-C5+C11


                            Sl. 4.1.1.         Cjeline u aritmetičkom izrazu 2+3*4-8+(7-6*2)
        Pogledavši cjelinu C12 (cijeli izraz) uoĉava se da se izraz sastoji od jednog ili više ĉlanova razdvojenih
znakovima plus ili minus. Primjećuje se da i izraz C11 unutar zagrada ima istu strukturu.
        Uoĉena struktura aritmetiĉkog izraza se predstavlja sintaksnim dijagramom na slici Sl. 4.1.2. Okruglim ili ovalnim
znakovima predstavljaju se simboli koji se dalje ne razraĊuju (terminalni) a ĉetvrtastim oni simboli koji se razraĊuju
(neterminalni).
        Izraz

                                                      -
                    Ĉlan                              -                  Ĉlan

                                                      +


                                                       Sl. 4.1.2.         Izraz
        Gledajući cjeline C1, C4, C5, i C11, te C10 i C9, uoĉava se da se ĉlan izraza sastoji od jednog ili više faktora,
razdvojenih zvjezdicom ili kosom crtom. Sam faktor je cifra ili, kao u cjelini C11, kompletan aritmetiĉki izraz koji poĉinje
otvorenom zagradom. Na slikama Sl. 4.1.3 i Sl. 4.1.4 prikazani su sintaksni dijagrami pojmova Član i Faktor.
        Član
                                                       *
                    Faktor                             -                 Faktor

                                                       /

                                                           Sl. 4.1.3.     Član
                                                            11
        Faktor

                                0

                                1

                                9




                       (               Izraz                  )


                                                     Sl. 4.1.4.        Faktor

4.2.     Sintaksna analiza aritmetičkih izraza
          Prateći sintaksne dijagrame, lako je sintaksno analizirati izraze. Svaki od dijagrama moţe se izdvojiti u posebnu
Pascal-sku proceduru, ili predstaviti odgovarajućim pseudokodom. Ĉvorišta u sintaksnim dijagramima gdje se pojam razdvaja
u više podsluĉaja se mapiraju u uslovna grananja u pseudokodu, a vraćanja na već proĉitani simbol u dijagramu se mapiraju u
petlje u pseudokodu. Stoga procedure Izraz , Faktor i Član izgledaju u pseudokodu kao na slici Sl. 4.2.1.

              Izraz:
              Pozovi Član
              Sve dok je naredni simbol “+“ ili “- “ ,pozovi Član
              Član:
              Pozovi Faktor
              Sve dok je naredni simbol “*” ili “/“ , pozovi Faktor
              Faktor:
              Ako je naredni simbol cifra, faktor je u redu,
              Ako je naredni simbol “(“pozovi Izraz, zatim očekuj simbol “)”
                                     prijavi grešku. Pseudokod: Izraz, Član, Faktor
              U ostalim slučajevima,Sl. 4.2.1.

4.3.     Generisanje koda za računanje aritmetičke izraze
         Intelovi 32 bitni procesori imaju umjeren broj procesorskih registara. Stoga, nije moguće cijeli aritmetiĉki izraz
drţati u registrima, ali ga nema smisla ni u potpunosti drţati na steku ili memorijskim lokacijama. Pošto je prethodnim
operacijama izraz razloţen na njegove sastavne komponente, uglavnom se operiše sa glavnim registrom, EAX i pomoćnim
registrom EBX. Trenutni meĊurezultat se uvijek ĉuva u registru EAX, u kome je i jedan od operanada. Drugi operand je u
registru EBX.
      Lako je prevesti faktor koji se sastoji od jedne konstante. Dovoljno je izvršiti odgovarajuću komandu
MOV EAX,NN da se konstanta smjesti u registar EAX. Npr. konstanta 3 se prevodi u MOV EAX,3
          Kada su u pitanju prevoĊenja izraza ili ĉlanova, na primjer, ĉuvanje u registrima postaje nedovoljno. Stoga se pri
uoĉavanju sabiranja, oduzimanja, mnoţenja ili dijeljenja, registar EAX mora saĉuvati na steku, jer će poziv procedure za
raĉun drugog operanda promijeniti sadrţaj ovog registra. Po okonĉanju ove procedure, vrijednost sa steka se stavlja u EBX
registar za komutativne operacije. Za nekomutativne operacije registar EAX se prebaci u EBX, a zatim vrijednost sa steka
stavlja u EAX registar. Preostaje još da se obavi odgovarajuća ADD, SUB, IMUL ili IDIV instrukcija, ĉime registar EAX
ponovo sadrţi meĊurezultat.
        Tako se sabiranje prevodi u
               Pozovi Član
               Sve dok slijedi znak sabiranja, generiši naredne instrukcije
                   PUSH EAX
                   Pozovi Član
                   POP EBX
                   ADD EAX,EBX
                                                           12
         Pozivom procedure Ĉlan uvijek se dobija meĊurezultat u EAX. Instrukcijom POP EBX se u EBX registar smješta
vrijednost sa vrha steka. Ako se sa stekom paţljivo postupa, što će se raditi u cijelom procesu razvoja, na vrhu steka se
nalazi sadrţaj EAX registra nakon raĉunanja prvog sabirka. Stoga će registar EBX imati vrijednost prvog sabirka, a registar
EAX vrijednost drugog sabirka. Posljednjom instrukcijom dobija se zbir u registru EAX.
       Kako je i mnoţenje komutativno generisani kôd za mnoţenje je sliĉan. IMUL instrukcija će uzgred pokvariti sadrţaj
EDX registra, ali se bitan dio meĊurezultata ĉuva u EAX registru.
            Pozovi Faktor
            Sve dok slijedi znak množenja, generiši naredne instrukcije
                PUSH EAX
                Pozovi Faktor
                POP EBX
                IMUL EBX


          Oduzimanje nije komutativno, pa se mora prvi operand smjestiti u EAX, a drugi u EBX. Stoga generisani kôd moţe
izgledati ovako:
            Pozovi Član
            Sve dok slijedi znak oduzimanja, generiši naredne instrukcije
                  PUSH EAX
                  Pozovi Član
                  MOV EBX,EAX
                  POP EAX
                  SUB EAX,EBX
         Dakle, instrukcijom MOV EBX,EAX u registar EBX smiješta se drugi operand, dok će instrukcija POP EAX
pokupiti prvi operand sa steka.
          Dijeljenje, pored toga što nije komutativno, zahtijeva da se u EDX nalazi predznaĉno proširen EAX registar, što se
radi instrukcijom CDQ. Predznaĉno proširenje predstavlja kopiranje najvišeg bita EAX registra u sve bite EDX registra.
           Pozovi Faktor
           Sve dok slijedi znak dijeljenja, generiši naredne instrukcije
               PUSH EAX
               Pozovi Faktor
               MOV EBX,EAX
               POP EAX
               CDQ
               IDIV EBX
        Nakon cijele rutine, registar EAX će sadrţati koliĉnik, a EDX ostatak pri dijeljenju.


4.4.     Prva verzija kompajlera
        Nakon analize strukture aritmetiĉkog izraza i pseudokoda za sintaksnu analizu dijelova izraza te generisanja
mašinskog koda, moţe se pristupiti pisanju prve verzije kompajlera u Pascalu. Na slici Sl. 4.4.1 data je prva verzija
kompajlera, koji je prosti prevodilac prostog aritmetiĉkog izraza koji se unosi sa tastature i prikazuje na ekranu.
                                                               13



         Sl. 4.4.1.        Prevodilac         st: string;
                                            begin
                                                                                                    Emit(' IDIV EBX');
                                                                                                  end;
                        izraza                case znak of                                 end;
program Kompajler;                               '0'..'9': begin                        end;
var                                                  rezultat := UzmiKonstantu;       end;
  pozicija: integer;                                 Str(rezultat, st);
  znak: char;                                        Emit(' MOV EAX,' + st);          procedure Izraz;
  linija: string;                                  end;                               var
                                                 '(': begin                             z: char;
procedure Emit(st: string);                          Novi;                            begin
begin                                                Izraz;                             Clan;
  WriteLn(st);                                       Novi;                              while (znak in ['+', '-']) do begin
end;                                               end                                     Emit(' PUSH EAX');
                                              else                                         z := znak;
procedure Novi;                                  WriteLn('Greska');                        Novi;
begin                                         end;                                         Clan;
  pozicija := pozicija + 1;                 end;                                           case z of
  if pozicija <= Length(linija) then                                                         '+': begin
     znak := linija[pozicija]               procedure Clan;                                       Emit(' POP EBX');
  else                                      var                                                   Emit(' ADD EAX,EBX');
     Halt;                                    z: char;                                          end;
end;                                        begin                                            '-': begin
                                              Faktor;                                             Emit(' MOV EBX,EAX');
function UzmiKonstantu: integer;              while (znak in ['*', '/', '%']) do                  Emit(' POP EAX');
var                                             begin                                             Emit(' SUB EAX,EBX');
  rezultat: integer;                            z := znak;                                      end;
begin                                           Emit(' PUSH EAX');                         end;
  rezultat := ord(znak) - ord('0');             Novi;                                   end;
  Novi;                                         Faktor;                               end;
  UzmiKonstantu := rezultat;                    case z of
end;                                              '*': begin                          begin
                                                       Emit(' POP EBX');                pozicija := 0;
procedure Izraz; forward;                              Emit(' IMUL EBX');               ReadLn(linija);
                                                    end;                                Novi;
procedure Faktor;                                 '/': begin                            Izraz;
var                                                    Emit(' MOV EBX,EAX');          end.
  rezultat: integer;                                   Emit(' POP EAX');
                                                       Emit(' CDQ');




         Iz listinga se uoĉava da pored procedura pored procedura Izraz, Clan i Faktor, koje su prikazane u pseudokodu
postoje i procedure Emit, Novi i UzmiKonstantu. Procedura Emit je prosti ispis stringa na ekranu. Procedura Novi je
najznaĉajnija procedura. Ona varijablu pozicija uvećava za 1 i zatim dohvati odgovarajući znak iz unesene linije u
varijablu znak. Ta varijabla sadrţi sljedeći simbol. Procedura UzmiKonstantu dohvata jednocifreni broj i koristeći funkciju
ord dolazi do njegove numeriĉke vrijednosti.


4.5.     Testni primjer
        Sa tastature se unosi sljedeći izraz:
        2+3*4-8+(7-6*2);
Kada ovaj primjer proĊe kroz kompajler, dobije se asemblerski listing na slici Sl. 4.5.1. (Zadnji simbol u primjeru moţe biti
taĉka-zarez, ali i bilo koji drugi jer se ignoriše). Uz asemblerski listing dat je komentar sadrţaja registara i steka nakon
izvršenja svake od instrukcija


 MOV EAX,2       EAX=2, EBX=?,      stek =()                     PUSH EAX          EAX=6, EBX=8, stek =(6)
 PUSH EAX        EAX=2, EBX=?,      stek =(2)                    MOV EAX,7         EAX=7, EBX=8, stek =(6)
 MOV EAX,3       EAX=3, EBX=?,      stek =(2)                    PUSH EAX          EAX=7, EBX=8, stek =(7,6)
 PUSH EAX        EAX=3, EBX=?,      stek =(3,2)                  MOV EAX,6         EAX=6, EBX=8, stek =(7,6)
 MOV EAX,4       EAX=4, EBX=?,      stek =(3,2)                  PUSH EAX          EAX=6, EBX=8, stek =(6,7,6)
 POP EBX         EAX=4, EBX=3,      stek =(2)                    MOV EAX,2         EAX=2, EBX=8, stek =(6,7,6)
 IMUL EBX        EAX=12, EBX=3,      stek =(2)                   POP EBX           EAX=2, EBX=6, stek =(7,6)
 POP EBX         EAX=12, EBX=2,      stek =()                    IMUL EBX          EAX=12, EBX=6, stek =(7,6)
 ADD EAX,EBX     EAX=14, EBX=2,      stek =()                    MOV EBX,EAX       EAX=12, EBX=12, stek =(7,6)
 PUSH EAX        EAX=14, EBX=2,      stek =(14)                  POP EAX           EAX=7, EBX=12, stek =(6)
 MOV EAX,8       EAX=8, EBX=2,      stek =(14)                   SUB EAX,EBX       EAX=-5, EBX=12, stek =(6)
 MOV EBX,EAX     EAX=8, EBX=8,      stek =(14)                   POP EBX           EAX=-5, EBX=6, stek =()
 POP EAX         EAX=14, EBX=8,      stek =()                    ADD EAX,EBX       EAX=1, EBX=6, stek =()
 SUB EAX,EBX     EAX=6, EBX=8,      stek =()
                       Sl. 4.5.1.         Asemblerski listing prevedenog koda sa tokom izvršavanja


        Dakle, kao rezultat izvršenja programa sa slike Sl. 4.5.1 dobiva se 1, što se slaţe sa vrijednošću aritmetiĉkog izraza.
Naravno da bi ruĉno pisani asemblerski program bio daleko kraći. No, raĉunar gleda ulaz sekvencijalno i ne moţe odmah
pojednostaviti program, jer ne vidi unaprijed da li je uopšte potrebno npr. saĉuvati EAX registar. U ovom trenutku
optimizacija koda ima niţi prioritet jer se moţe i bez nje. Daleko je bitniji problem što su izrazi samo sa jednocifrenim
brojevima, nema varijabli i kontrolnih struktura, niti unarnih operatora. No, najveći nedostatak sadašnje verzije kompajlera
                                                               14
je što ona prevodi samo jednu jedinu liniju sa tastature na ekran. Prevedeni kôd se još uvijek ne moţe asemblirati, i njegovo
izvršavanje se simulira na papiru.


4.6.     Rezime poglavlja
         Razvoj kompajlera kreće od prevodioca prostog aritmetiĉkog izraza. U strukturi jednog tipiĉnog aritmetiĉkog izraza
sa zagradama i prioritetima uoĉavaju se odreĊene cjeline, Izraz, Ĉlan i Faktor koje se definišu sintaksnim dijagramima i
realizuju odgovarajućim procedurama. U realizacija ĉetiri osnovne aritmetiĉke operacije se koriste odgovarajuće instrukcije
mikroprocesora, a meĊurezultati se uvijek ĉuvaju u EAX. Prva verzija kompajlera prevodi samo uneseni aritmetiĉki izraz, s
jednocifrenim brojevima sa tastature. Testni primjer za prvu verziju kompajlera je uspješan, no programski jezik u ovom
trenutku nema nikakvih kontrolnih struktura, niti mogućnost prevoĊenja iz datoteka.
                                                                 15
5. PREVOĐENJE IZ DATOTEKA, BLOKOVI, VIŠECIFRENI BROJEVI
         Prva verzija kompajlera prevodi samo jedan jedini aritmetiĉki izraz u asemblerski jezik. Aritmetiĉki izraz se ne moţe
saĉuvati na disku nego se svaki put mora ponovo unositi. Izlazne asemblerske naredbe se takoĊe ne mogu direktno proslijediti
asembleru u cilju generisanja izvršnog koda.


5.1.     Format instrukcija
         Da bi se ovaj prevodilac mogao zvati kompajlerom višeg programskog jezika a ne prevodiocem jednog izraza,
neophodno je omogućiti da se izvorni kod iz jedne datoteke prevodi u asemblerski ili mašinski kod u drugoj datoteci. Iako
postoje kompajleri koji sve rade u memoriji, ipak su oni koji prevode iz datoteke u datoteku neuporedivo upotrebljiviji. Pored
ovoga, ulazni program treba da se sastoji od više naredbi ili aritmetiĉkih izraza, da bi se uopšte moglo govoriti o programu.
          U ovom trenutku donosi se jedna kljuĉna odluka u izboru koncepcije programskog jezika vezano za format pisanja
njegovih naredbi. U praksi postoje tri takva formata. Bajtovski format (mašinski jezik, Befunge, Forth) definiše da jedna
naredba zauzima jedan bajt ili svega nekoliko njih. Linijski format (asemblerski jezik, Fortran, BASIC, XBASE) odreĊuje da
se jedna naredba (ponekad i više od jedne) sadrţi u jednoj liniji izvornog koda. Slobodni format (Pascal, Lisp, C, Java) dopušta
da se naredbe pišu u više redova. Kako je slobodni format ujedno i najpraktiĉniji, bit će primijenjen i u programskom jeziku
koji se sada razvija.
         Odluka o izboru slobodnog formata povlaĉi sljedeću odluku: Da li za oznake poĉetka i kraja grupe naredbi koristiti
kljuĉne rijeĉi (kao u Pascalu) ili simbole (kao u C-u). Prepoznavanje simbola je jednostavnije od prepoznavanja kljuĉnih rijeĉi,
pa će ovaj jezik više podsjećati na C nego na Pascal, iako će kasnije imati elemenata i jednog i drugog jezika. Osim toga,
kljuĉne rijeĉi će biti uvedene znatno kasnije.


5.2.     Blokovi
          Skup naredbi se zove blok i uokviren je vitiĉastim zagradama. Ipak, iz praktiĉnih razloga prepoznavanja simbola, prva
vitiĉasta zagrada je sastavni dio drugih struktura. Iza svake naredbe unutar bloka se nalazi simbol taĉka-zarez (;). Program se
sastoji od vitiĉaste zagrade i jednog bloka. To se moţe predstaviti sintaksnim dijagramima na slikama Sl. 5.2.1 i Sl. 5.2.2.
         Program:
                          {                   Blok
                                                       Sl. 5.2.1.       Program
         Blok

                              Izraz                       ;             }




                                                         Sl. 5.2.2.         Blok
         Pseudokod za realizaciju bloka izgleda kao na slici Sl. 5.2.3
                           Sve dok ne slijedi “}” izvrši Izraz i pokupi simbol “;”
                           Pokupi simbol “}”

                                        Sl. 5.2.3.            Pseudokod, relizacija blokova

5.3.     Modifikacije procedura kompajlera zbog prevoĎenja iz datoteke
        Procedura Novi treba da sada ĉita znakove iz ulazne datoteke, ignorišući blankove kao i neprintabilne znakove
(ASCII <32) i nove redove. Stoga je ona sada sloţenija. U pseudokodu procedura Novi izgleda ovako:
                 Početak sekvence
                 Uvećaj pokazivač unutar linije za 1
                 Ako je pokazivač prešao kraj linije Uvećaj brojač linija za 1, učitaj novu liniju s
    diska i pokazivač postavi na 1
                 Varijabli znak dodijeli slovo linije na poziciji pokazivača. Ako je linija prazna,
    dodijeli varijabli znak blanko
                 Ponavljaj sve dok je znak blanko ili neprintabilan, a nije kraj ulazne datoteke

                                          Sl. 5.3.1.           Pseudokod, procedura Novi
                                                             16


          Procedura IdiDo ima kao argument karakter. Ona treba da prijavi grešku ukoliko znak koji slijedi iz ulazne datoteke
nije onaj koji je naveden kao argument ove procedure.
         Procedura Greska ĉiji je argument string, prikazuje tekst greške na ekranu, zatvara datoteke i prekida izvršenje
kompajlera. Ovo moţe zvuĉati priliĉno nepraktiĉno, jer ovako dizajnirani kompajler prevodi samo do prve greške. Sa
današnjim raĉunarima i interaktivnim radom to ne mora biti problem, što dokazuje uspjeh Turbo Pascala koji je sve do svoje
desete verzije (Delphi 2) potpuno zanemarivao oporavak od grešaka. Oporavak od grešaka zahtijeva dosta dodatnog koda što
smanjuje razumljivost rada kompajlera.
        Procedura Emit se nije mnogo izmijenila. Umjesto na ekran, izlaz se šalje u izlaznu datoteku.


5.4.     Modifikacije kompajlera zbog generisanja datoteka sa asemblerskim kodom
         Nije dovoljno samo prevedene aritmetiĉke izraze usmjeriti u datoteku. Dobijeni asemblerski program treba prevesti
nekim 32-bitnim asemblerom, kakvi su MASM, TASM ili NASM. Osim toga, mora postojati i odreĊeni kôd da se program
uspješno završi i vrati kontrolu operativnom sistemu. U programerskom ţargonu taj dio koda se zove entry stub ili ulazni kôd
i on izgleda kao na slici Sl. 5.4.1 . U suštini je ovim reĉeno asembleru da generiše 32 bitni mašinski program, prilagoĊen
Windows operativnom sistemu. Nakon generisanog programa se nalazi poziv rutine za završetak procesa i rezervisano mjesto
za 26 varijabli.

         .386
         .MODEL FLAT,STDCALL
          OPTION CASEMAP:NONE
          EXTRN ExitProcess@4:NEAR
          .CODE
          ULAZ:
          JMP GLAVNI
       GLAVNI:
         .....
          generisani program
         .....
          PUSH 0
          CALL ExitProcess@4
          .DATA
          GLOBALV DD 26 DUP(0)
          END ULAZ

                              Sl. 5.4.1.        Entry stub – standardni asemblerski ulazni kôd
        Procedura Prevedi emituje ovaj ulazni kôd i poziva proceduru Blok. Procedura Prevedi se poziva iz procedure
Glavni, koja otvara ulaznu i izlaznu datoteku. Imena ovih datoteka se navode kao argumenti komandne linije prilikom poziva
kompajlera koristeći, npr.:
KOMP32V2 PRIMJER.JEZ PRIMJER.ASM
        Iako većina današnjih programa koristi menije umjesto komandne linije, zbog kratkoće programa i koncentracije na
proces kompajliranja a ne na korisniĉki interfejs, ovaj kompajler je realizovan u formi komande iz komandne linije.


5.5.     Proširenja aritmetičkih izraza
       Napravljene su odreĊene izmjene i u samim aritmetiĉkim izrazima. Najvaţnije je što numeriĉke
konstante nisu više jednocifrene. Dohvatanje konstante se moţe izvesti algoritmom sa slike Sl. 5.5.1
                 Uzmi konstantu
                 Rezultat postavi na 0
                 Sve dok je znak koji slijedi izmeĎu 0 i 9 rezultat postavi na
                  10 * rezultat + vrijednost cifre znaka, pa uzmi novi znak
                 Ako je znak blanko dohvati novi
                             Sl. 5.5.1.         Promijenjeni algoritam za dohvatanje konstante
        Lako je dodati operaciju ostatka pri dijeljenju koja se, u skladu sa konvencijom iz C-a, oznaĉava znakom %.
Dovoljno je obaviti operaciju dijeljenja i nakon nje izvršiti jedno
        MOV AX,DX
                                                               17
U skladu sa uvoĊenjem operacije ostatka pri dijeljenju mijenja se sintaksa jeziĉkog pojma ĉlan i ona sada izgleda kao na slici
Sl. 5.5.2. Nema potrebe pisati pseudokod, jer je modifikacija odgovarajuće procedure ĉlan trivijalna.
        Član

                                                    %

                    Faktor                          *                Faktor
                                                    -
                                                    /
                                                        Sl. 5.5.2.           Član
Jeziĉki pojam Faktor (ĉija je nova verzija prikazana na slici Sl. 5.5.3) i odgovarajuća procedura proširuju se unarnim
minusom. Implementacija unarnog minusa rekurzivno poziva Faktor, a nakon tog pozva dodaje se naredba NEG EAX             .
Faktor:

            -                 Faktor

                           Numeriĉka konstanta



                      (              Izraz                  )

                                                         Sl. 5.5.3.       Faktor
U prilogu 2 na kraju rada dat je listing druge verzije kompajlera. Tamnijom bojom slova su oznaĉene izmjene u odnosu na
prvu verziju.


5.6.      Testni primjer
        Na slici Sl. 5.6.1 primjer malog programa. Treba kreirati datoteku ulaz2.jez sa sljedećim sadrţajem:
        {
            2+3*8;
            6*8*(4-2);
        }
                               Sl. 5.6.1.        Primjer za testiranje prve verzije kompajlera
        Iza zadnje vitiĉaste zagrade potrebno je preći u novi red. Nakon kompajliranja ovog primjera sa
           KOMP32V2 ULAZ2.JEZ ULAZ2.ASM
        dobije se asemblerski listing prikazan na slici Sl. 5.6.2:
.386                                            MOV EAX,8                                  MOV EAX,2
.MODEL FLAT,STDCALL                             POP EBX                                    MOV EBX,EAX
OPTION CASEMAP:NONE                             IMUL EBX                                   POP EAX
EXTRN ExitProcess@4:NEAR                        POP EBX                                    SUB EAX,EBX
.CODE                                           ADD EAX,EBX                                POP EBX
ULAZ:                                         ;    6*8*(4-2);                              IMUL EBX
  JMP GLAVNI                                    MOV EAX,6                                 ;}
;{                                              PUSH EAX                                  ;}
;    2+3*8;                                     MOV EAX,8                                  PUSH 0
GLAVNI:                                         POP EBX                                    CALL ExitProcess@4
  MOV EAX,2                                     IMUL EBX                                  .DATA
  PUSH EAX                                      PUSH EAX                                  GLOBALV DD 26 DUP(0)
  MOV EAX,3                                     MOV EAX,4                                 END ULAZ
  PUSH EAX                                      PUSH EAX

                                   Sl. 5.6.2.       Asemblerski listing dobijen kompajlerom
          Prilikom generisanja listinga dodano je da se linija izvornog koda šalje u asemblerski program kao komentar. Iza te
linije obiĉno slijede asemblerske linije koje implementiraju navedenu liniju koda u višem programskom jeziku. Asemblerski
listing još uvijek nije pravi mašinski program. Da bi se on preveo u mašinski program, treba pokrenuti asembler, na primjer
Microsoftov MASM 6.14 komandom
                ml /c /coff /Fl ulaz2.asm
                                                            18
        što znaĉi da se prevodi bez linkovanja u Common object file format (coff) uz generisanje listinga. Kao rezultat ovog
asembliranja dobijaju se datoteke ulaz2.obj i ulaz2.lst. Datoteku u OBJ formatu sada treba povezati sa drugim takvim
datotekama ili bibliotekama rutina koje se nalaze u LIB datotekama. To se radi programom koji se zove linker. Kao primjer
uzima se Microsoftov LINK 5.12 i pokreće sa
              link /defaultlib:kernel32.lib /subsystem:console ulaz2.obj
          Ovo znaĉi da se ulaz2.obj povezuje sa bibliotekom funkcija kernel32.lib praveći ulaz2.exe Program ULAZ2.EXE
moţe se pokrenuti, neće pasti, nego se samo uspješno završava ne prikazujući ništa na ekranu. To je i za oĉekivati, pošto se
rezultati izraza samo smještaju u AX po njihovom izvršenju. Program bi se eventualno mogao pratiti korak po korak koristeći
debager.
          Na slici Sl. 5.6.3 dati su izgled LST datoteke koja daje heksadekadni prikaz generisanog mašinskog koda uz
odgovarajući asemblerski kôd, izgled objektne (OBJ) te izvršne (EXE) datoteke. Mnogi kompajleri direktno prevode u
objektnu ili izvršnu datoteku. Formati OBJ i EXE datoteka su, meĊutim, dosta sloţeni, nepregledni i glomazni i njihov opis je
izvan opsega ovog rada. No, poredeći prevedeni kôd u LST datoteci i posebno oznaĉene bajtove u OBJ i EXE datotekama na
slici Sl. 5.6.3 prepoznaje se da je program korektno preveden u mašinski jezik. Ostatak datoteke OBJ sadrţi tabele za
relociranje u sluĉaju spajanja razliĉitih modula. EXE datoteka, pored mašinskog koda testnog programa, sadrţi i dio koda koji
sprjeĉava izvršavanje programa pod 16-bitnim MS DOS-om, spisak dinamiĉkih biblioteka i rutina iz njih koje se uvezuju sa
korisniĉkim programom te relokacione tabele
                                                                                                                 Turbo Dump Version 5.0.16.4 Copyright (c) 1988, 1998 Borland
   Turbo Dump.    Version 5.0.16.4 Copyright (c) 1988, 1998 Borland International
                           Display of File ULAZ2.OBJ                                                             International
                                                                                                                                     Display of File ULAZ2.EXE
   000000:   4C   01   03   00   36   5F   84   3D   4C   01   00   00   0B   00   00   00   L...6_.=L.......
   000010:   00   00   00   00   2E   74   65   78   74   00   00   00   00   00   00   00   .....text.......    000000: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00    MZ..............
   000020:   00   00   00   00   42   00   00   00   8C   00   00   00   CE   00   00   00   ....B...........    000010: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00    ........@.......
   000030:   00   00   00   00   01   00   00   00   20   00   30   60   2E   64   61   74   ........ .0`.dat    000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   000040:   61   00   00   00   42   00   00   00   00   00   00   00   68   00   00   00   a...B.......h...    000030: 00 00 00 00 00 00 00 00 00 00 00 00 B0 00 00 00    ................
   000050:   D8   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   ................    000040: 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68    ........!..L.!Th
   000060:   40   00   30   C0   2E   64   72   65   63   74   76   65   AA   00   00   00   @.0..drectve....    000050: 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F    is program canno
   000070:   00   00   00   00   0C   00   00   00   40   01   00   00   00   00   00   00   ........@.......    000060: 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20    t be run in DOS
   000080:   00   00   00   00   00   00   00   00   00   0A   00   00   EB   00   B8   02   ................    000070: 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00    mode....$.......
   000090:   00   00   00   50   B8   03   00   00   00   50   B8   08   00   00   00   5B   ...P.....P.....[    000080: 5D 17 1D DB 19 76 73 88 19 76 73 88 19 76 73 88    ]....vs..vs..vs.
   0000A0:   F7   EB   5B   03   C3   B8   06   00   00   00   50   B8   08   00   00   00   ..[.......P.....    000090: 19 76 73 88 1D 76 73 88 E5 56 61 88 18 76 73 88    .vs..vs..Va..vs.
   0000B0:   5B   F7   EB   50   B8   04   00   00   00   50   B8   02   00   00   00   8B   [..P.....P......    0000A0: 52 69 63 68 19 76 73 88 00 00 00 00 00 00 00 00    Rich.vs.........
   0000C0:   D8   58   2B   C3   5B   F7   EB   6A   00   E8   00   00   00   00   3E   00   .X+.[..j......>.    0000B0: 50 45 00 00 4C 01 03 00 38 5F 84 3D 00 00 00 00    PE..L...8_.=....
   0000D0:   00   00   07   00   00   00   14   00   00   00   00   00   00   00   00   00   ................    0000C0: 00 00 00 00 E0 00 0F 01 0B 01 05 0C 00 02 00 00    ................
   0000E0:   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   ................    0000D0: 00 04 00 00 00 00 00 00 00 10 00 00 00 10 00 00    ................
   0000F0:   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   ................    0000E0: 00 20 00 00 00 00 40 00 00 10 00 00 00 02 00 00    . ....@.........
   000100:   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   ................    0000F0: 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00    ................
   000110:   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   ................    000100: 00 40 00 00 00 04 00 00 00 00 00 00 03 00 00 00    .@..............
   000120:   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   ................    000110: 00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00    ................
   000130:   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   ................    000120: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00    ................
   000140:   2D   65   6E   74   72   79   3A   55   4C   41   5A   20   2E   66   69   6C   -entry:ULAZ .fil    000130: 08 20 00 00 28 00 00 00 00 00 00 00 00 00 00 00    . ..(...........
   000150:   65   00   00   00   00   00   00   00   FE   FF   00   00   67   01   75   6C   e...........g.ul    000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   000160:   61   7A   32   2E   61   73   6D   00   00   00   00   00   00   00   00   00   az2.asm.........    000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   000170:   40   63   6F   6D   70   2E   69   64   FC   20   12   00   FF   FF   00   00   @comp.id. ......    000160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   000180:   03   00   2E   74   65   78   74   00   00   00   00   00   00   00   01   00   ...text.........    000170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   000190:   00   00   03   01   42   00   00   00   01   00   00   00   00   00   00   00   ....B...........    000180: 00 00 00 00 00 00 00 00 00 20 00 00 08 00 00 00    ......... ......
   0001A0:   00   00   00   00   00   00   2E   64   61   74   61   00   00   00   00   00   .......data.....    000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   0001B0:   00   00   02   00   00   00   03   01   68   00   00   00   00   00   00   00   ........h.......    0001A0: 00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00    .........text...
   0001C0:   00   00   00   00   00   00   00   00   00   00   00   00   00   00   04   00   ................    0001B0: 48 00 00 00 00 10 00 00 00 02 00 00 00 04 00 00    H...............
   0001D0:   00   00   00   00   00   00   00   00   20   00   02   00   5F   55   4C   41   ........ ..._ULA    0001C0: 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60    ............ ..`
   0001E0:   5A   00   00   00   00   00   00   00   01   00   20   00   02   00   2E   64   Z......... ....d    0001D0: 2E 72 64 61 74 61 00 00 54 00 00 00 00 20 00 00    .rdata..T.... ..
   0001F0:   72   65   63   74   76   65   00   00   00   00   03   00   00   00   03   01   rectve..........    0001E0: 00 02 00 00 00 06 00 00 00 00 00 00 00 00 00 00    ................
   000200:   0C   00   00   00   00   00   00   00   00   00   00   00   00   00   00   00   ................    0001F0: 00 00 00 00 40 00 00 40 2E 64 61 74 61 00 00 00    ....@..@.data...
   000210:   00   00   13   00   00   00   5F   45   78   69   74   50   72   6F   63   65   ......_ExitProce    000200: 68 00 00 00 00 30 00 00 00 02 00 00 00 08 00 00    h....0..........
   000220:   73   73   40   34   00   00   00   00   00   00   00   00   00   00   00   00   ss@4............    000210: 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0    ............@...
                                                                                                                 000220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                                                 000240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   Microsoft (R) Macro Assembler Version 6.14.8444                                                               000250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   09/15/02 12:21:42                                                                                             000260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   ulaz2.asm                                                                                                     000270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                    Page 1 - 1                                                                                   000280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                                                 000290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                                                 0002A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                        .386                     0002B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                                                 0002C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                        .MODEL FLAT,STDCALL
                                                                                                                 0002D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                        OPTION CASEMAP:NONE      0002E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                        EXTRN                    0002F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
   ExitProcess@4:NEAR                                                                                            000300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000000                                                   .CODE                                             000310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000000                                                   ULAZ:                                             000320: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000000 EB 00                                              JMP GLAVNI                                       000330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                        ;{                       000340: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                        ;    2+3*8;              000350: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                                                 000360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000002                                                   GLAVNI:                                           000370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000002       B8   00000002                                MOV EAX,2                                        000380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000007       50                                                                   PUSH EAX                 000390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000008       B8   00000003                                    MOV EAX,3                                    0003A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    0000000D       50                                                                   PUSH EAX                 0003B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    0000000E       B8   00000008                                    MOV EAX,8                                    0003C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000013       5B                                                                   POP EBX                  0003d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000014       F7   EB                                          IMUL EBX                                     0003E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000016       5B                                                                   POP EBX                  0003F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                                                 000400: EB 00 B8 02 00 00 00 50 B8 03 00 00 00 50 B8 08    .......P.....P..
    00000017       03   C3                                          ADD EAX,EBX                                  000410: 00 00 00 5B F7 EB 5B 03 C3 B8 06 00 00 00 50 B8    ...[..[.......P.
                                                                                        ;    6*8*(4-2);          000420: 08 00 00 00 5B F7 EB 50 B8 04 00 00 00 50 B8 02    ....[..P.....P..
    00000019       B8   00000006                                    MOV EAX,6                                    000430: 00 00 00 8B D8 58 2B C3 5B F7 EB 6A 00 E8 00 00    .....X+.[..j....
    0000001E       50                                                                   PUSH EAX                 000440: 00 00 FF 25 00 20 40 00 00 00 00 00 00 00 00 00    ...%. @.........
    0000001F       B8   00000008                                    MOV EAX,8                                    000450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000024       5B                                                                   POP EBX                  000460: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000025       F7   EB                                          IMUL EBX                                     000470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000027       50                                                                   PUSH EAX                 ........................................................
    00000028       B8   00000004                                    MOV EAX,4                                    0005D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                                                 0005E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    0000002D       50                                                                   PUSH EAX                 0005F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    0000002E       B8   00000002                                    MOV EAX,2                                    000600: 38 20 00 00 00 00 00 00 30 20 00 00 00 00 00 00    8 ......0 ......
    00000033       8B   D8                                          MOV EBX,EAX                                  000610: 00 00 00 00 46 20 00 00 00 20 00 00 00 00 00 00    ....F ... ......
    00000035       58                                                                   POP EAX                  000620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000036       2B   C3                                          SUB EAX,EBX                                  000630: 38 20 00 00 00 00 00 00 75 00 45 78 69 74 50 72    8 ......u.ExitPr
    00000038       5B                                                                   POP EBX                  000640: 6F 63 65 73 73 00 4B 45 52 4E 45 4C 33 32 2E 64    ocess.KERNEL32.d
    00000039       F7   EB                                          IMUL EBX                                     000650: 6C 6C 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ll..............
                                                                                        ;}                       000660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                        ;}                       000670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                                                                                                                 000680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    0000003B       6A 00                                        PUSH 0                                           .......................................................
    0000003D       E8 00000000 E                                CALL ExitProcess@4                               0009D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000000                                                   .DATA                                             0009E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    00000000       0000001A [                                  GLOBALV DD 26 DUP(0)                              0009F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
                        00000000
                       ]
                                                                                        END ULAZ




                                                                                        Sl. 5.6.3.              Izgled OBJ, LST i EXE datoteka
                                                              19
5.7.     Rezime poglavlja
         Format pisanja instrukcija u jeziku koji se razvija u ovom radu je slobodni, a od ove verzije kompajlera moguće je
prevoditi iz datoteke u datoteku. Program se više ne sastoji od jednog aritmetiĉkog izraza, već od bloka naredbi. Novi naĉin
prevoĊenja zahtijeva modifikaciju procedura Novi i Emit, a uvode se procedure IdiDo i Greska. Asemblerski programi
zahtijevaju odreĊeni kôd koji se zove Entry stub, pa kompajler generiše i njega. Da bi aritmetiĉki izrazi radili sa višecifrenim
brojevima modifikovano je dohvatanje konstante. Dodavanje unarnog minusa i ostatka pri dijeljenju zahtijeva promjenu
procedura Faktor i Clan. Iz testnog primjera uspješno se generiše asemblerski listing, a iz asemblerskog listinga se dobijaju
objektni i izvršni kôd.
Prilog 2: Verzija izvornog koda kompajlera br. 2
program Kompajler;                                                                        Novi;
const                                      procedure Izraz; forward;                      Clan;
  OCEKIVANO = 'Ocekivano ';                                                               case z of
  GRIZRAZ = 'Izraz';                       procedure Faktor;                                '+': begin
var                                        var                                                   Emit('   POP EBX');
  ulaz, izlaz: text;                         rezultat: integer;                                  Emit('   ADD EAX,EBX');
  pozicija, brojaclinija: integer;           st: string;                                       end;
  znak: char;                              begin                                            '-': begin
  linija: string;                            case znak of                                        Emit('   MOV EBX,EAX');
                                                '-': begin                                       Emit('   POP EAX');
procedure Greska(poruka: string);                   Novi;                                        Emit('   SUB EAX,EBX');
begin                                               Faktor;                                    end;
  WriteLn(poruka);                                  Emit(' NEG EAX');                     end;
  WriteLn(brojaclinija, ':', linija);             end;                                 end;
  Close(ulaz);                                  '0'..'9': begin                      end;
  Close(izlaz);                                     rezultat := UzmiKonstantu;
  Halt;                                             Str(rezultat, st);               procedure Blok;
end;                                                Emit(' MOV EAX,' + st);          begin
                                                  end;                                 while znak <> '}' do begin
procedure Emit(st: string);                     '(': begin                                Izraz;
begin                                               Novi;                                 IdiDo(';');
  WriteLn(izlaz, st);                               Izraz;                             end;
end;                                                IdiDo(')');                        IdiDo('}');
                                                  end;                               end;
procedure Novi;                              else
begin                                           Greska(GRIZRAZ);                     procedure Prevedi;
  repeat                                     end;                                    begin
     pozicija := pozicija + 1;             end;                                        Emit('.386');
     if pozicija > Length(linija) then                                                 Emit('.MODEL FLAT,STDCALL');
       begin                               procedure Clan;                             Emit('OPTION CASEMAP:NONE');
       brojaclinija := brojaclinija + 1;   var                                         Emit('EXTRN ExitProcess@4:NEAR');
       if not (Eof(ulaz)) then               z: char;                                  Emit('.CODE');
          ReadLn(ulaz, linija);            begin                                       Emit('ULAZ:');
       Emit(';' + linija);                   Faktor;                                   Emit(' JMP GLAVNI');
       pozicija := 1;                        while (znak in ['*', '/', '%']) do        pozicija := 0;
     end;                                       begin                                  Novi;
     if Length(linija) > 0 then                 z := znak;                             IdiDo('{');
       znak := linija[pozicija]                 Emit(' PUSH EAX');                     Emit('GLAVNI:');
     else                                       Novi;                                  Blok;
       znak := ' ';                             Faktor;                                Emit(' PUSH 0');
  until (znak > ' ') or Eof(ulaz)               case z of                              Emit(' CALL ExitProcess@4');
end;                                              '*': begin                           Emit('.DATA');
                                                       Emit(' POP EBX');               Emit('GLOBALV DD 26 DUP(0)');
procedure IdiDo(z: char);                              Emit(' IMUL EBX');              Emit('END ULAZ')
begin                                                end;                            end;
  if (znak <> z) then                             '/', '%': begin
     Greska(OCEKIVANO + z);                            Emit(' MOV EBX,EAX');         procedure Glavni;
  Novi;                                                Emit(' POP EAX');             var
end;                                                   Emit(' CDQ');                   linija: string;
                                                       Emit(' IDIV EBX');            begin
function UzmiKonstantu: integer;                       if z = '%' then                 Assign(ulaz, paramstr(1));
var                                                       Emit(' MOV EAX,EDX');        Assign(izlaz, paramstr(2));
  rezultat: integer;                                 end;                              brojaclinija := 0;
begin                                           end;                                   linija := '';
  rezultat := 0;                             end;                                      Reset(ulaz);
  while (znak >= '0') and (znak <= '9')    end;                                        Rewrite(izlaz);
     do begin                                                                          Prevedi;
     rezultat := 10 * rezultat +           procedure Izraz;                            Close(ulaz);
       ord(znak) - ord('0');               var                                         Close(izlaz);
     Novi;                                   z: char;                                  WriteLn('Prevedeno bez greske');
  end;                                     begin                                     end;
  if (znak = ' ') or (znak = '`') then       Clan;
     Novi;                                   while (znak in ['+', '-']) do begin     begin
  UzmiKonstantu := rezultat;                   Emit(' PUSH EAX');                      Glavni
end;                                           z := znak;                            end.
                                                                  20
6. VARIJABLE, RELACIONI OPERATORI, USLOVI, PETLJE
         Iako sposobna da generiše asemblerski kod, prethodna verzija kompajlera još uvijek ne liĉi na prevodilac pravog
programskog jezika jer nedostaju dvije izuzetno bitne stvari, mogućnost smještanja meĊurezultata u varijable i mogućnost
grananja programa. Stoga je potrebno uvesti elementarne kontrolne strukture, varijable i proširiti aritmetiĉke izraze.


6.1.      Proširenje aritmetičkih izraza
        Aritmetiĉki izraz se proširuje relacionim operatorima, operatorom dodjeljivanja, te unarnim operatorima. Za razliku
od Pascala, na primjer, dodjeljivanje nije poseban iskaz, nego sastavni dio aritmetiĉkog izraza (kao u C-u), te je pogodnije za
ovu koncepciju razvoja programskog jezika, koja kreće od koncepta izraza.
         Operator dodjeljivanja će, privremeno, biti dvotaĉka “:”. Primjer
         a:b:c:2;
         dodjeljuje varijabli c vrijednost 2, zatim se varijabla c dodjeli varijabli b, pa varijabla b varijabli a.
          Ovaj primjer dovodi do pojma lijeve i desne asocijativnosti operatora. Taj pojam odgovara na pitanje koji operandi se
prvi raĉunaju kada je prioritet više upotrijebljenih operatora jednak. Za sabiranje, oduzimanje, mnoţenje i dijeljenje korištena
je lijeva asocijativnost. Npr. 3+2-4 će prvo izraĉunati 3, njemu dodati 2 a zatim od toga oduzeti 4.
          Dodjeljivanje je desno asocijativno, što se vidi iz gore navedenog primjera. Već je u prvoj fazi pokazano da se
ponavljanje lijevo asocijativnih operatora realizuju while petljom. Suprotno tome, ponavljanje desno asocijativnih operatora
realizuje se rekurzijom unutar obrade desnog operanda.
         Relacioni operatori su =,>,< i # (razliĉito). Rezultat poreĊenja dva izraza moţe biti 0 ako je relacija netaĉna ili 1 ako
je taĉna. Ovi operatori nisu asocijativni, jer bi to dovelo do zbunjujućih situacija. Npr. izraz 3>2>1 u matematici je taĉan i
predstavlja ĉinjenicu da je broj 2 veći od 1 a manji od 3, ali u kontekstu izraza u raĉunaru ima sasvim drugu semantiku. Izraz
3>2 daje vrijednost 1, a zatim se ta vrijednost 1 poredi da li je veća od 1, što nije taĉno, pa cijeli izraz vraća vrijednost 0. Pošto
takva semantika nije mnogo korisna, neće biti realizovana.
         Operatori dodjeljivanja i relacioni operatori trebaju da imaju najniţi prioritet. To znaĉi da se mora definisati novi
jeziĉki pojam Izraz dodjeljivanja.
         Izraz dodjeljivanja
                                                         =

                                                         >

                                                         <
                                                                                       Izraz
                    Izraz
                                                         #


                                                                       Izraz
                                                         :             dodjeljivanja
                                                 Sl. 6.1.1.        Izraz dodjeljivanja
         Na dijagramu sa slike Sl. 6.1.1 se vidi da neasocijativni operatori (relacioni) sa desne strane imaju pojam Izraz dok se
za desno asocijativni operator dodjeljivanja sa desne strane nalazi pojam Izraz dodjeljivanja.
        Za realizaciju poreĊenja pomaţe instrukcija SETcc AL, gdje cc predstavlja uslov koji predstavlja testiranje flegova,
obiĉno vezano za rezultat prethodne instrukcije. Ova instrukcija postavlja AL na 1 ako je uslov ispunjen odnosno na 0 ako nije,
upravo ono što treba, bez korištenja uslovnih skokova. Generisani kôd za relacione operatore izgleda kao na slici Sl. 6.1.2
   Pozovi Izraz
   PUSH EAX
   Pozovi Izraz
   POP EBX
   CMP EBX,EAX
   SETE AL ili SETG AL ili SETL AL ili SETNE AL (respektivno na =,>,<,#)
   AND EAX,0FFh


                                     Sl. 6.1.2.         Generisani kôd za relacione operatore
                                                            21
         Dakle, analogno operaciji sabiranja, prvi operand se dobija u EBX, a drugi u EAX registru, a poreĊenje se vrši
CMP EBX,EAX instrukcijom. Rezultat poreĊenja se dobije u fleg registru, a zatim se odgovarajućom SETE, SETG, SETL ili
SETNE instrukcijom postavlja AL registar na ţeljenu vrijednost. Pošto preostala tri bajta registra EAX mogu imati sluĉajnu
vrijednost, posljednjom AND EAX,0FFh se oni postavljaju na nule.
         Kod dodjeljivanja, meĊutim, nije potrebna vrijednost prvog operanda, nego njegova adresa. Uzima se da se ova
adresa nalazi u EBX registru. To je dovoljno generalno rješenje, jer se vrijednost ne dodjeljuje samo varijablama, nego i nekim
izrazima (npr. onim koji su rezultati pointerskih operacija). Vrijednost drugog operanda se nalazi u EAX registru. Stoga je
generisani kôd za ovu operaciju oblika prikazanog na slici Sl. 6.1.3.

                                                      Izvrši Izraz
                                                      PUSH EBX
                                                      Izvrši Izraz dodjeljivanja
                                                      POP EBX
                                                      MOV [EBX],EAX
                                  Sl. 6.1.3.         Generisani kôd za operator dodjeljivanja
         U ovoj fazi se još uvijek jednostavnost kompajlera drţi u prvom planu. Stoga, imena varijabli, koje se upravo uvode,
su jednoslovna i to predstavljena malim slovima. To, u ovom trenutku, ukida potrebu za tabelom imena varijabli i
pretraţivanjem iste. Umjesto toga, svih 26 varijabli se moţe drţati u statiĉki alociranom prostoru.
         Statiĉki alociran prostor je deklarisan kao GLOBALV DD 26 DUP(0). Ovo znaĉi da će svaka varijabla zauzimati po 4
bajta.




            GLOBALV[0]- GLOBALV[3]                   GLOBALV[4]-GLOBALV[7]                         GLOBALV[8]...
            Varijabla a                              Varijabla b                                   Varijabla c



                                     Sl. 6.1.4.             Organizacija prostora za globalne varijable


       Pogledom na sliku Sl. 6.1.4, uoĉava se da ako se od ASCII koda imena varijable oduzme ASCII kôd slova 'a' i rezultat
pomnoţi sa 4, dobije se relativni pomak u odnosu na labelu GLOBALV a time i adresa traţene varijable.
          Nad varijablom se mogu obavljati dvije funkcije. Ona se moţe ĉitati, ali joj se moţe i dodijeliti vrijednost. Stoga je
potrebno da nakon pristupa varijabli registar EBX ima njenu adresu, a registar EAX njenu vrijednost. Dosljedno dosadašnjem
radu, vrijednost varijable c se moţe dobiti koristeći
             LEA EBX,GLOBALV[8]
             MOV EAX,[EBX]
         Da bi se uvele varijable potrebna je izmjena jeziĉkog pojma Faktor. Pored varijabli, u ovoj verziji kompajlera uvode
se i novi unarni operatori. Svi oni se realizuju na isti naĉin kao unarni minus uveden u prethodnoj verziji kompajlera, dakle
rekurzivnim pozivom procedure Faktor, a zatim generisanjem koda koji modifikuje registar EAX. Unarni operatori su
navedeni u tabeli na slici Sl. 6.1.5:


 Oznaka operatora   Znaĉenje operatora                                                             Instrukcije koje se generišu nakon
                                                                                                   poziva procedure Faktor
 -                  Aritmetiĉki unarni minus. Promjena predznaka registra EAX                      NEG EAX
 ~                  Binarna negacija. Pretvaranje svih nula u jedinice a svih jedinica u nule      NOT EAX
                    unutar binarnog zapisa registra EAX
 &                  Adresa operanda. Vraća adresu izraza koji slijedi (tipiĉno varijabla)          MOV EAX,EBX
 *                  Pointer/pokazivaĉ. Vraća cijeli broj koji se nalazi na adresi koja se dobije   MOV EBX,EAX
                    raĉunom izraza
                                                                                                   MOV EAX,[EBX]
 !                  Logiĉka negacija. Ako je EAX jednak 0 on dobija vrijednost 1, inaĉe            CMP EAX,0
                    dobija vrijednost 0
                                                                                                   SETE AL
                                                                                                   AND EAX,0FFh

                                                          Sl. 6.1.5.             Unarni operatori
                                                             22
        UvoĊenje unarnih operatora zahtijeva da se promijene sintaksni dijagram za jeziĉki pojam Faktor i odgovarajuća
procedura za implementaciju tog jeziĉkog pojma. Realizacija te procedure data je u okviru listinga u prilozima.
         Faktor:
                        -

                        ~

                        &                   Faktor

                        *

                        !

                                    Numeriĉka
                                    konstanta
                               (            Izraz                         )
                                            dodjeljivanja


                                       Varijabla

                                                        Sl. 6.1.6.         Faktor
         Uz dodatak relacionim operatorima, zgodno je ukljuĉiti i operatore konjunkcije, disjunkcije i ekskluzivne disjunkcije.
Iz C-a se preuzimaju operatori &,| i ^ koji vrše operacije bit po bit, pa su oni upotrebljivi i za maskiranja bitova. Kako su sve
tri operacije komutativne, realizacija je analogna sabiranju, sa kojim se dijeli i prioritet operacije. U tu svrhu se jeziĉki pojam
Izraz modifikuje da izgleda kao na slici Sl. 6.1.7.


                                                        -
                                                        Član
                                                               -
                                                               -
                                                               +
                                                                   Član




                     Ĉlan                               -
                                                        +


                                                        &                     Ĉlan

                                                        |

                                                        ^



                                                        Sl. 6.1.7.            Izraz
         Logiĉke operacije se prevode u kôd sa slike Sl. 6.1.8:

                            Pozovi Član
                            PUSH EAX
                            Pozovi Član
                            POP EBX
                            AND EAX,EBX ili OR EAX,EBX ili XOR EAX,EBX

                                    Sl. 6.1.8.         Generisani kôd za logičke operacije
         Pošto se ne dodaje novi operator prioriteta mnoţenja i dijeljenja, procedura Clan se ne mijenja.


6.2.      Uslovi
          Za realizovanje programskih struktura uslova i petlje, potrebno je koristiti skokove u asemblerskom jeziku. U ovoj
oblasti je generisanje asemblerskog programa jednostavnije od generisanja mašinskog programa, pogotovo kada su u pitanju
skokovi unaprijed. To omogućavaju labele. Labele u generisanom listingu imaju oblik L1, L2, L3..., pri ĉemu je broj iza slova
                                                           23
L smješten u cjelobrojnu globalnu varijablu TrenLabela. Procedurom NovaLabela se taj broj uveća za 1 i zatim vrati u formi
stringa.
         Uslov se moţe predstaviti sintaksnim dijagramom sa slike Sl. 6.2.1
         Uslov:


                ?            Izraz                   {             Blok               {             Blok
                             dodjeljivan
                             ja
                                                          Sl. 6.2.1.        Uslov


         Jezik još nema kljuĉnih rijeĉi, pa se uslov oznaĉava znakom ?, zatim slijedi izraz koji treba da vrati vrijednost 0 ili 1,
pa otvorena vitiĉasta zagrada i blok koji oznaĉavaju sekciju koja se izvršava ako je uslov ispunjen. Prethodni znak “?” je
prikazan isprekidanim linijama u sintaksnom dijagramu jer se ne prepoznaje u proceduri Uslov koja implementira uslove nego
u proceduri Blok. Na kraju jeziĉkog pojma Uslov nalazi se druga otvorena vitiĉasta zagrada i sekcija koja se izvršava ako
uslov nije ispunjen.

                                                 ? (a=3 & n>8)
                                                    {
                                                      b:8;
                                                      c:2;
                                                    }
                                                    {
                                                      b:12;
                                                    }

                                    Sl. 6.2.2.         Primjer uslova, treća verzija kompajlera
         Na slici Sl. 6.2.2 dat je primjer uslova koji radi sljedeće: Ako je varijabla a jednaka 3 i varijabla n veća od 8, varijabli
b se dodjeljuje vrijednost 8, a varijabli c vrijednost 2. Ako bar jedan od gornjih uslova nije ispunjen, varijabla b dobija
vrijednost 12.
         Uslov se smatra ispunjenim ako je rezultat izraza koji se ispituje razliĉit od nule. Izraz ima rezultat u EAX registru.
Stoga se uslov moţe realizovati kodom sa slike Sl. 6.2.3. Na slici se vidi da je potrebno generisati tri nove labele. Ovdje su one
oznaĉene sa Londa, Linace i Lkrajuslova, a u praksi mogu biti, na primjer, L11, L12 i L13.
          Instrukcija CMP EAX,0 postavlja Z fleg na 1 ako je u EAX registru nula, a u protivnom Z fleg se postavi na 0. Stoga
instrukcija JNE Londa izaziva skok na labelu Londa ako je EAX=0, a u protivnom se izvrši sljedeća instrukcija koja je
bezuslovni skok na labelu Linace. Na kraju bloka koji se izvršava kada je uslov ispunjen, nalazi se skok na labelu Lkrajuslova
da bi se preskoĉila sekcija koja se ne izvršava.
                               Pozovi Izraz dodjeljivanja
                               CMP EAX,0
                               JNE Londa
                               JMP Linace
                    Londa: Pozovi Blok
                              JMP Lkrajuslova
                    Linace: Pozovi Blok
                    Lkrajuslova: ....
                                      Sl. 6.2.3.         Generisani kôd za realizaciju uslova

6.3.      Petlje
        Iako konceptualno sloţenije od uslova petlje su za realizaciju još jednostavnije. Kao sintaksni simbol petlje uzima se
znak &, ĉije druge dvije upotrebe za adresu varijable i binarnu konjunkciju neće praviti konfuziju jer nema smisla da se u tom
kontekstu nalaze na poĉetku naredbe. Petlja se predstavlja sintaksnim dijagramom sa slike Sl. 6.3.1.
                                                                  24
         Petlja:


                                   Izraz                                      Blok
                    &                                        {
                                   dodjeljivanja
                                                        Sl. 6.3.1.           Petlja
         Primjer
         & a<0 { a:a+1}
         sve dok je a manje od nula, uvećavaj varijablu a za 1.
         Petlja se moţe realizovati generisanim kodom kao na slici Sl. 6.3.2.

                            Luslov:
                                        Pozovi Izraz dodjeljivanja
                                        CMP EAX,0
                                        JNE Ldok
                                        JMP Lkrajpetlje
                            Ldok:      Pozovi Blok
                                       JMP Luslov
                            Lkrajpetlje: ....



                                          Sl. 6.3.2.       Generisanje koda za petlje
          Sa ovim tipom petlje (odgovara while petlji) mogu se realizovati i programi koji zahtijevaju ostala dva popularna tipa
petlji (for i do/repeat).
         Programskom jeziku potrebno je sada dodati ulaz/izlaz. To je već stvar ovisna od operativnog sistema i ne moţe se
realizovati bez asemblerskih potprograma ili poziva sistemskih procedura. Stoga se uvodi specijalni simbol \ , koji predstavlja
da od sljedeće linije slijedi asemblerski kôd Nakon ovoga, kompajler jednostavno prepisuje naredne linije u generisani
asemblerski kôd, sve dok se ne doĊe do linije koja poĉinje znakom \.
         Sintaksni dijagram za asemblersku sekvencu se neće navoditi, jer je asemblerski jezik linijski orijentisan.


6.4.     Generalizovani jezički pojam blok
        Jeziĉki pojam Blok, i s njim vezana odgovarajuća procedura se sada mora redizajnirati da ukljuĉi uslove, petlje,
asembler i izraz dodjeljivanja, kao na slici Sl. 6.4.1
         Blok:
                                   &                Petlja


                                   ?                   Uslov
                                                                                                 }
                                   Izraz dodjeljivanja                 ;

                                   \                 Asembler


                                                Sl. 6.4.1.             Jezički pojam blok

        To u realizaciji znaĉi da procedura Blok treba da prepozna odgovarajući simbol i ovisno o njemu pozove
odgovarajuću proceduru.
        Sada se moţe realizovati listing treće verzije kompajlera, pod imenom komp32v3, koji je naveden u prilogu 3.
Izmjene u odnosu na drugu verziju prikazane su tamnijim slovima.
                                                                     25
6.5.      Testni primjer

Kao primjer programa u ovoj verziji jezika uzeće se traţenje kvadratnog korijena cijelog broja Heronovim algoritmom.
Koristeći Heronov algoritam, program će naći cijeli dio korijena broja iz varijable n, pazeći da ne doĊe do dijeljenja s nulom ili
vaĊenja korijena negativnog broja, a zatim emitovati zvuĉni signal onoliko puta koliki je rezultat. Zvuĉni signal se generiše
asemblerskim pozivom sistemske funkcije MessageBeep@4, koja se nalazi u biblioteci USER32.DLL, pri ĉemu se prije poziva
mora na stek staviti broj -1.
         Treba unijeti sljedeći kôd sa slike Sl. 6.5.1 i snimiti ga pod imenom heron.jez
             {                                                                                    }
                 n:200;                                                                       }
                 a:n;                                                                     q:a;
                 b:1;                                                                     & q>0
                 & (b<10)                                                                     {
                  {                                                                   \
                      ? (a>0)                                                             extrn MessageBeep@4:near
                        {                                                                 PUSH -1
                            a:(a+n/a)/2;                                                  CALL MessageBeep@4
                            b:b+1;                                                    \
                        }                                                                 q:q-1;
                        {                                                                 }
                            a:0;                                                      }
                                     Sl. 6.5.1.    Traženje kvadratnog korijena Heronovim algoritmom
                        Nakon naredbi
             komp32v3 heron.jez heron.asm
             ml /c /coff /Fl heron.asm | more
             link /defaultlib:user32.lib kernel32.lib /subsystem:console heron.obj

         i startanja prevedenog programa, zvuĉni signal se ĉuje 14 puta što je pribliţno korijen iz 200.


6.6.      Rezime poglavlja
          U trećoj verziji jezika aritmetiĉki izrazi su prošireni relacionim i unarnim operatorima. Varijable su statiĉki alocirane
relativno od labele GLOBALV i njihova adresa se izraĉunava iz ASCII koda jednoslovnog imena varijable. Uslovi i petlje se
oznaĉavaju simbolima ? i &. Moguće je ukljuĉivati asemblerske instrukcije. U ovoj verziji jezika moguće je pisati primjere iz
oblasti cjelobrojne numeriĉke analize.


Prilog 3: Verzija izvornog koda kompajlera br. 3

program Kompajler;                                  WriteLn(izlaz, st);                           function UzmiKonstantu: integer;
const                                             end;                                            var
  OCEKIVANO = 'Ocekivano ';                                                                         rezultat: integer;
  GRIZRAZ = 'Izraz';                              procedure Novi;                                 begin
                                                  begin                                             rezultat := 0;
var                                                 repeat                                          while (znak >= '0') and (znak <= '9')
  ulaz, izlaz: text;                                   pozicija := pozicija + 1;                       do begin
  pozicija, trenlabela, brojaclinija:                  if pozicija >                                   rezultat := 10 * rezultat +
  integer;                                               Length(linija) then begin                       ord(znak) - ord('0');
  znak: char;                                            brojaclinija :=                               Novi;
  linija: string;                                           brojaclinija + 1;                       end;
                                                         if not (Eof(ulaz)) then                    if (znak = ' ') or (znak = '`') then
procedure NovaLabela(var ImeLabele:                         ReadLn(ulaz, linija);                      Novi;
  string);                                               Emit(';' + linija);                        UzmiKonstantu := rezultat;
begin                                                    pozicija := 1;                           end;
  trenlabela := trenlabela + 1;                        end;
  Str(trenlabela, ImeLabele);                          if Length(linija) > 0 then                 procedure IzrazDodjeljivanja; forward;
end;                                                     znak := linija[pozicija]                 procedure Blok; forward;
                                                       else
procedure Greska(poruka: string);                        znak := ' ';                             procedure Varijabla;
begin                                               until (znak > ' ') or Eof(ulaz)               var
  WriteLn(poruka);                                end;                                              rezultat: integer;
  WriteLn(brojaclinija, ':', linija);                                                               st: string;
  Close(ulaz);                                    procedure IdiDo(z: char);                       begin
  Close(izlaz);                                   begin                                             rezultat := (ord(znak) -
  Halt;                                             if (znak <> z) then                               ord('a')) * 4;
end;                                                   Greska(OCEKIVANO + z);                       Str(rezultat, st);
                                                    Novi;                                           Emit(
procedure Emit(st: string);                       end;                                                ' LEA EBX,GLOBALV[' + st + ']');
begin                                                                                               Emit(' MOV EAX,[EBX]');
                                                          26
  Novi;                                  Clan;                                      repeat
end;                                     while (znak in                                ReadLn(ulaz, linija);
                                            ['+', '-', '&', '|', '^']) do begin        if linija <> '\' then
procedure Faktor;                           Emit(' PUSH EAX');                           Emit(linija);
var                                         z := znak;                                 if eof(ulaz) then
  rezultat: integer;                        Novi;                                        linija := '\';
  st: string;                               Clan;                                   until linija[1] = '\';
begin                                       case z of                               pozicija := 1;
  case znak of                                '+': begin                            znak := linija[pozicija];
     '-': begin                                    Emit(' POP EBX');                IdiDo('\');
         Novi;                                     Emit(' ADD EAX,EBX');          end;
         Faktor;                                 end;
         Emit(' NEG EAX');                    '-': begin                          procedure Petlja;
       end;                                        Emit(' MOV EBX,EAX');          var
     '~': begin                                    Emit(' POP EAX');                sdok, skrajpetlje, suslov: string;
         Novi;                                     Emit(' SUB EAX,EBX');          begin
         Faktor;                                 end;                               Novi;
         Emit(' NOT EAX');                    '&': begin                            NovaLabela(suslov);
       end;                                        Emit(' POP EBX');                Emit('L' + suslov + ':');
     '&': begin                                    Emit(' AND EAX,EBX');            IzrazDodjeljivanja;
         Novi;                                   end;                               Emit(' CMP EAX,0');
         Faktor;                              '|': begin                            NovaLabela(sdok);
         Emit(' MOV EAX,EBX');                     Emit(' POP EBX');                NovaLabela(skrajpetlje);
       end;                                        Emit(' OR EAX,EBX');             Emit(' JNE L' + sdok);
     '*': begin                                  end;                               Emit(' JMP L' + skrajpetlje);
         Novi;                                '^': begin                            IdiDo('{');
         Faktor;                                   Emit(' POP EBX');                Emit('L' + sdok + ':');
         Emit(' MOV EBX,EAX');                     Emit(' XOR EAX,EBX');            Blok;
         Emit(' MOV EAX,[EBX]');                 end;                               Emit(' JMP L' + suslov);
       end;                                 end;                                    Emit('L' + skrajpetlje + ':');
     '!': begin                          end;                                     end;
         Novi;                         end;
         Faktor;                                                                  procedure Blok;
         Emit(' CMP EAX,0');           procedure IzrazDodjeljivanja;              begin
         Emit(' SETE AL');             var                                          while znak <> '}' do
         Emit(' AND EAX,0FFh');          z: char;                                      case znak of
       end;                            begin                                             '&': Petlja;
     '0'..'9': begin                     Izraz;                                          '?': Uslov;
         rezultat := UzmiKonstantu;      case znak of                                    '\': Asembler;
         Str(rezultat, st);                 ':': begin                                 else begin
         Emit(' MOV EAX,' + st);                Emit(' PUSH EBX');                          IzrazDodjeljivanja;
       end;                                     Novi;                                       IdiDo(';');
     '(': begin                                 IzrazDodjeljivanja;                      end;
         Novi;                                  Emit(' POP EBX');                      end;
         IzrazDodjeljivanja;                    Emit(' MOV [EBX],EAX');             IdiDo('}');
         IdiDo(')');                          end; {:}                            end;
       end;                                 '=', '>', '<', '#': begin
     'a'..'z':                                  Emit(' PUSH EAX');                procedure Prevedi;
       Varijabla                                z := znak;                        begin
  else                                          Novi;                               Emit('.386');
     Greska(GRIZRAZ);                           Izraz;                              Emit('.MODEL FLAT,STDCALL');
  end;                                          Emit(' POP EBX');                   Emit('OPTION CASEMAP:NONE');
end;                                            Emit(' CMP EBX,EAX');               Emit('EXTRN ExitProcess@4:NEAR');
                                                case z of                           Emit('.CODE');
procedure Clan;                                    '=': Emit(' SETE AL');           Emit('ULAZ:');
var                                                '>': Emit(' SETG AL');           Emit(' JMP GLAVNI');
  z: char;                                         '<': Emit(' SETL AL');           pozicija := 0;
begin                                              '#': Emit(' SETNE AL');          Novi;
  Faktor;                                       end;                                IdiDo('{');
  while (znak in ['*', '/', '%']) do            Emit(' AND EAX,0FFh');              Emit('GLAVNI:');
     begin                                    end;                                  Blok;
     z := znak;                          end;                                       Emit(' PUSH 0');
     Emit(' PUSH EAX');                end;                                         Emit(' CALL ExitProcess@4');
     Novi;                                                                          Emit('.DATA');
     Faktor;                           procedure Uslov;                             Emit('GLOBALV DD 26 DUP(0)');
     case z of                         var                                          Emit('END ULAZ')
       '*': begin                        sonda, sinace, skrajuslova: string;      end;
            Emit(' POP EBX');          begin
            Emit(' IMUL EBX');           Novi;                                    procedure Glavni;
          end;                           IzrazDodjeljivanja;                      var
       '/', '%': begin                   Emit(' CMP EAX,0');                        linija: string;
            Emit(' MOV EBX,EAX');        NovaLabela(sonda);                       begin
            Emit(' POP EAX');            NovaLabela(sinace);                        trenlabela := 0;
            Emit(' CDQ');                NovaLabela(skrajuslova);                   Assign(ulaz, paramstr(1));
            Emit(' IDIV EBX');           Emit(' JNE L' + sonda);                    Assign(izlaz, paramstr(2));
            if z = '%' then              Emit(' JMP L' + sinace);                   brojaclinija := 0;
               Emit(' MOV EAX,EDX');     IdiDo('{');                                linija := '';
          end;                           Emit('L' + sonda + ':');                   Reset(ulaz);
     end;                                Blok;                                      Rewrite(izlaz);
  end;                                   Emit(' JMP L' + skrajuslova);              Prevedi;
end;                                     Emit('L' + sinace + ':');                  Close(ulaz);
                                         IdiDo('{');                                Close(izlaz);
                                         Blok;                                      WriteLn('Prevedeno bez greske');
                                         Emit('L' + skrajuslova + ':');           end;
procedure Izraz;                       end;
var                                                                               begin
  z: char;                             procedure Asembler;                          Glavni
begin                                  begin                                      end.
                                                                    27
7. KLJUČNE RIJEČI, STRINGOVI, DINAMIČKI NIZOVI I FUNKCIJE
          Prethodna verzija kompajlera omogućava, u kombinaciji s asemblerskim umetnutim kodom, realizaciju raznih
programa i za neke ĉitaoce je dovoljna, ali i dalje ima mnogo slabih taĉaka. Tu je prije svega evidentan nedostatak
potprograma, jednodimenzionalnih nizova i stringova. Osim toga, jezik je veoma kriptiĉan i potrebno mu je dodati kljuĉne
rijeĉi, kako bi bio razumljiviji.


7.1.      Ključne riječi
         Neka se dodaju prvo kljuĉne rijeĉi. Jeziĉki pojam Blok sada moţe izgledati kao na slici Sl. 7.1.1.
         Blok:


                      dok                      Petlja

                       ako                        Uslov
                                                                                             }
                                 Izraz dodjeljivanja            ;

                       asembler                Asembler
                       r


                                                           Sl. 7.1.1.          Blok
           Za prepoznavanje kljuĉnih rijeĉi postoje dva pristupa. Jedan je izrada konaĉnog automata koji se zove skaner ili
leksiĉki analizator. On se zasniva na dodjeli specijalnih simbola kljuĉnim rijeĉima. U primjeru sa slike Sl. 7.1.1 bi trebalo
modifikovati proceduru Novi da ako prepozna slovo a da provjeri da li iza njega slijedi slovo k ili s pa ako slijedi k, provjeriti
da li slijedi slovo o i ako su sva tri uslova ispunjena tada se vraća simbol za ako, u protivnom se vraća identifikator a, ak, ili
ĉak neki duţi identifikator (akcenat, akt itd.). U sluĉaju da je iza slova a slijedilo slovo s analogno se provjerava da li je rijeĉ o
kljuĉnoj rijeĉi asembler ili moţda varijabli astronaut. Skanerski pristup je brţi, i omogućava odvajanje prepoznavanja
kljuĉnih rijeĉi (leksiĉka analiza) od ostatka procesa prevoĊenja, te samim tim fleksibilniji kompajler. Pristup je konzistentan jer
se jednom procedurom dohvataju i jednoslovni i višeslovni jeziĉki simboli. Mana skanerskog pristupa je u relativno dugaĉkom
kodu za ostvarenje jednostavnog zadatka, kao i ĉinjenici da se prosti karakter tip koji prikazuje simbol koji slijedi mora
zamijeniti cjelobrojnim ili specijalizovanim, jer 256 znakova nije dovoljno.
         Drugi pristup je pristup oĉekivanih uzoraka (matching) . Ovaj pristup primijenjen je u kompajleru za programski jezik
Small C. U ulaznoj liniji se provjerava da li na trenutnom mjestu u ulaznoj slijedi ţeljeni string u cjelini. To znaĉi da će se
provjera vršiti više puta, bila ona potrebna ili ne. Osim toga, provjera se mora realizovati posebnom procedurom umjesto
prostog poreĊenja sa narednim simbolom, pa se malo gubi na konzistentnosti. Ali, pristup je dovoljno jednostavan da je
izabran za programski jezik razvijan u ovom radu Kako taj jezik ima vrlo malo kljuĉnih rijeĉi, gubitak performansi je
neznatan.
         Za prepoznavanje uzorka uvodi se funkcija Slijedi. Ova funkcija ima string argument, koji predstavlja oĉekivanu
kljuĉnu rijeĉ, a vraća Boolean, tako da se moţe pozivati sa
            if Slijedi('ako') then ...
Algoritam koji realizuje funkciju Slijedi se radi na sljedeći naĉin:
            Ako je niz znakova na trenutnoj ulaznoj poziciji jednak stringu navedenom kao parametar, onda se
vraća vrijednost tačno i postavi pokazivač pozicije iza tog niza. U protivnom se vrati vrijednost netačno.
        Koristeći ovu funkciju slijedi, lako je napisati novu verziju procedure blok i na taj naĉin uvesti kljuĉne rijeĉi.


7.2.      Komentari i neignorisanje simbola
          Strukturirani programski jezik je nezamisliv bez komentara. Programski jezici obiĉno definišu komentare kao dio
koda koji se ignoriše, pri ĉemu se komentar smatra dijelom koda izmeĊu dva specijalna niza simbola ili od jednog simbola do
kraja linije.
         U ovom jeziku, komentar je predstavljen apostrofom okrenutim na desnu stranu ` . Od tog znaka, do kraja linije tekst
se ignoriše. Proceduru Novi je potrebno malo modifikovati da bi dio koda izmeĊu ovog simbola i kraja linije bio ignorisan.
        Ponekad je potrebno dohvatiti i analizirati simbol ĉak i kada je on blanko, naopaki apostrof ili novi red. Naime, u
prethodnoj verziji kompajlera bilo je sasvim normalno napisati
                                                                   28
            a:1343223;
         kao i
            a:134 3
            22
            3;
        što je vrlo neuobiĉajeno, a kada se budu uvele stringovne konstante i neprihvatljivo. Stoga se pored funkcije novi
uvodi funkcija NoviSvaki koja radi sliĉno kao Novi, ali ne provjerava da li je rijeĉ o blanku ili komentaru. Ova funkcija ima
parametar koji govori da li će se prijavljivati greška ukoliko se, dohvaćajući simbole, došlo do kraja reda ili ne (u tom sluĉaju
kao kraj reda vraća blanko). Procedura UzmiKonstantu se sada modifikuje tako da novu cifru uzima ovom procedurom
umjesto procedure Novi.


7.3.      Modifikacija uslova i petlji
         Pošto je nepraktiĉno pisati uslove tako da se uvijek navodi i sekcija koja se izvrši kad je uslov ispunjen i ona kad
uslov nije ispunjen, uvodi se kljuĉna rijeĉ inace i jeziĉki pojam Uslov redizajnira kao na slici Sl. 7.3.1 i skladno tome se
mijenja odgovarajuća procedura Uslov. Time dio koda koji se izvršava kada uslov nije ispunjen postaje opcionalan.
         Uslov:


                      Izraz                                                                       {   Blok
       ako                                   {              Blok               inace
                      dodjeljivan
                      ja
                                                        Sl. 7.3.1.       Uslov
         Sintaksa petlji se ne mijenja, iako je simbol & zamijenjen kljuĉnom rijeĉju dok. Prepoznavanje kljuĉne rijeĉi dok se
obavlja unutar procedure Blok.


7.4.      Modifikacije aritmetičkih izraza i uvoĎenje stringova
           Dodjeljivanje simbolom : je takoĊe zbunjujuće, pa se Izraz dodjeljivanja mijenja da se umjesto znaka : ,
dodjeljivanje vrši koristeći operator := . Taj se operator moţe, nakon što je prepoznata dvotaĉka, provjeravati funkcijom
slijedi(':='). Izraz dodjeljivanja je prikazan na slici Sl. 7.4.1

                                                      =

                                                      >

                                                      <
                                                                                          Izraz
                  Izraz
                                                      #


                                                                          Izraz
                                                       :=                 dodjeljivanja

                                                 Sl. 7.4.1.             Izraz dodjeljivanja


        Stringovne konstante nije teško dodati, ukoliko se preuzme koncepcija stringova iz C-a. U C-u se stringovi prenose u
potprograme i dodjeljuju odgovarajućim varijablama tako što se prenosi adresa poĉetka stringovne konstante. Da bi se znalo
gdje je kraj stringovne konstante, na kraju stringa se nalazi bajt sa vrijednošću 0. Stringovne konstante uokvirene su
dvostrukim navodnicima.
String konstanta:


                               "                     karakter                        "

                                                  Sl. 7.4.2.             String konstanta
                                                             29
        Procedura koja prevodi stringovnu konstantu koristi proceduru NoviSvaki uz zabranu prelaska u naredni red. Ona
mora generisati kôd sa slike Sl. 7.4.3

                                            .DATA
                                            Lnn db "String koji je koristen",0
                                            .CODE
                                            MOV EAX,OFFSET Lnn


                                   Sl. 7.4.3.       Generisani kôd za stringovne konstante
          Iz ovoga se vidi da se mora prvo prekinuti kodni segment i reći asembleru da se ova konstanta smjesti u segment sa
podacima, kako bi se izbjeglo izvršavanje besmislenih instrukcija koje sluĉajno imaju isti operacioni kôd kao bajtovi
predstavljeni ASCII kodovima. Nakon ovoga ponovo se navodi kodni segment i instrukcija kojom se u EAX registar donosi
adresa toga stringa. Ova adresa će se kasnije moći prosljeĊivati Windows API funkcijama kao argument. U specijalnom
sluĉaju, prazan string se prevodi u Lnn DB 0.
        Ideja iz jezika C o pristupu nizovima cijelih brojeva koristeći pokazivaĉke varijable, omogućava vrlo jednostavno
dodavanje jednodimenzionalnih nizova. Uz pretpostavku da varijabla sadrţi adresu nekog prostora u memoriji (koji se moţe u
ovom trenutku dobiti dodjeljivanjem stringovne konstante varijabli ili pozivom Windows API funkcije GlobalAlloc u
asemblerskom modulu) i ako se taj prostor iskoristi za smještanje elemenata niza, tada je dovoljno u sintaksi varijable dodati
opcionalni indeks unutar uglastih zagrada, kao što se vidi na sintaksnom dijagramu sa slike Sl. 7.4.4:
         Varijabla:
                       Slovo                                           Izraz
                                                       [               dodjeljivanja
                                                                                                   ]




                                                       Sl. 7.4.4.         Varijabla
Adresa elementa niza tada se moţe dobiti po formuli
            Adresa=vrijednost varijable predstavljene slovom + 4 * vrijednost izraza dodjeljivanja
         Stoga se element niza dobija koristeći kôd sa slike Sl. 7.4.5.

                                  PUSH EAX
                                  Pozovi IzrazDodjeljivanja;
                                  POP EBX
                                  SAL EAX,2
                                  ADD EBX,EAX
                                  MOV EAX,[EBX]

                              Sl. 7.4.5.        Generisani kôd za dobijanje elementa niza
        Instrukcija SAL pomjera registar EAX za dva bita ulijevo, što efektivno predstavlja mnoţenje sa 4. U skladu sa
dosadašnjim standardom, adresa elementa niza se dobija u registru EBX, a njegova vrijednost u registru EAX.


7.5.     Funkcije i procedure
        Pošto je jezik koji se razvija sliĉan C-u, gdje se kreće od izraza, a ne iskaza, dodavanje funkcija automatski rješava i
problem dodavanja procedura ili obiĉnih potprograma. Procedure su prosto funkcije ĉija se vrijednost zanemaruje, a obiĉni
potprogrami pored toga nemaju argumenata.
         Poziv funkcije se vrši unutar izraza i sintaksno je prikazan na slici Sl. 7.5.1:


                             Veliko                  malo                               Izraz
                                                                          (                                        )
                             slovo                   slovo                              dodjeljivanja


                                                                                               ,
                                                Sl. 7.5.1.       Poziv funkcije
         Kao u implementaciji većine modernih programskih jezika, parametri se prije poziva funkcije smještaju na stek.
                                                              30
        U definiciji funkcije se za sada ne navode parametri, iako se oni mogu navesti pri pozivu. Stoga, ova verzija
kompajlera nema provjeru broja i tipa parametara funkcija i smatraće se da sve funkcije imaju po 26 parametara.
         Imajući ovo u vidu, generisani kôd za poziv funkcije izgleda kao na slici Sl. 7.5.2 :
                                  Za svaki parametar:
                                      Pozovi Izrazdodjeljivanja
                                      PUSH EAX
                                  MOV ECX,ukupna veličina svih parametara
                                  CALL P_funkcija


                                         Sl. 7.5.2.        Poziv funkcije, generisani kôd

         Podatak o tome koliko su memorije na steku zauzeli parametri, a koji se smješta u ECX, koristiće se u samoj funkciji.
         Definicija funkcije data je na sintaksnom dijagramu na slici Sl. 7.5.3.
         Funkcija:


                    funkcija                 Veliko                     malo
                                                                                                        ;
                                             slovo                      slovo


                                                                                                        {            Blok

                                                      Sl. 7.5.3.     Funkcija
         Ime funkcije obavezno poĉinje velikim slovom iza koga slijedi više malih slova. Ovo je uĉinjeno da bi se razlikovale
funkcije po imenu od varijabli, koje su predstavljene malim slovima.
        Ako iza imena funkcije slijedi znak { , tada slijedi tijelo funkcije. Ukoliko iza imena funkcije slijedi znak ; tada je
samo u pitanju deklarisanje funkcije, ĉije se tijelo nalazi u drugom modulu (drugoj .JEZ ili .OBJ datoteci).
      Definisanje funkcije koja je implementirana u drugom modulu se realizuje prostom upotrebom pseudoinstrukcije
EXTRN:       EXTRN P_imefunkcije:NEAR
         Funkcije koje imaju tijelo se prevode znatno sloţenije. Na steku se rezerviše prostor za svih 26 parametara, koji iznosi
104 bajta (26*4). Parametri se oznaĉavaju sa @a, @b, ... , @z, pri ĉemu @a predstavlja prvi parametar naveden u pozivu, a
@z predstavlja 26-ti parametar. Naravno, većina parametara neće biti iskorištena , pa se neiskorišteni parametri mogu
upotrijebiti kao lokalne varijable. Registar ECX, kako je već reĉeno, sadrţi veliĉinu dijela steka potrošenog za parametre, a za
lokalne varijable ostaje 104-ECX bajtova. Lokalnim varijablama i parametrima se pristupa relativno u odnosu na EBP registar,
pa EBP registar treba pokazivati na vrh steka u trenutku poziva. Sam stek pointer se mora umanjiti kako bi se iz funkcija
pozivale druge funkcije, a zatim na stek stavila povratna adresa. Sve navedeno se postiţe kodom slike Sl. 7.5.4.
         Primjećuje se da nema posebnog koda za vraćanje vrijednosti funkcije. Ona se jednostavno već nalazi u EAX registru
kao rezultat posljednjeg aritmetiĉkog izraza unutar bloka. Instrukcija RET 104 pored povratka iz potprograma ujedno i vrati
poziciju stek pointera na vrijednost prije stavljanja prvog argumenta. Ovaj kôd će se pojednostaviti nakon uvoĊenja provjera
argumenata, u narednom poglavlju.
                                P_ImeFunkcije:
                                 POP EDX
                                 ADD ESP,ECX
                                 SUB ESP,104
                                 PUSH EDX
                                 PUSH EBP
                                 MOV EBP,ESP
                                 Pozovi Blok
                                 POP EBP
                                 RET 104
                                PUBLIC P_ImeFunkcije
                                     Sl. 7.5.4.         Generisani kôd za tijelo funkcije
        Realizacija funkcija, dinamiĉkih nizova i stringova dovodi do nove sintaksne definicije pojma faktor i skladno s tim
odgovarajuće procedure:
                                                                31
         Faktor:
                   -

                   ~

                   &
                                              Faktor
                   *

                   !

                                      Numeriĉka konstanta

                              (               Izraz dodjeljivanja                  )
                       @


                                         Varijabla

                              "                     String konstanta

                                                       Poziv funkcije

                                                         Sl. 7.5.5.        Faktor


         Numeriĉku konstantu, varijablu ili poziv funkcije moguće je razlikovati po tome da li poĉinju cifrom, malim ili
velikim slovom.
         Lokalne varijable se implementiraju sljedećim kodom
            LEA EBX,[EBP+n]
            MOV EAX,[EBX]
         gdje se n raĉuna izrazom n=108-(ord(znak)- ord('a'))*4 .
         U ovom izrazu, znak predstavlja ime varijable bez simbola @.


7.6.      Testni primjer

         Na slici Sl. 7.6.1 dat je program u ĉetvrtoj verziji jezika koji prikazuje na ekranu za brojeve od 1 do 10: broj, ime
broja, kvadrat, kub, faktorijel (rekurzivno) te proste faktore tog broja. Program se zove tabbroj.jez i kompajlira koristeći
             komp32v4 tabbroj.jez tabbroj.asm
             ml /c /coff /Fl tabbroj.asm | more
             link /defaultlib:user32.lib kernel32.lib /subsystem:console tabbroj.obj
                                                             32


funkcija Prikazistring {                                      }
asembler
  extrn GetStdHandle@4:near                                   funkcija Fact
  extrn WriteConsoleA@20:near                                 {
  MOV EAX,-11 ; -11 je parametar za STDOUT                       ako (@a=0)
  PUSH EAX                                                        {
  CALL GetStdHandle@4 ; Uzmi hendl za STDOUT                        1;
  MOV ECX,0 ; Petlja koja racuna duzinu stringa                   }
  MOV EBX,[EBP+108]                                              inace
DUZ: CMP BYTE PTR [EBX],0                                         {
  JE IZR                                                            @a*Fact(@a-1);
  INC ECX                                                         }
  INC EBX                                                     }
  JMP DUZ
IZR:
  PUSH DWORD PTR 0 ; Rezervisano                              funkcija Tabela
  LEA EBX,[EBP+104]                                           {
  PUSH EBX ; Pointer na broj karaktera koji su prikazani         Prikazistring("Tabela");
  PUSH ECX ; Broj karaktera koji se pisu                         Novired();
  MOV EBX,[EBP+108]                                              n:=1;
  PUSH EBX ; Pointer na string                                   dok (n<11) {
  PUSH EAX ; Handle                                                Prikazibroj (n);
  CALL WriteConsoleA@20 ; Ispisi string                            Prikazistring(" ");
\                                                                  Prikazistring(a[n]);
}                                                                  Prikazistring(" ");
                                                                   Prikazibroj (n*n);
funkcija Zamijeniznak {                                            Prikazistring(" ");
  asembler                                                         Prikazibroj (n*n*n);
  MOV EBX,[EBP+108] ; Adresa stringa                               Prikazistring(" ");
  ADD EBX,[EBP+104] ; Redni broj karaktera                         Prikazibroj (Fact(n));
  MOV EAX,[EBP+100] ; ASCII kod karaktera koji mijenjamo           Prikazistring(" Djeljiv sa ");
  MOV [EBX],AL ; Upisuje karakter                                  m:=1;
\                                                                  dok !(m>n) {
}                                                                    ako (n%m=0) {
                                                                       Prikazibroj(m);
funkcija Novired {                                                     Prikazistring(" ");
  @a:=" ";                                                           }
  Zamijeniznak(@a,0,13);                                             m:=m+1;
  Zamijeniznak(@a,1,10);                                           }
  Prikazistring(@a);                                               n:=n+1;
}                                                                  Novired();
                                                                 }
funkcija Prikazibroj {                                        }
  @q:="           "; ` Alociramo bafer
  @c:=@a;                                                     funkcija Postavinazive
` Negativne brojeve oznaci indikatorom                        {
  ako (@c<0) { @i:=1; @c:=-@c; }                                a:="                                              ";
    inace { @i:=0; }                                              ` Prostor za niz
`maksimalno 9 cifara                                            a[1]:="Jedan";
  @p:=9;                                                        a[2]:="Dva";
  ako (@c=0) { Zamijeniznak(@q,@p,48);@p:=@p-1;}                a[3]:="Tri";
  dok (@c>0)                                                    a[4]:="Cetiri";
  {                                                             a[5]:="Pet";
     @o:=(@c % 10); `ostatke dijeljenja u bafer                 a[6]:="Sest";
     Zamijeniznak(@q,@p,@o+48);                                 a[7]:="Sedam";
     @c:=@c/10; ` stalno dijeli s 10                            a[8]:="Osam";
     @p:=@p-1;                                                  a[9]:="Devet";
  }                                                             a[10]:="Deset";
  ako (@i=1)                                                  }
  {
     Zamijeniznak(@q,@p,45);                                  {
     @p:=@p-1;                                                    Postavinazive();
  }                                                               Tabela();
  @q:=@q+@p+1; ` Pomjeri pokazivac pocetka stringa            }
  Prikazistring(@q);
                              Sl. 7.6.1.          Tablica brojeva, četvrta verzija kompajlera

        Funkcija Prikazistring realizovana je u asembleru, jer poziva Windows API funkcije GetStdHandle i
WriteConsole. Ove funkcije predstavljaju naĉin ispisa stringa na ekranu koristeći Windowsove sistemske funkcije za rad s
konzolnim aplikacijama.
         Funkcija GetStdHandle je sistemska funkcija koja vraća broj pridruţen ulaznom ureĊaju, izlaznom ureĊaju ili ureĊaju
greške. U Windows API funkcijama definisana je ovako
             HANDLE GetStdHandle(
                DWORD nStdHandle              // input, output, or error device
               );
pa je potrebno na stek prije njenog poziva staviti konstantu -11, koja predstavlja STDOUT.
        Funkcija WriteConsole je definisana ovako
                                                       33
             BOOL WriteConsole(
               HANDLE hConsoleOutput,         // handle to a console screen buffer
               CONST VOID *lpBuffer, // pointer to buffer to write from
               DWORD nNumberOfCharsToWrite,            // number of characters to write
               LPDWORD lpNumberOfCharsWritten,//pointer to number of chars written
               LPVOID lpReserved     // reserved
              );


          Windows-ova konvencija je da se parametri za API funkcije smještaju na stek obrnutim redom u odnosu na onaj koji
je definisan u zaglavlju funkcije. Asemblerski potprogram priprema sve parametre i smješta ih potrebnim redoslijedom.
         Pošto još nema naredbi za pristup pojedinaĉnim karakterima, u asembleru je napisana i funkcija Zamijeniznak, koja
se poziva sa tri parametra, prvi je adresa stringa, drugi redni broj karaktera koji mijenjamo i treći ASCII kôd koji upisujemo.
          Ostale funkcije su pisane bez pomoći asemblera. Funkcija Novired ispisuje string koji sadrţi kodove CR i LF, ĉime
se prelazi u novi red. Funkcija Prikazibroj pretvara cijeli broj u njegovu ASCII reprezentaciju, koristeći uzastopno dijeljenje
sa 10 uz prikazivanje ostataka, a zatim se ta ASCII reprezentacija prikazuje na ekranu, koristeći funkciju PrikaziString.
Posebno je interesantna funkcija Fact koja rekurzivno raĉuna faktorijel, koristeći definiciju faktorijela. Dakle, jezik već u ovoj
fazi podrţava i tako sloţene stvari kao što je rekurzija. Glavna funkcija Tabela je dobro strukturirana i shvatljiva svakome ko
poznaje bar jedan viši programski jezik. Jedino treba reći da se u unutrašnjoj petlji (sa m kao brojaĉem) vrši poreĊenje ostatka
(pri dijeljenju n sa m ) sa brojem 0 i ako je ostatak jednak 0, tada se prikazuje broj kao djelilac. U funkciji Postavinazive se
globalnoj varijabli a pridruţi adresa stringa koji ima dosta blankova. Ovaj string sluţi samo kao rezervisani prostor za 10
pokazivaĉa na nove stringove koji sadrţe imena brojeva.
          Izvršenje programa Tabbroj daje kao rezultat


1    Jedan 1 1 1 Djeljiv sa 1
2    Dva 4 8 2 Djeljiv sa 1 2
3    Tri 9 27 6 Djeljiv sa 1 3
4    Cetiri 16 64 24 Djeljiv sa 1 2 4
5    Pet 25 125 120 Djeljiv sa 1 5
6    Sest 36 216 720 Djeljiv sa 1 2 3 6
7    Sedam 49 343 5040 Djeljiv sa 1 7
8    Osam 64 512 40320 Djeljiv sa 1 2 4 8
9    Devet 81 729 362880 Djeljiv sa 1 3 9
10    Deset 100 1000 3628800 Djeljiv sa 1 2       5   10



što je i trebalo dobiti. EXE verzija programa je velika svega 4 kilobajta, jer nema opterećujuće biblioteke, kao u svim drugim
kompajlerima. Ova verzija jezika je sasvim upotrebljiva za mnoge primjene iako programi pisani u njoj zahtijevaju dosta
hakerskih trikova. Tu se prije svega misli na povremenu upotrebu asemblerskog koda. Ipak, asemblerske i druge funkcije se
već u ovoj verziji kompajlera mogu izdvojiti i posebno kompajlirati i linkovati, te na taj naĉin formirati jezgro programske
biblioteke, što u mnogome olakšava programiranje.


7.7.      Rezime poglavlja
         Ĉetvrta verzija kompajlera uvodi kljuĉne rijeĉi. Kljuĉne rijeĉi se mogu prepoznavati skanerom, koji provjerava slovo
po slovo kao konaĉni automat ili oĉekivanim uzorkom, poreĊenjem sa cijelim oĉekivanim stringom. Odabran je princip
oĉekivanih uzoraka, i uzorci se provjeravaju procedurom Slijedi. Dodane su kljuĉne rijeĉi ako, dok, inace, funkcija i
asembler. Dodjeljivanje vrijednosti varijabli se vrši simbolom :=. Stringovne konstante se prevode u instrukciju koja registru
EAX dodjeljuje adresu stringa. Uvedeni su jednodimenzionalni nizovi, vezani uz pojam pointera. Moguće je pozivati funkcije
sa varijabilnim brojem parametara. Parametri se mogu koristiti kao lokalne varijable. Funkcije mogu biti i u eksternim
modulima. Testni primjer ukljuĉuje cjelobrojnu aritmetiku i ispis na ekran.
        Ovo je najznaĉajnija verzija kompajlera. Dovoljno je kratka da se moţe prikazati za jedan nastavni blok-ĉas, ali opet
dovoljno velika da ukljuĉuje većinu koncepata iterativnih programskih jezika.
                                                              34
program Kompajler;                           if (znak = ' ') or (znak = '`') then            * 4;
const                                           Novi;                                      Str(rezultat, st);
  GRIZRAZ = 'Izraz';                         UzmiKonstantu := rezultat;                    Emit(' LEA EBX,GLOBALV[' + st +']');
  DUGAKONST =                              end;                                         end
    'Konstanta prevazilazi liniju';                                                     else begin
  OCEKIVANO = 'Ocekivano ';                function Slijedi(ocekivano: string):            Novi;
  IMEFUN = 'Ocekivano ime funkcije';         Boolean;                                      if (znak < 'a') or (znak > 'z')
  DEFFUN = 'Definicija funkcije';          begin                                             then
  OCEKDOD = 'Ocekivano dodjeljivanje';       if copy(linija, pozicija,                       Greska('Lokalna');
                                                Length(ocekivano)) = ocekivano then        rezultat := 108 - (ord(znak) -
var                                               begin                                      ord('a')) * 4;
  ulaz, izlaz: text;                            Slijedi := true;                           Str(rezultat, st);
  pozicija, trenlabela, brojaclinija:           pozicija := pozicija +                     Emit(' LEA EBX,[EBP+' + st + ']');
  integer;                                        Length(ocekivano) - 1;                end;
  znak: char;                                end                                        Emit(' MOV EAX,[EBX]');
  linija: string;                            else                                       Novi;
                                                Slijedi := false;                       if znak = '[' then
procedure NovaLabela(var ImeLabele:        end;                                            PokazivacINiz;
  string);                                                                            end;
begin                                      procedure IzrazDodjeljivanja; forward;
  trenlabela := trenlabela + 1;            procedure Blok; forward;                  procedure Faktor;
  Str(trenlabela, ImeLabele);                                                        var
end;                                       procedure PokazivacINiz;                    rezultat: integer;
                                           begin                                       st: string;
procedure Greska(poruka: string);            Novi;                                   begin
begin                                        Emit(' PUSH EAX');                        case znak of
  WriteLn(poruka);                           IzrazDodjeljivanja;                          '-': begin
  WriteLn(brojaclinija, ':', linija);        Emit(' POP EBX');                                 Novi;
  Close(ulaz);                               Emit(' SAL EAX,2');                               Faktor;
  Close(izlaz);                              Emit(' ADD EBX,EAX');                             Emit(' NEG EAX');
  Halt;                                      Emit(' MOV EAX,[EBX]');                        end;
end;                                         IdiDo(']');                                  '~': begin
                                           end;                                                Novi;
procedure Emit(st: string);                                                                    Faktor;
begin                                      procedure StringKonstanta;                          Emit(' NOT EAX');
  WriteLn(izlaz, st);                      var                                              end;
end;                                         st, strtekst: string;                        '&': begin
                                           begin                                               Novi;
procedure Novi;                              NovaLabela(strtekst);                             Faktor;
begin                                        Emit('.DATA');                                    Emit(' MOV EAX,EBX');
  repeat                                     st := 'L' + strtekst + ' DB ''';               end;
     pozicija := pozicija + 1;               repeat                                       '*': begin
     if pozicija > Length(linija) then          NoviSvaki(true);                               Novi;
       begin                                    if znak <> '"' then                            Faktor;
       brojaclinija := brojaclinija + 1;          st := st + znak;                             Emit(' MOV EBX,EAX');
       if not (Eof(ulaz)) then               until znak = '"';                                 Emit(' MOV EAX,[EBX]');
          ReadLn(ulaz, linija);              IdiDo('"');                                    end;
       Emit(';' + linija);                   st := st + ''',0';                           '!': begin
       pozicija := 1;                        if copy(st, length(st) - 3, 2) =                  Novi;
     end;                                       '''''' then                                    Faktor;
     if Length(linija) > 0 then                 st := 'L' + strtekst + ' DB 0';                Emit(' CMP EAX,0');
       znak := linija[pozicija]              Emit(st);                                         Emit(' SETE AL');
     else                                    Emit('.CODE');                                    Emit(' AND EAX,0FFh');
       znak := ' ';                          Emit(' MOV EAX,OFFSET L' + strtekst);          end;
     if (znak = '`') then                  end;                                           '"':
       pozicija := Length(linija);                                                          StringKonstanta;
  until ((znak > ' ') and (znak <>         procedure PozivFunkcije;                       '0'..'9': begin
     '`')) or Eof(ulaz)                    var                                                 rezultat := UzmiKonstantu;
end;                                         lokalnih: integer;                                Str(rezultat, st);
                                             ImeFunkcije, st: string;                          Emit(' MOV EAX,' + st);
procedure NoviSvaki(greskakrln:            begin                                            end;
  Boolean);                                  ImeFunkcije := '';                           '(': begin
begin                                        while ((znak >= 'a') and (znak <=                 Novi;
  pozicija := pozicija + 1;                     'z')) or                                       IzrazDodjeljivanja;
  if pozicija > Length(linija) then             ((znak >= 'A') and (znak <= 'Z')) do           IdiDo(')');
     begin                                        begin                                     end;
     if greskakrln then                         ImeFunkcije := ImeFunkcije + znak;        '@':
       Greska(DUGAKONST)                        NoviSvaki(false);                           Varijabla(false);
     else                                    end;                                         'A'..'Z':
       znak := ' ';                          if (znak = ' ') or (znak = '`') then           PozivFunkcije;
  end                                           Novi;                                     'a'..'z':
  else                                       lokalnih := 0;                                 Varijabla(true)
     znak := linija[pozicija];               IdiDo('(');                               else
end;                                         while (znak <> ')') do begin                 Greska(GRIZRAZ);
                                                IzrazDodjeljivanja;                    end;
procedure IdiDo(z: char);                       Emit(' PUSH EAX');                   end;
begin                                           lokalnih := lokalnih + 4;
  if (znak <> z) then                           if znak <> ')' then                  procedure Clan;
     Greska(OCEKIVANO + z);                       IdiDo(',');                        var
  Novi;                                      end;                                      z: char;
end;                                         IdiDo(')');                             begin
                                             Str(lokalnih, st);                        Faktor;
function UzmiKonstantu: integer;             Emit(' MOV ECX,' + st);                   while (znak in ['*', '/', '%']) do
var                                          Emit(' CALL P_' + ImeFunkcije);              begin
  rezultat: integer;                       end;                                           z := znak;
begin                                                                                     Emit(' PUSH EAX');
  rezultat := 0;                           procedure Varijabla(glob: Boolean);            Novi;
  while (znak >= '0') and (znak <= '9')    var                                            Faktor;
    do begin                                 rezultat: integer;                           case z of
    rezultat := 10 * rezultat +              st: string;                                    '*': begin
       ord(znak) - ord('0');               begin                                                 Emit(' POP EBX');
    NoviSvaki(false);                        if glob then begin                                  Emit(' IMUL EBX');
  end;                                          rezultat := (ord(znak) - ord('a'))             end;
                                                           35
       '/', '%': begin                  procedure Uslov;                           Novi;
            Emit(' MOV EBX,EAX');       var                                        while (znak >= 'a') and (znak <= 'z')
            Emit(' POP EAX');             sonda, sinace, skrajuslova: string;         do begin
            Emit(' CDQ');               begin                                         ImeFunkcije := ImeFunkcije + znak;
            Emit(' IDIV EBX');            Novi;                                       Novi;
            if z = '%' then               IzrazDodjeljivanja;                      end;
               Emit(' MOV EAX,EDX');      Emit(' CMP EAX,0');                      case znak of
          end;                            NovaLabela(sonda);                          '{': begin
     end;                                 NovaLabela(sinace);                             Emit('P_' + ImeFunkcije + ':');
  end;                                    NovaLabela(skrajuslova);                        Emit(' POP EDX');
end;                                      Emit(' JNE L' + sonda);                         Emit(' ADD ESP,ECX');
                                          Emit(' JMP L' + sinace);                        Emit(' SUB ESP,104');
procedure Izraz;                          IdiDo('{');                                     Emit(' PUSH EDX');
var                                       Emit('L' + sonda + ':');                        Emit(' PUSH EBP');
  z: char;                                Blok;                                           Emit(' MOV EBP,ESP');
begin                                     Emit(' JMP L' + skrajuslova);                   IdiDo('{');
  Clan;                                   Emit('L' + sinace + ':');                       Blok;
  while (znak in ['+', '-', '&', '|',     if Slijedi('inace') then begin                  Emit(' POP EBP');
     '^']) do begin                          Novi;                                        Emit(' RET 104');
     Emit(' PUSH EAX');                      IdiDo('{');                                  Emit('PUBLIC P_' +
     z := znak;                              Blok;                                           ImeFunkcije);
     Novi;                                end;                                          end;
     Clan;                                Emit('L' + skrajuslova + ':');              ';': begin
     case z of                          end;                                              Emit('extrn P_' + ImeFunkcije +
       '+': begin                                                                            ':near');
            Emit(' POP EBX');           procedure Asembler;                               IdiDo(';');
            Emit(' ADD EAX,EBX');       begin                                           end
          end;                            repeat                                   else
       '-': begin                            ReadLn(ulaz, linija);                    Greska(DEFFUN);
            Emit(' MOV EBX,EAX');            if linija <> '\' then                 end;
            Emit(' POP EAX');                  Emit(linija);                     end;
            Emit(' SUB EAX,EBX');            if eof(ulaz) then
          end;                                 linija := '\';                    procedure Prevedi;
       '&': begin                         until linija[1] = '\';                 begin
            Emit(' POP EBX');             pozicija := 1;                           Emit('.386');
            Emit(' AND EAX,EBX');         znak := linija[pozicija];                Emit('.MODEL FLAT,STDCALL');
          end;                            IdiDo('\');                              Emit('OPTION CASEMAP:NONE');
       '|': begin                       end;                                       Emit('EXTRN ExitProcess@4:NEAR');
            Emit(' POP EBX');                                                      Emit('.CODE');
            Emit(' OR EAX,EBX');        procedure Petlja;                          Emit('ULAZ:');
          end;                          var                                        Emit(' JMP GLAVNI');
       '^': begin                         sdok, skrajpetlje, suslov: string;       pozicija := 0;
            Emit(' POP EBX');           begin                                      Novi;
            Emit(' XOR EAX,EBX');         Novi;                                    while (Slijedi('funkcija')) do begin
          end;                            NovaLabela(suslov);                         Novi;
     end;                                 Emit('L' + suslov + ':');                   DefFunkcija;
  end;                                    IzrazDodjeljivanja;                      end;
end;                                      Emit(' CMP EAX,0');                      IdiDo('{');
                                          NovaLabela(sdok);                        if znak <> '}' then begin
procedure IzrazDodjeljivanja;             NovaLabela(skrajpetlje);                    Emit('GLAVNI:');
var                                       Emit(' JNE L' + sdok);                      Blok;
  z: char;                                Emit(' JMP L' + skrajpetlje);               Emit(' PUSH 0');
begin                                     IdiDo('{');                                 Emit(' CALL ExitProcess@4');
  Izraz;                                  Emit('L' + sdok + ':');                     Emit('.DATA');
  case znak of                            Blok;                                       Emit('GLOBALV DD 26 DUP(0)');
     ':': begin                           Emit(' JMP L' + suslov);                    Emit('END ULAZ')
         if not (Slijedi(':=')) then      Emit('L' + skrajpetlje + ':');           end
            Greska(OCEKDOD);            end;                                       else begin
         Emit(' PUSH EBX');                                                           Emit('GLAVNI:');
         Novi;                          procedure Blok;                               Emit('END');
         IzrazDodjeljivanja;            begin                                      end;
         Emit(' POP EBX');                while znak <> '}' do begin             end;
         Emit(' MOV [EBX],EAX');             if Slijedi('dok') then
       end; {:}                                Petlja                            procedure Glavni;
     '=', '>', '<', '#': begin               else if Slijedi('ako') then         var
         Emit(' PUSH EAX');                    Uslov                               linija: string;
         z := znak;                          else if Slijedi('asembler') then    begin
         Novi;                                 Asembler                            trenlabela := 0;
         Izraz;                              else begin                            Assign(ulaz, paramstr(1));
         Emit(' POP EBX');                     IzrazDodjeljivanja;                 Assign(izlaz, paramstr(2));
         Emit(' CMP EBX,EAX');                 IdiDo(';');                         brojaclinija := 0;
         case z of                           end;                                  linija := '';
            '=': Emit(' SETE AL');        end;                                     Reset(ulaz);
            '>': Emit(' SETG AL');        IdiDo('}');                              Rewrite(izlaz);
            '<': Emit(' SETL AL');      end;                                       Prevedi;
            '#': Emit(' SETNE AL');                                                Close(ulaz);
         end;                           procedure DefFunkcija;                     Close(izlaz);
         Emit(' AND EAX,0FFh');         var                                        WriteLn('Prevedeno bez greske');
       end;                               ImeFunkcije: string;                   end;
  end;                                  begin
end;                                      if (znak < 'A') or (znak > 'Z') then   begin
                                            Greska(IMEFUN);                        Glavni
                                          ImeFunkcije := znak;                   end.
                                                                   36
8. DEKLARACIJE VARIJABLI, STANDARDNE FUNKCIJE
         Iako već prihvatljiva da u nekim kraćim kursevima kompajlera bude i finalna, prethodna verzija kompajlera ima ĉetiri
ozbiljna nedostatka:
      Jednoslovna imena varijabli ograniĉavaju jezik na 26 lokalnih/parametarskih i toliko globalnih varijabli. Iako je to ĉesto
       dovoljno, postoje situacije kada nije. Sem toga, ova imena nisu dovoljno deskriptivna.
      Jedini tip je 32 bitni cijeli broj koji se sluĉajno poklapa sa pointerom.
      Programski jezik nema nikakve semantiĉke analize. Sasvim je legalno napisati izraz tipa 5:=2+a; što će upisati vrijednost
       zbira konstante 2 i varijable a, na neku sluĉajnu lokaciju gdje je u tom trenutku pokazivao EBX registar. Funkcija moţe
       biti deklarisana više puta, a grešku će primijetiti tek asembler.
      Poziv potprograma nije standardan, pa se sistemske funkcije moraju pozivati iz asemblerskog modula.


8.1.        Tabela identifikatora
          UvoĊenje višeslovnih imena varijabli zahtijeva napuštanje statiĉkog naĉina alokacije varijabli i pravljenje tabele
identifikatora. Tabela identifikatora TabIdent je niz slogova
              TIdent=record
                ime:string[20];
                duzina:integer;
                adresa:integer;
                nivo:integer;
                vrsta:Tvrsta;
                tip:Ttip;
                pod1:integer;
                pod2:integer;
                pod3:integer;
              end;
koji ĉuvaju ime identifikatora, duţinu, relativnu adresu identifikatora u skupu svih varijabli unutar funkcije ili globalnih
varijabli, nivo koji predstavlja identifikator funkcije kojoj varijabla pripada (ili 0 za globalne), vrstu identifikatora (funkcija,
lokalna varijabla, globalna varijabla, parametar), tip identifikatora (karakter, cijeli broj, pointer na karakter, pointer na cijeli
broj), kao i tri dodatna podatka za šire objašnjenje identifikatora.
         Ova promjena u koncepciji zahtijeva dodavanje novih procedura, kao i da neke procedure u kompajleru budu
proširene, a neke ĉak i nanovo napisane, ĉime kompajler postaje gotovo duplo duţi u odnosu na prethodnu verziju.
          Procedura NoviIdent dodaje identifikator u tabelu identifikatora. Dodavanje se vrši trivijalno, uvećanjem brojaĉa
identifikatora ukupnoident za 1, a zatim upisom svih devet parametara ove procedure u odgovarajuća polja konkretnog sloga
tabele identifikatora.
          U svrhu traţenja ţeljenog identifikatora u ovoj tabeli uvodi se funkcija NadjiIdent koja ima za parametre ime
identifikatora, nivo koji predstavlja identifikator funkcije kojoj varijabla pripada (ili 0 za globalne), vrstu uslova i dodatni
podatak. Ova funkcija treba da vrati poziciju navedenog identifikatora u tabeli identifikatora, ili vrijednost 0 ako identifikator
nije naĊen. Pretraţivanje se vrši sekvencijalno jer identifikatori nisu sortirani. No, ono se vrši s kraja prema poĉetku, kako bi
lokalne varijable bile naĊene prije istoimenih globalnih. Znaĉenje parametra “vrsta uslova” dato je u tabeli na slici Sl. 8.1.1.
Broj         Znaĉenje
1            Traţi lokalnu varijablu, globalnu varijablu, parametar funkcije ili funkciju koja ima ime kao
             navedena a nalazi se u funkciji koja se trenutno prevodi ili glavnom programu
2            Traţi lokalnu varijablu, globalnu varijablu, parametar funkcije ili funkciju koja ima kao
             navedena a nalazi se u ili funkciji koja se trenutno prevodi ili u glavnom programu ako se on u
             tom trenu prevodi
3            Rezervisano
4            Traţi parametar funkcije koja se prevodi u ovom trenutku po njegovom rednom broju
                                         Sl. 8.1.1.        Parametar Vrsta uslova
         Procedura UzmiIdent vraća string vrijednost koja predstavlja niz slova. Algoritam koji implementira tu proceduru
izgleda ovako:
                                                            37
             Postavi rezultantni string na prazan string
             Sve dok slijedi slovo dodaj ga na rezultantni string, i uzmi sljedeći znak
             Ako je sljedeći znak blanko ili komentar dohvati ga kako bi ga rutine ignorisale
         Procedura DeklIdent objedinjuje UzmiIdent i NadjiIdent, tj. dohvata identifikator i traţi da li on već postoji u tabeli,
te ako postoji prijavljuje grešku.
         Sada je potrebno proširiti sintaksu jezika. Prvo treba definisati pojam identifikatora, koji je prikazan na slici Sl. 8.1.2.
         Identifikator:

                                                                         Cifra


                                                                           _

                                 Slovo                                   Slovo
                            (veliko ili malo)                       (veliko ili malo)



                                                  Sl. 8.1.2.        Identifikator
         Realizacija jeziĉkog pojma Identifikator uraĊena je u proceduri UzmiIdent.


8.2.      Tipovi
          Postoje ĉetiri tipa varijabli, cijeli, karakter, te pointeri na njih. Oni se zajedno definišu u pojmu ImeTipa, (Sl. 8.2.1)
koji je implementiran u funkcijama SlijediDekTipa i TipDek. Funkcija
         function TipDek(imetipa: string; var tip: TTip; stip, ptip: TTip): Boolean;
provjerava da li slijedi navedeno ime tipa ili pointer na njega. Ako ne slijedi ni jedno ni drugo, funkcija vraća false. Ime tipa se
navodi kao niz karaktera, a u varijablu tip funkcija vraća oznaku tipa ili pointera na njega. Ove oznake se navode kao
parametri stip i ptip i mogu biti karakter, cijeli, pkarakter i pcijeli. Rogobatna sintaksa funkcije TipDek se prevazilazi
funkcijom
         function SlijediDekTipa(var tip: TTip):Boolean
         koja vraća true ako slijedi ime bilo kojeg tipa, a kao boĉni efekt u varijabli tip se dobije oznaka tog tipa.
         ImeTipa
                                       cijeli                   *


                                       karakter                *
                                                        Sl. 8.2.1.          Ime tipa
          Veliĉina prostora koji zauzima pojedinaĉna varijabla nekog tipa dobija se funkcijom DuzinaTipa. Za tip karakter,
ta vrijednost iznosi 1 bajt, dok za tipove cijeli, pkarakter i pcijeli veliĉina prostora je 4 bajta.


8.3.      Deklarisanje varijabli i nova struktura programa
          Nakon uvoĊenja identifikatora i imena tipa, moţe se pristupiti deklarisanju varijabli. Deklaracija varijabli izgleda kao
na slici Sl. 8.3.1.
         Deklaracija varijabli:

                                ImeTipa                                          Identifikator                    ;


                                                                                          ,
                                                Sl. 8.3.1.          Deklaracija varijabli
                                                                 38
        Na primjer:
            cijeli Duzina, Sirina;
            karakter * ime;


         U suštini, deklaracija svake nove varijable jednostavno povećava ukupnu veliĉinu prostora za same varijable, bilo u
prostoru za globalne varijable, bilo na steku za lokalne varijable. Tada se u slogu koji predstavlja dati identifikator upiše
relativna adresa gdje se nalazi varijabla kojoj se pristupa. Dakle, u generisanom asemblerskom kodu se ne ĉuva ime varijable.
         Pojam programa sada ukljuĉuje deklaraciju varijabli, definiciju funkcija i glavni blok. Varijable i funkcije se mogu u
programu neograniĉeno puta ponavljati. Ako se u glavnom bloku nalazi samo zatvorena zagrada, tada je rijeĉ o biblioteci
funkcija. Nova definicija pojma Program nalazi se na slici Sl. 8.3.2.
        Program:


                                     Deklaracija
                                     funkcije
                                                                                                 }

                                                                                           {         Blok

                                     Deklaracija
                                     varijabli
                                                      Sl. 8.3.2.             Program
        Deklaracija funkcije će biti prikazana kasnije.


8.4.     Izrazi i semantika
         UvoĊenje jedinstvenog sistema identifikatora zahtijeva izmjenu jeziĉkog pojma Faktor u kome se zbog toga ukida
sintaksa lokalnih varijabli sa znakom @, te prepoznavanje funkcije tako što joj ime poĉinje velikim slovom. Sada je pogodan
trenutak i za uvoĊenje znakovne konstante koja se, kao u C-u, navodi izmeĊu jednostrukih navodnika. Jeziĉki pojam Faktor
sada izgleda kao na slici Sl. 8.4.1
        Faktor:
                            -

                            ~

                            &
                                                   Faktor
                            *

                            !

                                              Numeriĉka konstanta

                                      (            Izraz dodjeljivanja            )


                                               Varijabla

                                      "                String
                                                       konstanta
                                                            Poziv funkcije


                                          „           Slovo                            „


                                                        Sl. 8.4.1.           Faktor
                                                                 39
         Realizacija slovne konstante je trivijalna i svodi se na prostu MOV AL,konstanta instrukciju. No, iako se sintaksno ne
mijenjaju ostali jeziĉki pojmovi koji saĉinjavaju izraz, procedure koje ga realizuju potrebno je radikalno promijeniti. Razlog
tome je uvoĊenje semantike i razliĉitih tipova.
         Ozbiljan semantiĉki problem da je u prethodnim verzijama kompajlera moguće napisati 5+3:=a-8; rješava se
uvoĊenjem varijabilnog parametra dod u sve procedure koje realizuju aritmetiĉke izraze. Prilikom obrade dijela izraza, ovom
parametru daje se vrijednost true, ako se tom dijelu izraza moţe dodijeliti vrijednost. Tipiĉno, to su varijable, elementi nizova i
lokacije na koje pokazuju pointeri. Ovaj parametar će se provjeravati u proceduri IzrazDodjeljivanja nakon prvog poziva
procedure Izraz i prijaviti greška ukoliko on nema taĉnu vrijednost.
        Procedurama koje predstavljaju dijelove aritmetiĉkih izraza dodaje se još jedan varijabilni parametar. Preko tog
parametra se vraća tip dijela aritmetiĉkog izraza, tj. da li je karakter, cijeli broj, pointer itd.
          Jezik koji se ovdje razvija spada u jezike slabe tipiziranosti i omogućava automatske konverzije izmeĊu podataka
razliĉitih tipova prilikom dodjeljivanja. To znaĉi da je legalno napisati
             a:=‟#‟+1;
         gdje je a cjelobrojna varijabla. Iako su sabirci u gornjem zbiru razliĉitog tipa (karakter i cijeli broj), ipak rezultat
predstavlja cijeli broj 36, jer je ASCII kôd znaka # jednak 35.
          Cijeli brojevi i pointeri zahtijevaju ĉetiri bajta za njihovo predstavljanje, dok se karakteri mogu smjestiti u jedan bajt.
Baš kao što se za smještanje cijelih brojeva u toku izraza koriste registri EAX, EBX i stek, za karaktere se koriste AL, BL i
stek, pri ĉemu se zbog karakteristika steka na stek smještaju ĉitavi EAX/EBX registri.
         U primjeru “a:=‟#‟+1” kompajler generiše kôd za smještanje konstante 35 u registar AL, ali nakon toga nalazi
cjelobrojnu konstantu 1, zakljuĉuje da je ipak rijeĉ o izrazu sa 32 bitnim rezultatom pa registar AL konvertuje u EAX i
nastavlja da generiše kôd kao da je rijeĉ o sabiranju dva 32 bitna broja. Konverzija registra AL u EAX se vrši postavljanjem
viših 24 bita na nula instrukcijom AND.
         Većina udţbenika o kompajlerima izbjegava miješanje razliĉitih tipova podataka unutar jednog aritmetiĉkog izraza.
Razlog je u tome što je broj potrebnih konverzija jednak kvadratu broja tipova koji se u tom izrazu mogu pojaviti. Razrješenju
tog problema pomaţu tablice, navedene u sljedećoj taĉki.


8.5.      Tablice generisanog koda za različite operande
         Pošto ima dosta kombinacija lijevog i desnog operanda, za sve binarne i unarne operatore potrebno je napraviti
odgovarajuće tablice koje odreĊuju kakav će se kôd generisati zavisno od operatora i tipa operanada. Pri prikazu generisanog
koda, dio koji se jednom ili više puta ponavlja (ukoliko se dati operator uzastopno ponavlja više puta) stavljen je u vitiĉaste
zagrade.
Operacija                        Desni      Karakter          cijeli            karakter *         cijeli *
                      Lijevi
                                            Clan              Clan              Nije dopušteno     Nije
        +             karakter              {                 {                                    dopušteno
                                            PUSH EAX          PUSH EAX
                                            Clan              Clan
Samo za sluĉaj                              POP EBX           POP EBX
sabiranja dva                               ADD AL,BL         AND EBX,0FFh
                                            }                 ADD EAX,EBX
karaktera                                                     }
                                            Clan              Clan              Nije dopušteno     Nije
rezultat je tipa      cijeli                {                 {                                    dopušteno
                                            PUSH EAX          PUSH EAX
karakter, u                                 Clan              Clan
svim ostalim                                POP EBX           POP EBX
                                            AND EAX,0FFh      ADD EAX,EBX
sluĉajevima                                 ADD EAX,EBX       }
                                            }
rezultat je                                 Nije dopušteno    Nije dopušteno    Nije dopušteno     Nije
                      karakter *                                                                   dopušteno
cijeli broj
                                            Nije dopušteno    Nije dopušteno    Nije dopušteno     Nije
                      cijeli *                                                                     dopušteno




                       Sl. 8.5.1.         Generisani kôd za sabiranje zavisno od tipova argumenata
                                                              40

Operacija                        Desni     Karakter         cijeli           karakter *       cijeli *
                      Lijevi
                                           Clan             Clan             Nije dopušteno   Nije
                      karakter             {                {                                 dopušteno
                                           PUSH EAX         PUSH EAX
        -                                  Clan
                                           MOV EBX,EAX
                                                            Clan
                                                            MOV EBX,EAX
                                           POP EAX          POP EAX
Samo za sluĉaj                             SUB AL,BL        AND EAX,0FFh
                                           }                SUB EAX,EBX
oduzimanja                                                  }
                                           Clan             Clan             Nije dopušteno   Nije
dva karaktera         cijeli               {                {                                 dopušteno
                                           PUSH EAX         PUSH EAX
rezultat je tipa                           Clan             Clan
                                           MOV EBX,EAX      MOV EBX,EAX
karakter, u                                POP EAX          POP EAX
                                           AND EBX,0FFh     SUB EAX,EBX
svim ostalim                               SUB EAX,EBX      }
sluĉajevima                                }
                                           Nije dopušteno   Nije dopušteno   Nije dopušteno   Nije
rezultat je           karakter *                                                              dopušteno
cijeli broj           cijeli *             Nije dopušteno   Nije dopušteno   Nije dopušteno   Nije
                                                                                              dopušteno



                      Sl. 8.5.2.         Generisani kôd za oduzimanje zavisno od tipova argumenata

          Iz tabela sa sabiranje i oduzimanje (Sl. 8.5.1 i Sl. 8.5.2) vidi se da pointerski tipovi ne mogu uĉestvovati u
operacijama sabiranja i oduzimanja. Samo ako su oba operanda karakteri koriste se instrukcije ADD AL,BL ili SUB AL,BL.
Ako je jedan operand karakter ubacuje se AND EAX,0FFh ili AND EBX,0FFh. Na ovaj naĉin se tri viša bajta EAX ili EBX
registra postavljaju na nule, bez izmjena registara AL odnosno BL. To predstavlja efikasnu konverziju izmeĊu karaktera i
cijelih brojeva. Ako su oba operanda cijeli brojevi, nema dodatnih instrukcija.


Operacija                        Desni     Karakter         cijeli           karakter *       cijeli *
                      Lijevi
                                           Clan             Clan             Nije dopušteno   Nije
        &             Cijeli ili           {                {                                 dopušteno
                      karakter             PUSH EAX         PUSH EAX
rezultat je                                Clan             Clan
                                           POP EBX          POP EBX
karakter ako su                            AND EAX,EBX      AND EAX,EBX
                                           }                }
oba argumenta
tog tipa, inaĉe
cijeli
                                           Clan             Clan             Nije dopušteno   Nije
        |             Cijeli ili           {                {                                 dopušteno
                      karakter             PUSH EAX         PUSH EAX
tip kao kod &                              Clan             Clan
                                           POP EBX          POP EBX
                                           OR EAX,EBX       OR EAX,EBX
                                           }                }
                                           Clan             Clan             Nije dopušteno   Nije
    ^                 Cijeli ili           {                {                                 dopušteno
                      karakter             PUSH EAX         PUSH EAX
tip kao kod &                              Clan             Clan
                                           POP EBX          POP EBX
                                           XOR EAX,EBX      XOR EAX,EBX
                                           }                }
                   Sl. 8.5.3.        Generisani kôd za logičke operacije zavisno od tipova argumenata

         Logiĉke operacije (Sl. 8.5.3) nemaju prijenosa, jer se obavljaju bit po bit. Kod ovih instrukcija nema potrebe za
specijalnim sluĉajevima u kodu.
                                                             41



Operacija                      Desni     Karakter          cijeli           karakter *        cijeli *
                    Lijevi
                                         Faktor            Faktor           Nije dopušteno    Nije
                    karakter             {                 {                                  dopušteno
                                         PUSH EAX          PUSH EAX
                                         Faktor            Faktor
                                         POP EBX           POP EBX
                                         AND EAX,0FFh      AND EBX,0FFh
   *                                     AND EBX,0FFh      IMUL EBX
                                         IMUL EBX          }
Tip rezultata je                         }
                                         Faktor            Faktor           Nije dopušteno    Nije
uvijek cijeli       cijeli               {                 {                                  dopušteno
                                         PUSH EAX          PUSH EAX
broj                                     Faktor            Faktor
                                         POP EBX           POP EBX
                                         AND EAX,0FFh      IMUL EBX
                                         IMUL EBX          }
                                         }
                                         Nije dopušteno    Nije dopušteno   Nije dopušteno    Nije
                    karakter *                                                                dopušteno

                                         Nije dopušteno    Nije dopušteno   Nije dopušteno    Nije
                    cijeli *                                                                  dopušteno


                      Sl. 8.5.4.       Generisani kôd za množenje zavisno od tipova argumenata

         Na slici Sl. 8.5.4 se vidi da pri mnoţenju nisu dopušteni pointeri kao faktori, a da se faktori koji su tipa karakter
trebaju prije mnoţenja konvertovati u cijeli broj instrukcijama AND EAX,0ffh ili AND EBX,0ffh.


Operacija                      Desni     Karakter          Cijeli           karakter *        cijeli *
                    Lijevi
                                         Faktor            Faktor           Nije dopušteno    Nije
                    karakter             {                 {                                  dopušteno
                                         PUSH EAX          PUSH EAX
    /                                    Faktor            Faktor
                                         MOV EBX,EAX       MOV EBX,EAX
                                         POP EAX           POP EAX
Tip rezultata je                         AND EAX,0FFh      AND EAX,0FFh
uvijek cijeli                            AND EBX,0FFh      CDQ
                                         CDQ               IDIV EBX
broj                                     IDIV EBX          }
                                         }
                                         Faktor            Faktor           Nije dopušteno    Nije
                    cijeli               {                 {                                  dopušteno
                                         PUSH EAX          PUSH EAX
                                         Faktor            Faktor
                                         MOV EBX,EAX       MOV EBX,EAX
                                         POP EAX           POP EAX
                                         AND EBX,0FFh      CDQ
                                         CDQ               IDIV EBX
                                         IDIV EBX          }
                                         }
                                         Nije dopušteno    Nije dopušteno   Nije dopušteno    Nije
                    karakter *                                                                dopušteno
                                         Nije dopušteno    Nije dopušteno   Nije dopušteno    Nije
                    cijeli *                                                                  dopušteno

                      Sl. 8.5.5.        Generisani kôd za dijeljenje zavisno od tipova argumenata
                                                                42


Operacija                       Desni      Karakter          Cijeli            karakter *        cijeli *
                     Lijevi
                                           Faktor            Faktor            Nije dopušteno    Nije
                     karakter              {                 {                                   dopušteno
                                           PUSH EAX          PUSH EAX
                                           Faktor            Faktor
                                           MOV EBX,EAX       MOV EBX,EAX
                                           POP EAX           POP EAX
                                           AND EAX,0FFh      AND EAX,0FFh
                                           AND EBX,0FFh      CDQ
   %                                       CDQ               IDIV EBX
                                           IDIV EBX          MOV EAX,EDX
                                           MOV EAX,EDX       }
Tip rezultata je                           }
uvijek cijeli        cijeli                Faktor
                                           {
                                                             Faktor
                                                             {
                                                                               Nije dopušteno    Nije
                                                                                                 dopušteno
broj                                       PUSH EAX          PUSH EAX
                                           Faktor            Faktor
                                           MOV EBX,EAX       MOV EBX,EAX
                                           POP EAX           POP EAX
                                           AND EBX,0FFh      CDQ
                                           CDQ               IDIV EBX
                                           IDIV EBX          MOV EAX,EDX
                                           MOV EAX,EDX       }
                                           }
                                           Nije dopušteno    Nije dopušteno    Nije dopušteno    Nije
                     karakter *                                                                  dopušteno
                                           Nije dopušteno    Nije dopušteno    Nije dopušteno    Nije
                     cijeli *                                                                    dopušteno

               Sl. 8.5.6.         Generisani kôd za ostatak pri dijeljenju zavisno od tipova argumenata


        Na slikama Sl. 8.5.5 i Sl. 8.5.6 se vidi da pri dijeljenju i ostatku pri dijeljenju nisu dopušteni pointeri kao operandi, a
da se operandi koji su tipa karakter trebaju prije dijeljenja konvertovati u cijeli broj instrukcijama AND EAX,0ffh ili AND
EBX,0ffh.

Operacija                       Desni    Karakter           cijeli            karakter *        cijeli *
                     Lijevi
                                         Izraz              Izraz             Izraz             Izraz
                     karakter            PUSH EBX           PUSH EBX          PUSH EBX          PUSH EBX
                                         Izrazdodjelj       Izrazdodjelj      Izrazdodjelj      Izrazdodjelj
                                         POP EBX            POP EBX           POP EBX           POP EBX
                                         MOV [EBX],AL       MOV [EBX],AL      MOV [EBX],AL      MOV [EBX],AL
                                         Izraz              Izraz             Izraz             Izraz
                     cijeli              PUSH EBX           PUSH EBX          PUSH EBX          PUSH EBX
                                         Izrazdodjelj       Izrazdodjelj      Izrazdodjelj      Izrazdodjelj
  :=                                     POP EBX            POP EBX           POP EBX           POP EBX
                                         MOV [EBX],EAX      MOV [EBX],EAX     MOV [EBX],EAX     MOV [EBX],EAX
                                         Nije dopušteno     Izraz             Izraz             Izraz
Tip rezultata je     karakter *                             PUSH EBX          PUSH EBX          PUSH EBX
tip koji ima                                                Izrazdodjelj      Izrazdodjelj      Izrazdodjelj
                                                            POP EBX           POP EBX           POP EBX
operand sa                                                  MOV [EBX],EAX     MOV [EBX],EAX     MOV [EBX],EAX
                                         Nije dopušteno     Izraz             Izraz             Izraz
lijeve strane        cijeli *                               PUSH EBX          PUSH EBX          PUSH EBX
operatora                                                   Izrazdodjelj      Izrazdodjelj      Izrazdodjelj
                                                            POP EBX           POP EBX           POP EBX
                                                            MOV [EBX],EAX     MOV [EBX],EAX     MOV [EBX],EAX
                    Sl. 8.5.7.          Generisani kôd za dodjeljivanje zavisno od tipova argumenata

         Iz tabele Sl. 8.5.7 vidi se da se karakter ne smije dodijeliti pointeru, a da je meĊusobna razlika svih ostalih
kombinacija tipova operanada u tome što ako se s lijeve strane izraza dodjeljivanja nalazi varijabla karakterskog tipa, da se na
navedenu adresu na koji pokazuje registar EBX upisuje sadrţaj registra AL. Pointerske varijable se mogu dodjeljivati
cjelobrojnim i obrnuto, bez eksplicitnog navoĊenja imena tipa (type casting).
                                                               43




Operacija                      Desni      Karakter          cijeli           karakter *     cijeli *
                    Lijevi
                                          Izraz             Izraz            Izraz          Izraz
                    karakter              PUSH EAX          PUSH EAX         PUSH EAX       PUSH EAX
                                          Izraz             Izraz            Izraz          Izraz
                                          POP EBX           POP EBX          POP EBX        POP EBX
                                          CMP BL,AL         AND EAX,0FFh     AND EAX,0FFh   AND EAX,0FFh
                                          SETE AL           CMP EBX,EAX      CMP EBX,EAX    CMP EBX,EAX
                                          AND EAX,0FFh      SETE AL          SETE AL        SETE AL
                                                            AND EAX,0FFh     AND EAX,0FFh   AND EAX,0FFh
  =#<>              cijeli                Izraz             Izraz            Izraz          Izraz
                                          PUSH EAX          PUSH EAX         PUSH EAX       PUSH EAX
                                          Izraz             Izraz            Izraz          Izraz
                                          POP EBX           POP EBX          POP EBX        POP EBX
                                          AND EBX,0FFh      CMP EBX,EAX      CMP EBX,EAX    CMP EBX,EAX
Tip rezultata je                          CMP EBX,EAX       SETE AL          SETE AL        SETE AL
                                          SETE AL           AND EAX,0FFh     AND EAX,0FFh   AND EAX,0FFh
uvijek cijeli                             AND EAX,0FFh
broj.                                     Izraz             Izraz            Izraz          Izraz
                    karakter *            PUSH EAX          PUSH EAX         PUSH EAX       PUSH EAX
Promijeniti                               Izraz             Izraz            Izraz          Izraz
                                          POP EBX           POP EBX          POP EBX        POP EBX
instrukciju                               AND EBX,0FFh      CMP EBX,EAX      CMP EBX,EAX    CMP EBX,EAX
                                          CMP EBX,EAX       SETE AL          SETE AL        SETE AL
SETE u                                    SETE AL           AND EAX,0FFh     AND EAX,0FFh   AND EAX,0FFh
                                          AND EAX,0FFh
Za = SETE           cijeli *              Izraz             Izraz            Izraz          Izraz
                                          PUSH EAX          PUSH EAX         PUSH EAX       PUSH EAX
                                          Izraz             Izraz            Izraz          Izraz
Za < SETL                                 POP EBX           POP EBX          POP EBX        POP EBX
                                          AND EBX,0FFh      CMP EBX,EAX      CMP EBX,EAX    CMP EBX,EAX
Za > SETG                                 CMP EBX,EAX       SETE AL          SETE AL        SETE AL
                                          SETE AL           AND EAX,0FFh     AND EAX,0FFh   AND EAX,0FFh
                                          AND EAX,0FFh
Za # SETNE
                     Sl. 8.5.8.        Generisani kôd za poreĎenje zavisno od tipova argumenata

         Tabela na slici Sl. 8.5.8 obuhvata sva ĉetiri relaciona operatora, pri ĉemu je za svaki navedeni operator potrebno
upisati odgovarajuću SETxx instrukciju.
        Unarni operatori i generisani kôd za njih su navedeni na slici Sl. 8.5.9.


Operacija             Karakter                     cijeli                     karakter *         cijeli *
                      Nije dopušteno               Faktor                     Nije dopušteno     Nije dopušteno
Unarni -                                           NEG EAX
                                                   (rez. tip je cijeli )
                      Nije dopušteno               Nije dopušteno             Faktor             Faktor
Unarni *                                                                      MOV EBX,EAX        MOV EBX,EAX
                                                                              MOV EAX,[EBX]      MOV EAX,[EBX]
                                                                              AND EAX,0FFh       (rez. tip je
                                                                              (rez. tip je       cijeli)
                                                                              karakter )
                      Faktor                       Faktor                     Faktor             Faktor
Unarni &              MOV EAX,EBX                  MOV EAX,EBX                MOV EAX,EBX        MOV EAX,EBX
                      (rez. tip je karakter *)     (rez. tip je cijeli *)     (rez. tip je       (rez. tip je
                                                                              cijeli *)          cijeli *)
                      CMP EAX,0                    CMP EAX,0                  Nije dopušteno     Nije dopušteno
Unarni !              SETE AL                      SETE AL
                      AND EAX,0FFh                 (rez. tip je cijeli )
                      (rez. tip je karakter )
                      Faktor                       Faktor                     Nije dopušteno     Nije dopušteno
Unarni ~              NOT AL                       NOT EAX
                      (rez. tip je karakter )      (rez. tip je cijeli )

                Sl. 8.5.9.         Generisani kôd za unarne operatore zavisno od tipova argumenata

         Na bazi gornjih tabela se mijenjaju funkcije Clan, Faktor, Izraz i IzrazDodjeljivanja. Iskorištavaju se uoĉene
pravilnosti u generisanom kodu, jer nema potrebe mnogo puta ponavljati isti skup naredbi.


8.6.     Funkcije i provjera parametara
         Deklaracija funkcije se u ovoj verziji kompajlera proširuje definisanjem svih parametara i lokalnih varijabli koje
funkcija moţe imati, kao na slici Sl. 8.6.1.
                                                                    44




 ImeTipa        funkcija       Identifi-               Ime         Identifi-                  Deklaracia   Blok
                                 kator
                                             (                                     )   {
                                                       Tipa          kator                    varijabli




                                                               ,
                                                                                                   ;

                                                  Sl. 8.6.1.           Deklaracija funkcije

        Deklarisanje parametara i lokalnih varijabli se realizuje tako da se za svaki prepoznati identifikator dodaju podaci o
njemu u tabelu identifikatora, pri ĉemu se za nivo uzima pozicija identifikatora funkcije u tabeli svih identifikatora.
         Po Windowsovom standardu svi parametri, bez obzira na veliĉinu, moraju biti poravnati na adrese djeljive sa 4. Pod
poravnanjem se podrazumijeva smještanje svih podataka tako da poĉinju od adrese djeljive s nekim paranim brojem. Lokalne
varijable moraju biti poravnate na adrese djeljive sa 4 ako je njihova duţina djeljiva sa 4. Prema redoslijedu smještanja
parametara na stek razlikuju se konvencije:
           a)   C call, parametri se smještaju na stek PUSH instrukcijama u obrnutom redoslijedu u odnosu na navedeni u pozivu
                funkcije, a poziciju stek pointera vraća u prvobitno stanje glavni program. Ovaj naĉin poziva se koristi u
                Windows API funkciji wvsprintf i svim funkcijama biblioteke MSVCRT.DLL (biblioteka Microsoft C
                kompajlera)
           b) Pascal call, parametri se smještaju na stek PUSH instrukcijama u istom redoslijedu u odnosu na navedeni, a
              poziciju stek pointera vraća u prvobitno stanje potprogram. Koristi se u svim sistemskim pozivima za Windows
              3.1 aplikacije
           c)   StdCall, parametri se smještaju na stek PUSH instrukcijama u obrnutom redoslijedu u odnosu na navedeni, a
                poziciju stek pointera vraća u prvobitno stanje potprogram. Koristi se u većini Win32 API funkcija.
           d) Fast Call, parametri su u registrima, koristi se pri pozivu DOS interapta
           e)   Inline Call, parametri se navode u memorijskom bloku, (na fiksnoj lokaciji ili neposredno iza CALL instrukcije=
                obiĉno se interno koristi u asemblerskim programima.
          Najlakše je prilagoditi postojeći kompajler da generiše pozive po Pascal Call standardu, pa će ovaj naĉin poziva biti i
implementiran. Pri tome će se ime potprograma generisati od imena funkcije iza kojeg slijedi znak @ i ukupan broj bajtova
koliko zauzimaju parametri. Tako na primjer funkcija ĉije je ime Racunaj i koja ima tri parametra će u generisanom kodu
imati ime Racunaj@12. Ovo je uĉinjeno da bi se postigla izvjesna kompatibilnost sa Win32 API funkcijama koje imaju
interno iste ovakve nazive, a kojih postoji preko 9000.
         Windows API funkcije, meĊutim, koriste standard StdCall, koje zahtijeva suprotan redoslijed postavljanja parametara
na stek od standarda Pascal Call. Ovaj problem je rješiv tako što se pri pozivu ovih funkcija navode parametri obrnutim
redoslijedom u odnosu na onaj kojim se parametri navode u jeziku C i kako su definisan u standardnoj dokumentaciji za
Windows API.
           Generisani kôd za definiciju funkcije izgleda kao na slici Sl. 8.6.2.

                           PUSH EBP
                           Racunaj@12: (zavisno od imena i prostora za parametre)
                           MOV EBP,ESP
                           SUB ESP,velicina prostora za lokalne varijable
                           Pozovi Blok;
                           MOV ESP,EBP
                           POP EBP
                           RET velicina prostora za parametre
                           PUBLIC Racunaj@12


                                     Sl. 8.6.2.          Definicija funkcije, generisani kôd
         Postavljanje EBP registra na mjesto gdje se ESP nalazio prije alokacije prostora za lokalne varijable, omogućava da
se lokalnim varijablama pristupa sa MOV EAX,[EBP-nn] a parametrima sa MOV EAX,[EBP+nn]. Odgovarajuće konstante nn
se raĉunaju prilikom deklaracija lokalnih varijabli i parametara i nalaze se u polju adresa tabele identifikatora. Za parametre,
prije dohvatanja prvog parametra ovo polje ima vrijednost 0, a zatim se uvećava za ((duzinavarijable-1) div 4 + 1)*4 nakon
                                                            45
svakog deklarisanog parametra. Za lokalne varijable, prije dohvatanja prve lokalne varijable, ovo polje ima vrijednost 0, a
zatim se, kako se redom dohvataju varijable, po apsolutnoj vrijednosti uvećava za duzinavarijable, a upisuje se negativna
vrijednost.
        Generisani kôd za poziv funkcije, prikazan na slici Sl. 8.6.3 se vrlo malo promijenio od prethodne verzije kompajlera


                  Za svaki parametar (osim ako se karakter prosljeĎuje pointeru što je greška):
                               Pozovi Izrazdodjeljivanja
                               Ako se karakter prosljeĎuje cijelim brojevima generiši AND EAX,0FFh
                               PUSH EAX
                  MOV ECX,ukupna veličina svih parametara
                  CALL funkcija@duzinaparametara
                  Ako funkcija vraća karakter generiši AND EAX,0FFh


                                       Sl. 8.6.3.        Generisani kôd za poziv funkcije


          Globalnim varijablama se i sada pristupa sa MOV EAX,GLOBALV[nn] pri ĉemu se nn nalazi u polju adresa tabele
identifikatora. Ako je varijabla tipa karakter registar EAX treba zamijeniti registrom AL. Prilikom deklaracije globalnih
varijabli prije dohvatanja prve globalne varijable ovo polje ima vrijednost 0, a zatim se kako se redom dohvataju varijable po
apsolutnoj vrijednosti uvećava za duzinavarijable.
        Koristeći sve ove informacije, moţe se napisati nova verzija kompajlera. Navedena je u prilogu broj 5.


8.7.     Testni primjer
         Primjer programa u petoj verziji jezika moţe biti identiĉan prethodnom primjeru, uz izbacivanje potrebe da se dijelovi
pišu u asembleru. Ipak, pošto dosadašnji primjeri nisu imali ulaz, dodano je da se unese ime korisnika na poĉetku, a zatim ono
i prikaţe na ekranu. Za ĉitanje se koristi API funkcija ReadConsoleA, koja ima iste parametre kao i WriteConsoleA, samo što
zahtijeva standardni hendl –10, umjesto –11.


        Primjer se prevodi koristeći
            komp32v5 tabbroj2.jez tabbro2j.asm
            ml /c /coff /Fl tabbroj2.asm | more
            link /defaultlib:user32.lib kernel32.lib /subsystem:console tabbroj2.obj


        Izvorni kôd primjera naveden je na slici Sl. 8.7.1
                                                              46

cijeli funkcija GetStdHandle(cijeli brhan);                         bafer[pokazivac]:='-';
cijeli funkcija WriteConsoleA(cijeli rez,cijeli * upisano,          pokazivac:=pokazivac-1;
  cijeli upisati,karakter * bafer,cijeli han);                   }
cijeli funkcija ReadConsoleA(cijeli rez,cijeli * upisano,        bafer:=&(bafer[pokazivac+1]);
  cijeli upisati,karakter * bafer,cijeli han);                 ` Pomjeri pokazivac pocetka stringa
cijeli * a; ` Ovo je zapravo niz pointera na stringove           Prikazistring(bafer);
cijeli * ime;                                                  }
cijeli funkcija Prikazistring (karakter * poruka){             cijeli funkcija Fact(cijeli a)
  cijeli handle,priv,duz;                                      {
    handle:=GetStdHandle(-11);                                     ako (a=0)
    duz:=0;                                                          {
    dok (poruka[duz]#0) { duz:=duz+1;}                                   1;
    WriteConsoleA(0,&priv,duz,poruka,handle);                        }
}                                                                  inace
cijeli funkcija Unesistring (karakter * poruka){                     {
  cijeli handle,priv,duz;                                                a*Fact(a-1);
    handle:=GetStdHandle(-10);                                       }
    duz:=30;                                                   }
    ReadConsoleA(0,&priv,duz,poruka,handle);                   cijeli funkcija Tabela()
}                                                              {
cijeli funkcija Novired () {                                       cijeli m,n;
  karakter * dvoznak;                                              Prikazistring("Tabela");
  dvoznak:=" ";                                                    Novired();
  dvoznak[0]:=13;                                                  n:=1;
  dvoznak[1]:=10;                                                  dok (n<11) {
  Prikazistring(dvoznak);                                              Prikazibroj (n);
}                                                                      Prikazistring(" ");
cijeli funkcija Predstavljanje ()                                      Prikazistring(a[n]);
{                                                                      Prikazistring(" ");
    ime:="                                         ";                  Prikazibroj (n*n);
    Unesistring(ime);                                                  Prikazistring(" ");
    Prikazistring("Tabelu generisao ");                                Prikazibroj (n*n*n);
    Prikazistring(ime);                                                Prikazistring(" ");
    Novired();                                                         Prikazibroj (Fact(n));
}                                                                      Prikazistring(" Djeljiv sa ");
cijeli funkcija Prikazibroj (cijeli broj){                             m:=1;
  cijeli cifra,negativan,pokazivac,ostatak;                            dok !(m>n) {
  karakter * bafer;                                                       ako (n%m=0) {
  bafer:="             "; ` Alociramo bafer                                 Prikazibroj(m);
  cifra:=broj;                                                              Prikazistring(" ");
` Negativne brojeve oznaci indikatorom                                    }
  ako (cifra<0)                                                           m:=m+1;
    {                                                                  }
       negativan:=1;                                                   n:=n+1;
       cifra:=-cifra;                                                  Novired();
    }                                                              }
      inace                                                    }
    {                                                          cijeli funkcija Postavinazive()
      negativan:=0;                                            {
    }                                                            a:="                                                  ";
`maksimalno 9 cifara                                                 ` Prostor za niz
  pokazivac:=9;                                                  a[1]:="Jedan";
  ako (cifra=0) {                                                a[2]:="Dva";
      bafer[pokazivac]:='0';                                     a[3]:="Tri";
      pokazivac:=pokazivac-1;                                    a[4]:="Cetiri";
  }                                                              a[5]:="Pet";
  dok (cifra>0)                                                  a[6]:="Sest";
  {                                                              a[7]:="Sedam";
       ostatak:=(cifra % 10);                                    a[8]:="Osam";
`ostatke dijeljenja u bafer                                      a[9]:="Devet";
       bafer[pokazivac]:=ostatak+'0';                            a[10]:="Deset";
       cifra:=cifra/10; ` stalno dijeli s 10                   }
       pokazivac:=pokazivac-1;                                 { Predstavljanje();
  }                                                                Postavinazive();
  ako (negativan=1)                                                Tabela();
  {                                                            }



                           Sl. 8.7.1.        Primjer: Tablica brojeva bez asemblerskih modula

8.8.     Rezime poglavlja
Ova verzija kompajlera predstavlja veliki skok naprijed i omogućava realizaciju većine aplikacija koje koriste cijele brojeve i
stringove. Uvedeni su tipovi cijeli, cijeli *, realni i realni *. Program se sada sastoji iz deklaracija varijabli, deklaracija
funkcija i tijela programa Imena varijabli se sastoje iz više slova, pa je potrebna tablica identifikatora. Pri pozivu funkcija
provjerava se broj i tipovi argumenata. UvoĊenje tipova usloţnjava aritmetiĉke izraze i zahtijeva paţljivo praćenje generisanog
koda za svaku kombinaciju operanada razliĉitog tipa. U testnim primjerima opada potreba za asemblerom.
                                                             47
Prilog 5: Verzija izvornog koda kompajlera br. 5
program Kompajler;                        end;                                            if Length(linija) >= n then begin
const                                                                                       znak := linija[n];
  MAXIDENT = 1024;                        procedure Greska(poruka: string);                 if ((znak >= 'a') and (znak <=
  DUGAKONST =                             begin                                               'z')) or
    'Konstanta prevazilazi liniju';         WriteLn(poruka);                                  ((znak >= 'A') and (znak <=
  OCEKIVANO = 'Ocekivano ';                 WriteLn(brojaclinija, ':', linija);               'Z')) then
  REDEKLAR =                                Close(ulaz);                                      ureduiza := false
    'Redeklarisan identifikator';           Close(izlaz);                                 end
  PROSTNIZ =                                Halt;                                      end;
    'Prosti tip ne moze biti niz';        end;                                         if ureduiza and (copy(linija,
  NEKORARG =                                                                              pozicija,
    'Nekorektan broj argumenata';         procedure Emit(st: string);                     Length(ocekivano)) = ocekivano) then
  NEKDODJP = 'Losa dodjela pointeru';     begin                                             begin
  NEDEKL = 'Nedeklarisano ';                WriteLn(izlaz, st);                           Slijedi := true;
  GRIZRAZ = 'Izraz';                      end;                                            pozicija := pozicija +
  POGRMNOZ =                                                                                Length(ocekivano) - 1;
    'Pogresan tip u ' +                   procedure Novi;                              end
    'mnozenju ili dijeljenju';            begin                                        else
  NEDOPFP =                                 repeat                                        Slijedi := false;
    ' Nedopustena FP operacija';               pozicija := pozicija + 1;             end;
  NEDOPARIT =                                  if pozicija > Length(linija) then
    'Nedopusteni tip u aritmetici';              begin                               function TipDek(imetipa: string; var
  OCEKDOD = 'Ocekivano dodjeljivanje';           brojaclinija := brojaclinija + 1;     tip: TTip;
  NEDODJ =                                       if not (Eof(ulaz)) then               stip, ptip: TTip): Boolean;
    'Izraz se ne moze dodijeliti';                  ReadLn(ulaz, linija);            begin
  DODJPOINT = 'Losa dodjela pointeru';           Emit(';' + linija);                   TipDek := false;
  TIPUSL = 'Neodgovarajuci tip uslova';          pozicija := 1;                        if Slijedi(imetipa, false) then begin
  TUSLPET =                                    end;                                       TipDek := true;
    'Neodgovarajuci uslov u petlji';           if Length(linija) > 0 then                 Novi;
  IMEFUN = 'Ocekivano ime funkcije';             znak := linija[pozicija]                 if znak = '*' then begin
  DEFFUN = 'Definicija funkcije';              else                                         tip := ptip;
  ARGNEKOM =                                     znak := ' ';                               Novi
    'Argument nekompatibilan' +                if (znak = '`') then                       end
    ' s operatorom';                             pozicija := Length(linija);              else
  OCIDENT =                                 until ((znak > ' ') and (znak <>                tip := stip;
    'Ocekivan Identifikator';                  '`')) or Eof(ulaz)                      end
                                          end;                                       end;
type
  TVrsta = (funkcija, lokalna,            procedure NoviSvaki(greskakrln:            function SlijediDekTipa(var tip: TTip):
     globalna, parametar);                  Boolean);                                  Boolean;
  TTip = (karakter, cijeli, pkarakter,    begin                                      var
     pcijeli);                              pozicija := pozicija + 1;                  a: Boolean;
  TIdent = record                           if pozicija > Length(linija) then        begin
     ime: string[20];                          begin                                   a := false;
     duzina: integer;                          if greskakrln then                      if not (a) then
     adresa: integer;                            Greska(DUGAKONST)                        a := TipDek('cijeli', tip, cijeli,
     nivo: integer;                            else                                         pcijeli);
     vrsta: TVrsta;                              znak := ' ';                          if not (a) then
     tip: TTip;                             end                                           a := TipDek('karakter', tip,
     pod1: integer;                         else                                            karakter, pkarakter);
     pod2: integer;                            znak := linija[pozicija];               SlijediDekTipa := a;
     pod3: integer;                       end;                                       end;
  end;
                                          procedure IdiDo(z: char);                  function DuzinaTipa(tip: TTip):
var                                       begin                                        Integer;
  ulaz, izlaz: text;                        if (znak <> z) then                      begin
  pozicija, trenlabela, brojaclinija,          Greska(OCEKIVANO + z);                  case tip of
    aktnivo: integer;                       Novi;                                         cijeli, pcijeli, pkarakter:
  znak: char;                             end;                                              DuzinaTipa := 4;
  linija: string;                                                                         karakter: DuzinaTipa := 1;
  TabIdent: array[0..MAXIDENT] of         function UzmiKonstantu                       else
  TIdent;                                   (var t: TTip; var dod: Boolean):              DuzinaTipa := 4;
  ukupnoident: integer;                     integer;                                   end;
  t: TTip;                                var                                        end;
  dod: Boolean;                             rezultat: integer;
                                          begin                                      function NadjiIdent(ident: string;
procedure NoviIdent(pime: string;           rezultat := 0;                             nivo, tuslova, p1: integer): integer;
  pduzina: integer;                         while (znak >= '0') and (znak <= '9')    var
  padresa: integer; pnivo: integer;            do begin                                n, poz: integer;
  pvrsta: TVrsta;                              rezultat := 10 * rezultat +             nadjen, Uslov: Boolean;
  ptip: TTip; ppod1: integer; ppod2:             ord(znak) - ord('0');               begin
  integer; ppod3: integer);                    NoviSvaki(false);                       n := ukupnoident;
begin                                       end;                                       nadjen := false;
  ukupnoident := ukupnoident + 1;           if (znak = ' ') or (znak = '`') then       poz := 0;
  with TabIdent[ukupnoident] do begin          Novi;                                   while (n > 0) and (not (nadjen)) do
     ime := pime;                           UzmiKonstantu := rezultat;                   begin
     duzina := pduzina;                     t := cijeli;                                 case tuslova of
     adresa := padresa;                     dod := false;                                  1: Uslov := (TabIdent[n].ime =
     nivo := pnivo;                       end;                                                 ident) and
     vrsta := pvrsta;                                                                        (TabIdent[n].vrsta in
     tip := ptip;                         function Slijedi(ocekivano: string;                  [lokalna, globalna,
     pod1 := ppod1;                         dslovoiza: Boolean): Boolean;                      parametar, funkcija]) and
     pod2 := ppod2;                       var                                                  ((TabIdent[n].nivo = nivo) or
     pod3 := ppod3;                         ureduiza: Boolean;                                 (TabIdent[n].nivo = 0));
  end;                                      n: integer;                                    2: Uslov := (TabIdent[n].ime =
end;                                        znak: char;                                        ident) and
                                          begin                                              (TabIdent[n].vrsta in
procedure NovaLabela(var ImeLabele:         if dslovoiza then                                  [lokalna, globalna,
  string);                                    ureduiza := true                                 parametar, funkcija]) and
begin                                       else begin                                         ((TabIdent[n].nivo = nivo));
  trenlabela := trenlabela + 1;               n := pozicija + Length(ocekivano);           4: Uslov := (TabIdent[n].nivo =
  Str(trenlabela, ImeLabele);                 ureduiza := true;                                nivo) and
                                                            48
        (TabIdent[n].pod2 = p1) and           '''''' then                                   cijeli: Emit(' NEG EAX');
          (TabIdent[n].vrsta =                st := 'L' + strtekst + ' DB 0';            else
          parametar)                       Emit(st);                                        Greska(err);
     else                                  Emit('.CODE');                                end;
       Uslov := false;                     Emit(' MOV EAX,OFFSET L' + strtekst);         dod := false;
     end;                                  t := pkarakter;                             end;
     if Uslov then begin                   dod := false;                             '~': begin
       nadjen := true;                   end;                                            Novi;
       poz := n;                                                                         Faktor(t, dod);
     end;                                procedure PozivFunkcije                         case t of
     n := n - 1;                           (idpoz: integer; var t: TTip; var                cijeli: Emit(' NOT EAX');
  end;                                     dod: Boolean);                                   karakter: Emit(' NOT AL');
  NadjiIdent := poz;                     var                                             else
end;                                       parametara, N, velsteka: integer;                Greska(err);
                                           t1, t2: TTip;                                 end;
procedure UzmiIdent(var ident: string);    ImeFunkcije, st: string;                      dod := false;
begin                                    begin                                         end;
  if znak in ['a'..'z', 'A'..'Z'] then     ImeFunkcije := TabIdent[idpoz].ime;       '&': begin
     begin                                 parametara := 0;                              Novi;
     ident := znak;                        velsteka := 0;                                Faktor(t, dod);
     NoviSvaki(false);                     IdiDo('(');                                   Emit(' MOV EAX,EBX');
  end                                      while (znak <> ')') do begin                  case t of
  else                                        IzrazDodjeljivanja(t1, dod);                  cijeli: t := pcijeli;
     Greska(OCIDENT);                         parametara := parametara + 1;                 karakter: t := pkarakter;
  while (znak in ['a'..'z', 'A'..'Z',         n := NadjiIdent('', idpoz, 4,              else
     '0'..'9', '_']) do begin                   parametara);                                t := pcijeli;
     ident := ident + znak;                   if n = 0 then                              end;
     NoviSvaki(false);                          Greska(NEKORARG);                        dod := false;
  end;                                        t2 := TabIdent[n].tip;                   end;
  if (znak = ' ') or (znak = '`') then        if (t1 = karakter) and                 '*': begin
     Novi;                                      (t2 in [pkarakter, pcijeli]) then        Novi;
end;                                            Greska(NEKDODJP);                        Faktor(t, dod);
                                              if (t1 = karakter) and (t2 = cijeli)       Emit(' MOV EBX,EAX');
procedure DeklIdent(var ident: string;          then                                     Emit(' MOV EAX,[EBX]');
  nivo: integer);                               Emit(' AND EAX,0FFh');                   case t of
begin                                         velsteka := velsteka + 4;                     pcijeli: t := cijeli;
  UzmiIdent(ident);                           Emit(' PUSH EAX');                            pkarakter: begin
  if NadjiIdent(ident, nivo, 2, 0) <> 0       if znak <> ')' then                               t := karakter;
     then                                       IdiDo(',');                                     Emit(' AND EAX,0FFh');
     Greska(REDEKLAR);                     end;                                               end;
end;                                       IdiDo(')');                                   else
                                           if TabIdent[idpoz].pod1 <> parametara            Greska(err);
procedure IzrazDodjeljivanja                  then                                       end;
  (var t: TTip; var dod: Boolean);            Greska(NEKORARG);                          dod := true;
  forward;                                 Str(velsteka, st);                          end;
procedure Blok; forward;                   Emit(' MOV ECX,' + st);                   '!': begin
                                           Emit(' CALL ' + ImeFunkcije + '@' +           Novi;
procedure PokazivacINiz(var t: TTip; var      st);                                       Faktor(t, dod);
  dod: Boolean);                           dod := false;                                 case t of
var                                        t := TabIdent[idpoz].tip;                        cijeli: Emit(' CMP EAX,0');
  t1: TTip;                                if t = karakter then                             karakter: Emit(' CMP AL,0');
begin                                         Emit(' AND EAX,0FFh0');                    else
  Novi;                                  end;                                               Greska(err);
  Emit(' PUSH EAX');                                                                     end;
  IzrazDodjeljivanja(t1, dod);           procedure Varijabla                             Emit(' SETE AL');
  Emit(' POP EBX');                        (idpoz: integer; var t: TTip; var             Emit(' AND EAX,0FFh');
  case t of                                dod: Boolean; glob: Boolean);                 dod := false;
     pkarakter: begin                    var                                             t := cijeli;
          t := karakter;                   rezultat: integer;                          end;
       end;                                st: string;                               '"': begin
     pcijeli: begin                      begin                                           StringKonstanta(t, dod);
          Emit(' SAL EAX,2');              rezultat := TabIdent[idpoz].adresa;         end;
          t := cijeli;                     t := TabIdent[idpoz].tip;                 '''': begin
       end;                                Str(rezultat, st);                            NoviSvaki(true);
  else                                     if glob then                                  Emit(' MOV AL,''' + znak +
     Greska(PROSTNIZ)                         Emit(' LEA EBX,GLOBALV[' + st + ']')          '''');
  end;                                     else begin                                    Novi;
  Emit(' ADD EBX,EAX');                       if rezultat >= 0 then                      IdiDo('''');
  case t of                                     Emit(' LEA EBX,[EBP+' + st + ']')        t := karakter;
     karakter:                                else                                     end;
       Emit(' MOV AL,[EBX]');                   Emit(' LEA EBX,[EBP' + st + ']');    '0'..'9': begin
  else                                     end;                                          rezultat := UzmiKonstantu(t,
     Emit(' MOV EAX,[EBX]');               case t of                                        dod);
  end;                                        karakter: Emit(' MOV AL,[EBX]');           Str(rezultat, st);
  IdiDo(']');                              else                                          Emit(' MOV EAX,' + st);
  dod := true;                                Emit(' MOV EAX,[EBX]');                  end;
end;                                       end;                                      '(': begin
                                           dod := true;                                  Novi;
procedure StringKonstanta(var t: TTip;     if znak = '[' then                            IzrazDodjeljivanja(t, dod);
  var dod: Boolean);                          PokazivacINiz(t, dod);                     IdiDo(')');
var                                      end;                                          end;
  st, strtekst: string;                                                              'A'..'Z', 'a'..'z': begin
begin                                    procedure Faktor(var t: TTip; var dod:          UzmiIdent(ime);
  NovaLabela(strtekst);                    Boolean);                                     poz := NadjiIdent(ime, aktnivo,
  Emit('.DATA');                         var                                                1, 0);
  st := 'L' + strtekst + ' DB ''';         rezultat, poz: integer;                       if poz = 0 then
  repeat                                   st, ime, err: string;                            Greska(NEDEKL + ime);
     NoviSvaki(true);                    begin                                           case TabIdent[poz].vrsta of
     if znak <> '"' then                   err := ARGNEKOM;                                 funkcija:
       st := st + znak;                    case znak of                                       PozivFunkcije(poz, t, dod);
  until znak = '"';                           '-': begin                                    lokalna, parametar:
  IdiDo('"');                                      Novi;                                      Varijabla(poz, t, dod,
  st := st + ''',0';                               Faktor(t, dod);                              false);
  if copy(st, length(st) - 3, 2) =                 case t of                                globalna:
                                                                 49
              Varijabla(poz, t, dod, true)               Emit(' POP EAX');                 sonda, sinace, skrajuslova: string;
        end                                              if (t1 = karakter) and (t2 =    begin
      end;                                                  karakter) then begin           Novi;
  else                                                      t := karakter;                 IzrazDodjeljivanja(t, dod);
     Greska(GRIZRAZ);                                       Emit(' SUB AL,BL');            if t <> cijeli then
  end;                                                   end                                  Greska(TIPUSL);
end;                                                     else begin                        Emit(' CMP EAX,0');
                                                            t := cijeli;                   NovaLabela(sonda);
procedure Clan(var t: TTip; var dod:                        if t1 = karakter then          NovaLabela(sinace);
  Boolean);                                                   Emit(' AND EAX,0FFh');       NovaLabela(skrajuslova);
var                                                         if t2 = karakter then          Emit(' JNE L' + sonda);
  z: char;                                                    Emit(' AND EBX,0FFh');       Emit(' JMP L' + sinace);
  t1, t2: TTip;                                             Emit(' SUB EAX,EBX');          IdiDo('{');
begin                                                    end;                              Emit('L' + sonda + ':');
  Faktor(t1, dod);                                     end;                                Blok;
  t := t1;                                          '&', '|', '^': begin                   Emit(' JMP L' + skrajuslova);
  while (znak in ['*', '/', '%']) do                     if (t1 = karakter) and (t2 =      Emit('L' + sinace + ':');
     begin                                                  karakter) then                 if Slijedi('inace', false) then begin
     z := znak;                                             t := karakter                     Novi;
     Emit(' PUSH EAX');                                  else                                 IdiDo('{');
     Novi;                                                  t := cijeli;                      Blok;
     Faktor(t2, dod);                                    Emit(' POP EBX');                 end;
     dod := false;                                       case z of                         Emit('L' + skrajuslova + ':');
     if ((t1 <> cijeli) and (t1 <>                          '&': Emit(' AND EAX,EBX');   end;
       karakter)) or                                        '|': Emit(' OR EAX,EBX');
       ((t2 <> cijeli) and (t2 <>                           '^': Emit(' XOR EAX,EBX');   procedure Asembler;
       karakter)) then                                   end;                            begin
       Greska(POGRMNOZ);                               end;                                repeat
     t := cijeli;                                 end;                                        ReadLn(ulaz, linija);
     case z of                                    t1 := t;                                    if linija <> '\' then
       '*': begin                              end;                                             Emit(linija);
            Emit(' POP EBX');                end;                                             if eof(ulaz) then
            if t1 = karakter then                                                               linija := '\';
               Emit(' AND EBX,0FFh');        procedure IzrazDodjeljivanja                  until linija[1] = '\';
            if t2 = karakter then              (var t: TTip; var dod: Boolean);            pozicija := 1;
               Emit(' AND EAX,0FFh');        var                                           znak := linija[pozicija];
            Emit(' IMUL EBX');                 z: char;                                    IdiDo('\');
          end;                                 t1, t2: TTip;                             end;
       '/', '%': begin                         dod1: Boolean;
            Emit(' MOV EBX,EAX');            begin                                       procedure Petlja;
            Emit(' POP EAX');                  Izraz(t1, dod1);                          var
            Emit(' CDQ');                      t := t1;                                    sdok, skrajpetlje, suslov: string;
            if t1 = karakter then              dod := dod1;                              begin
               Emit(' AND EAX,0FFh');          case znak of                                Novi;
            if t2 = karakter then                 ':': begin                               NovaLabela(suslov);
               Emit(' AND EBX,0FFh');                 if not (Slijedi(':=', true))         Emit('L' + suslov + ':');
            Emit(' IDIV EBX');                           then                              IzrazDodjeljivanja(t, dod);
            if z = '%' then                              Greska(OCEKDOD);                  if t <> cijeli then
               Emit(' MOV EAX,EDX');                  if not (dod1) then                      Greska(TUSLPET);
          end;                                           Greska(NEDODJ);                   Emit(' CMP EAX,0');
     end;                                             Emit(' PUSH EBX');                   NovaLabela(sdok);
     t1 := t;                                         Novi;                                NovaLabela(skrajpetlje);
  end;                                                IzrazDodjeljivanja(t2, dod);         Emit(' JNE L' + sdok);
end;                                                  Emit(' POP EBX');                    Emit(' JMP L' + skrajpetlje);
                                                      if (t2 = karakter) and (t1 <>        IdiDo('{');
procedure Izraz(var t: TTip; var dod:                    karakter) and                     Emit('L' + sdok + ':');
  Boolean);                                              (t1 <> cijeli) then               Blok;
var                                                      Greska(DODJPOINT);                Emit(' JMP L' + suslov);
  z: char;                                            if t1 = karakter then                Emit('L' + skrajpetlje + ':');
  t1, t2: TTip;                                          Emit(' MOV [EBX],AL')           end;
begin                                                 else
  Clan(t1, dod);                                         Emit(' MOV [EBX],EAX');         procedure Blok;
  t := t1;                                            t := t1;                           begin
  while (znak in ['+', '-', '&', '|',               end; {:}                               while znak <> '}' do begin
    '^']) do begin                                '=', '>', '<', '#': begin                   if Slijedi('dok', false) then
    Emit(' PUSH EAX');                                Emit(' PUSH EAX');                        Petlja
    z := znak;                                        z := znak;                              else if Slijedi('ako', false) then
    Novi;                                             Novi;                                     Uslov
    Clan(t2, dod);                                    Izraz(t2, dod);                         else if Slijedi('asembler', false)
    dod := false;                                     Emit(' POP EBX');                         then
    if ((t1 <> cijeli) and (t1 <>                     if (t1 = karakter) and (t2 =              Asembler
      karakter)) or                                      karakter) then                       else begin
      ((t2 <> cijeli) and (t2 <>                         Emit(' CMP BL,AL')                     IzrazDodjeljivanja(t, dod);
      karakter)) then                                 else begin                                IdiDo(';');
      Greska(NEDOPARIT);                                 if t1 = karakter then                end;
    case z of                                              Emit(' AND EAX,0FFh');          end;
      '+': begin                                         if t2 = karakter then             IdiDo('}');
           Emit(' POP EBX');                               Emit(' AND EBX,0FFh');        end;
           if (t1 = karakter) and (t2 =                  Emit(' CMP EBX,EAX');
             karakter) then begin                     end;                               procedure DefFunkcija(ftip: TTip);
             t := karakter;                           case z of                          var
             Emit(' ADD AL,BL');                         '=': Emit(' SETE AL');            parametara, paradresa, lokadresa,
           end                                           '>': Emit(' SETG AL');              pfunkc, i: integer;
           else begin                                    '<': Emit(' SETL AL');            ImeFunkcije, imeparametra,
             t := cijeli;                                '#': Emit(' SETNE AL');             imevarijable, st: string;
             if t1 = karakter then                    end;                                 tip: TTip;
                Emit(' AND EBX,0FFh');                Emit(' AND EAX,0FFh');               imaistogtipa: Boolean;
             if t2 = karakter then                    t := cijeli;                       begin
                Emit(' AND EAX,0FFh');              end;                                   if not (((znak >= 'a') and (znak <=
             Emit(' ADD EAX,EBX');             end;                                          'z')) or
           end;                              end;                                            ((znak >= 'A') and (znak <= 'Z')))
        end;                                                                                   then
      '-': begin                             procedure Uslov;                                Greska(IMEFUN);
           Emit(' MOV EBX,EAX');             var                                           DeklIdent(ImeFunkcije, 0);
                                                             50
NoviIdent(ImeFunkcije, 4, 0, 0,                    end;                                        0, 0, 0);
  funkcija, ftip, 0, 0, 0);                        Str(paradresa, st);                       globadresa := globadresa +
pfunkc := ukupnoident;                             Emit(ImeFunkcije + '@' + st +               DuzinaTipa(tip);
aktnivo := pfunkc;                                    ':');                                  imaistogtipa := true;
IdiDo('(');                                        Emit(' PUSH EBP');                        if znak = ',' then begin
parametara := 0;                                   Emit(' MOV EBP,ESP');                       Novi;
lokadresa := 0;                                    Str(lokadresa, st);                         imaistogtipa := false;
paradresa := 0;                                    Emit(' SUB ESP,' + st);                   end;
while znak <> ')' do begin                         Blok;                                   until imaistogtipa;
  if SlijediDekTipa(tip) then begin                Emit(' MOV ESP,EBP');                   while (globadresa mod 4) <> 0 do
     DeklIdent(ImeParametra, pfunkc);              Emit(' POP EBP');                         globadresa := globadresa + 1;
     parametara := parametara + 1;                 Str(paradresa, st);                     IdiDo(';');
     paradresa := paradresa +                      Emit(' RET ' + st);                   end
       ((DuzinaTipa(tip) - 1) div 4 +              Emit('PUBLIC ' + ImeFunkcije +     end;
       1) * 4;                                        '@' + st);                      IdiDo('{');
     NoviIdent(ImeParametra,                     end;                                 if znak <> '}' then begin
       DuzinaTipa(tip),                        ';': begin                                Emit('GLAVNI:');
       paradresa, pfunkc, parametar,               Str(paradresa, st);                   Blok;
       tip,                                        Emit('extrn ' + ImeFunkcije +         Emit(' PUSH 0');
       pfunkc, parametara, 0);                        '@' + st + ':near');               Emit(' CALL ExitProcess@4');
  end;                                             IdiDo(';');                           Emit('.DATA');
  if znak <> ')' then                            end                                     Str(globadresa, st);
     IdiDo(',');                            else                                         Emit('GLOBALV DB ' + st +
end;                                           Greska(DEFFUN);                             ' DUP(0)');
IdiDo(')');                                 end;                                         Emit('END ULAZ')
for i := ukupnoident downto 0 do            aktnivo := 0;                             end
  if (TabIdent[i].nivo = pfunkc) and      end;                                        else begin
     (TabIdent[i].vrsta = parametar)                                                     Emit('GLAVNI:');
       then                               procedure Prevedi;                             Emit('END');
     TabIdent[i].adresa := paradresa +    var                                         end;
       8 - TabIdent[i].adresa;              globadresa: Integer;                    end;
TabIdent[pfunkc].pod1 := parametara;        ImeVarijable, st: string;
case znak of                                tip: TTip;                              procedure Glavni;
  '{': begin                                imaistogtipa: Boolean;                  var
       IdiDo('{');                        begin                                       linija: string;
       while SlijediDekTipa(tip) do         Emit('.386');                           begin
         begin                              Emit('.MODEL FLAT,STDCALL');              trenlabela := 0;
         repeat                             Emit('OPTION CASEMAP:NONE');              ukupnoident := 0;
            DeklIdent(ImeVarijable,         Emit('EXTRN ExitProcess@4:NEAR');         aktnivo := 0;
               pfunkc);                     Emit('.CODE');                            Assign(ulaz, paramstr(1));
            lokadresa := lokadresa +        Emit('ULAZ:');                            Assign(izlaz, paramstr(2));
               DuzinaTipa(tip);             Emit(' JMP GLAVNI');                      brojaclinija := 0;
            NoviIdent(ImeVarijable,         pozicija := 0;                            linija := '';
               DuzinaTipa(tip),             globadresa := 0;                          Reset(ulaz);
               -lokadresa, pfunkc,          Novi;                                     Rewrite(izlaz);
               lokalna, tip,                while SlijediDekTipa(tip) do begin        Prevedi;
               pfunkc, parametara, 0);        if Slijedi('funkcija', false) then      Close(ulaz);
            imaistogtipa := true;               begin                                 Close(izlaz);
            if znak = ',' then begin            Novi;                                 WriteLn('Prevedeno bez greske');
               Novi;                            DefFunkcija(tip);                   end;
               imaistogtipa := false;         end
            end;                              else begin                            begin
         until imaistogtipa;                    repeat                                Glavni
         while (lokadresa mod 4) <> 0             DeklIdent(ImeVarijable, 0);       end.
            do                                    NoviIdent(ImeVarijable,
            lokadresa := lokadresa + 1;             DuzinaTipa(tip),
         IdiDo(';');                                globadresa, 0, globalna, tip,
                                                                51
9. REALNI BROJEVI
         Na listi prioriteta koje treba implementirati slijede realni (floating point) brojevi. Iako se mnogi problemi koji
zahtijevaju upotrebu ovih brojeva mogu riješiti i cjelobrojnom aritmetikom uz potrebno skaliranje (fixed point), preostaju
problemi kod kojih je aritmetika u pokretnom zarezu nezamjenjiva .


9.1.      Koprocesor
         Izbor procesora 486 i Pentium za ciljnu arhitekturu navodi da se aritmetika u pokretnom zarezu realizuje koristeći
instrukcije koprocesora koji je u njih ugraĊen, umjesto pisanja posebnih potprograma. Ĉak i za procesore 386 i 486SX (kojima
koprocesor nedostaje), Windows 95 obezbjeĊuje softverske emulatore koprocesora.
         Instrukcije za rad u pokretnom zarezu su drugaĉije koncipirane od instrukcija za cjelobrojnu aritmetiku. One ne
operišu sa uobiĉajenim registrima, nego imaju interni stek na koji moţe da stane osam konstanti, velikih 32, 64 ili 80 bita.
        Kao optimalna veliĉina FP brojeva uzeće se 64 bita, tj. dvostruka preciznost. Brojevi u memoriji su predstavljeni po
IEEE-754 standardu. Po ovom standardu, bitovi 0-51 predstavljaju mantisu, bitovi 52-62 predstavljaju eksponent, a bit 63
predznak broja.


9.2.      Realne konstante
        Prije svega je potrebno proširiti sintaksu numeriĉke konstante. Gotovo svi programski jezici poznaju realne brojeve u
formi “2.4E-8” , što predstavlja 2,4·108 u klasiĉnom obliku. Pri tome se mogu izostaviti predznak eksponenta, ĉitav
eksponentski dio ili necijeli dio frakcije. Stoga nova sintaksa za numeriĉke konstante izgleda kao na slici Sl. 9.2.1
         Numerička konstanta


                                                                               +
                  Cifra                        Cifra                                        Cifra
                                    .                                   E
                                                                               -

                                               Sl. 9.2.1.         Numerička konstanta


         Konvertovanje brojeva iz uobiĉajenog dekadnog formata tipa “2.4E-8” u format “binarna mantisa i eksponent” je
sloţen, neportabilan, posao koji je podloţan numeriĉkim greškama. Na sreću, većina 32-bitnih asemblera već poznaje ovaj
format konstanti, pa je dovoljno proslijediti izvorno napisan broj asembleru, koji će pravilno upisati u memoriju konstante
oblika
            KONST DQ 2.4E-8

         Stoga je nova verzija procedure UzmiKonstantu razmjerno jednostavna. Ova procedura pored raĉuna cjelobrojne
konstante, sve njene znakove pridodaje na jedan string, koji je u globalnoj varijabli realnakonstanta. Ako se pri dohvaćanju
znakova naiĊe na znak „.‟ ili „E‟, prestaje se s raĉunom cjelobrojne konstante, ali se nastavlja pridodavanje znakova na
spomenutu globalnu string varijablu, uz stalnu provjeru sintakse.
          U okviru procedure Faktor, prilikom obrade numeriĉkih konstanti se provjeri da li je procedura UzmiKonstantu
vratila cjelobrojnu ili realnu vrijednost. U sluĉaju cjelobrojne vrijednosti generiše se uobiĉajena MOV EAX,nn instrukcija.
Ako je u pitanju realna konstanta, tada se vrijednost te konstante ne treba staviti u EAX registar nego na vrh FP steka. Da bi se
to postiglo treba generisati sljedeći kôd
             .DATA
             L12 DQ 2.4E-8
             .CODE
              FLD L12
         pri ĉemu su oznaka labele i konstanta dati radi ilustracije.


9.3.      Komunikacija izmeĎu FP steka i memorije
         FP stek je ograniĉen na svega osam konstanti, za razliku od steka adresiranog ESP registrom za koji je operativni
sistem rezervisao nekoliko desetina kilobajta. To onemogućava rekurzivno raĉunanje nekih funkcija, pa je potrebno omogućiti
                                                         52
privremeno ĉuvanje meĊurezultata FP operacija i na steku adresiranom ESP registrom. U tu svrhu, kao i radi konverzije
izmeĊu formata, se uvode sljedeće procedure:
        CijeliNaFPStek (sadrţaj cjelobrojnog registra se prebacuje na vrh FP steka) generiše sljedeći kôd
              Ako se posmatra samo nižih osam bita cijelog broja
                 generiši AND registar,0FFh
              MOV INTTOFP,registar
              FILD DWORD PTR INTTOFP

         FPStekUCijeli (broj s vrha FP steka se prebacuje u cjelobrojni registar. Kao privremena lokacija u memoriji koristi
se vrh ESP adresiranog steka) generiše sljedeći kôd
               ADD ESP,-4
               FISTP DWORD PTR [ESP]
               POP registar

        CPUStekCijeliNaFPStek (cijeli broj sa vrha ESP adresiranog steka prebacuje se na vrh FP steka) generiše sljedeći
kôd
            Ako se posmatra samo nižih osam bita cijelog broja
                generiši AND DWORD PTR [ESP],0FFh
            FILD DWORD PTR [ESP]
            ADD ESP,4

          FPUStekNaStek (broj u pokretnom zarezu se prebacuje sa vrha FP steka na vrh ESP adresiranog steka) generiše
sljedeći kôd
             ADD ESP,-8
             FSTP QWORD PTR [ESP]

          StekNaFPUStek (broj u pokretnom zarezu se prebacuje sa vrha ESP adresiranog steka na vrh FP steka) generiše
sljedeći kôd
            FLD QWORD PTR [ESP]
            ADD ESP,8


         Gore navedene funkcije potrebne su i zato što ne postoje instrukcije za direktno prebacivanje podataka iz FP internog
steka u cjelobrojne registre.


9.4.     Aritmetičke operacije
         Aritmetiĉke operacije nad realnim brojevima za sluĉaj sabiranja, oduzimanja, mnoţenja i dijeljenja uvijek kao rezultat
imaju realan broj, bez obzira da li je drugi argument ovih operacija cijeli broj, realni broj ili karakter.
        Sabiranje u kome je bar jedan sabirak FP broj se moţe realizovati kodom sa slike Sl. 9.4.1.

             Pozovi Član
             Ako je prvi član cijeli broj ili karakter generiši PUSH EAX inače pozovi FPUStekNaStek
             Pozovi Član
             Ako nijedan član nije realan broj, generiši kôd kao i ranije, prema tablicama iz
  prethodnog poglavlja
             Ako je drugi član cijeli broj ili karakter a prvi član je bio realni broj pozovi
  CijeliNaFPStek za registar EAX
             Ako je prvi član cijeli broj ili karakter pozovi CPUStekCijeliNaFP, a ako je realni pozovi
  StekNaFPUStek
             Generiši FADD


                           Sl. 9.4.1.        Generisanje koda za sabiranje u pokretnom zarezu
                                                            53
         Potreba za privremenim ĉuvanjem podataka na procesorskom steku, radi omogućivanja rekurzije, dovodi do
redundantnog koda u još izraţenijem obliku nego kod cjelobrojne aritmetike. Za sada se zanemaruje taj problem, jer je u ovom
trenutku taĉnost i jednostavnost kompajlera u prvom planu.
         Realizacija oduzimanja, mnoţenja i dijeljenja se ne razlikuje mnogo od realizacije sabiranja. Kod ove tri operacije je
potrebno umjesto FADD respektivno generisati instrukcije FSUBR, FMUL i FDIVR, koje kao i FADD obavljaju operaciju nad
dva broja na vrhu FP steka, uklone ih sa FP steka i rezultat opet ostavljaju na vrh FP steka. Za mnoţenje i dijeljenje poziv
funkcije Član se zamjenjuje pozivom funkcije Faktor.
         U sluĉaju poreĊenja koristi se instrukcija FCOMPP, kao na slici Sl. 9.4.2. Instrukcija FCOMPP poredi brojeve na
vrhu steka, ali rezultat smješta u koprocesorske flegove. Da bi se ovi flegovi mogli testirati, instrukcijom FSTFW AX se oni
smještaju u AX registar, a zatim instrukcijom SAHF prebacuju u F registar.
        Instrukcija SETE se mijenja zavisno od relacijskog operatora u
                          '=': SETE AL
                          '>': SETA AL
                          '<': SETB AL
                          '#': SETNE AL
        Zanimljivo je da instrukcija FSTFW AX pakuje flegove               tako da izgleda kao da se FP operacije porede
nepredznaĉeno, iako je u pitanju predznaĉeno poreĊenje.

              Pozovi Izraz
              Ako je prvi član cijeli broj ili karakter generiši PUSH EAX inače pozovi FPUStekNaStek
              Pozovi Izraz
              Ako je prvi član cijeli broj ili karakter generiši POP EBX
              Ako nijedan član nije realan broj, generiši kod kao i ranije, prema tablicama iz
   prethodnog poglavlja
              Ako je drugi član cijeli broj ili karakter a prvi član je bio realni broj pozovi
   CijeliNaFPStek za registar EAX
              Ako je prvi član cijeli broj ili karakter a drugi član je bio realni broj pozovi
   CijeliNaFPStek za registar EBX
              Ako je prvi član realni pozovi StekNaFPUStek
              Generiši FCOMPP
              Generiši FSTSW AX
              Generiši SAHF
              Generiši SETE AL
              Generiši AND EAX,0FFh
                             Sl. 9.4.2.        Generisanje koda za poreĎenje dva realna broja

9.5.     Realne varijable
        UvoĊenje dva nova tipa, realni i realni * , zahtijeva redefiniciju pojma ImeTipa :
        Ime tipa:


                           cijeli                    *


                         realni                  *


                           karakter                  *

                                                      Sl. 9.5.1.         Ime tipa
        Ĉitanje sadrţaja realne varijable se obavlja koristeći sljedeće dvije instrukcije, od kojih je jedna već poznata
            LEA EBX,adresa
            FLD QWORD PTR [EBX]
                                                              54
         MeĊutim, kada je rijeĉ o dodjeli vrijednosti varijabli instrukcija FLD sa lijeve strane operatora dodjeljivanja je ne
samo nepotrebna, nego i štetna jer ostavlja na FP steku konstantu i tako ga prepunjava. Pošto se unaprijed ne zna da li slijedi
znak dodjeljivanja, ovo se mora neutralisati instrukcijom FSTP ST(0). Stoga se dodjela vrijednosti, kada figurišu i realne
varijable, obavlja kodom sa slike Sl. 9.5.2:

                   Pozovi Izraz
                   Prijavi grešku ako izraz nije dodjeljiv
                   Generiši PUSH EBX
                   Ako je prvi izraz realni broj generiši FSTP ST(0)
                   Pozovi IzrazDodjeljivanja
                   Generiši POP EBX
                   Ako je drugi izraz cijeli broj ili karakter a prvi član je bio realni broj pozovi
       CijeliNaFPStek za registar EAX
                   Ako je prvi izraz cijeli broj ili karakter a drugi član je bio realni broj pozovi FPStekUCijeli
       za registar EAX
                   Ako je prvi izraz karakter generiši MOV [EBX],AL
                                                             Sl. 9.5.2.
                   Ako je prvi izraz realni broj generiši FSTP QWORD PTR [EBX]
                                                             Sl. 9.5.3.
                                                             Sl. [EBX],EAX
                   Ako je prvi izraz cijeli broj generiši MOV 9.5.4.
                 Sl. 9.5.5.           Generisanje koda za dodjeljivanje vrijednosti realnim promjenjivim

9.6.      Funkcije realnog argumenta i unarni operatori
        Analognim pravilima konverzije tipova se proširuje i poziv funkcije. Svaki realni parametar na steku zauzima po 8
bajtova i umjesto prostog generisanja PUSH EAX instrukcije (sluĉaj ostalih tipova), ovdje se poziva procedura
FPUStekNaStek. Ako je na mjestu realnog parametra u pozivu proslijeĊena cjelobrojna ili karakter varijabla, prije poziva
procedure FPUStekNaStek treba pozvati CijeliNaFPStek sa parametrom EAX, što će konvertovati cijeli broj u realni.
Ukoliko se realna vrijednost prosljeĊuje cjelobrojnom parametru, treba pozvati FPStekUCijeli prije generisanja instrukcija
PUSH EAX.
         Samo tri unarna operatora operatora imaju smisla u radu s realnim brojevima. To su -, & i *. Unarni minus treba da
generiše instrukciju FCHS koja mijenja predznak broja na vrhu FP steka. Operator adrese pored promjene tipa, pored
uobiĉajene MOV EAX,EBX instrukcije treba da uništi broj na vrhu FP steka koristeći FSTP ST(0) instrukciju. Operator
vrijednosti na koju pointer pokazuje za tip realni * ,umjesto instrukcije MOV EAX,[EBX] , treba generisati instrukcije FSTP
ST(0) i FLD QWORD PTR [EBX].
         Za razliku od Fortran-a, Pascal-a i BASIC-a, transcendentne funkcije nisu sastavni dio ovog jezika. One se mogu
prosto dodati u naknadno napisanim bibliotekama.
          Minorna izmjena je potrebna u Entry stub dijelu generisanog koda. Mašina koja se podrazumijeva je 486, umjesto
386, te je potrebno inicijalizirati koprocesor instrukcijom FINIT, i dodati pomoćnu lokaciju INTTOFP DD 0.
         Sada je moguće napisati šestu verziju kompajlera, koja je data u prilogu 6.


9.7.      Testni primjer
         Primjer programa u šestoj verziji jezika je jedna od numeriĉkih metoda. Metodom                sekante (koja radi u
ekstrapolacionom i interpolacionom reţimu rada) se rješava jednaĉina

            x  2  0 . Kod ove metode naredna taĉka se dobija formulom
                                       xk  xk 1
          xk 1  xk  f ( xk )
                                  f ( xk )  f ( xk 1 )
         Funkcija ĉija se nula traţi navodi se unutar tijela funkcije f. Treba primijetiti da je funkcija sqrt napisana kao
asemblerski potprogram, jer je to sa ovim procesorom jednostavnije i brţe od vlastite implementacije Heronovog algoritma.
Funkcija Prikazidecimalnibroj prikazuje broj na 5 decimala, tako što već poznatom funkcijom Prikazibroj ispiše cijeli, a
zatim razlomljeni dio izraza. Kompajliranje ovog primjera se vrši na uobiĉajeni naĉin, s tim što mu je ime sekanta.jez.
                                                             55



cijeli funkcija GetStdHandle(cijeli brhan);
cijeli funkcija WriteConsoleA(cijeli rez,cijeli * upisano,
  cijeli upisati,karakter * bafer,cijeli han);                realni funkcija sqrt(realni x)
cijeli funkcija ReadConsoleA(cijeli rez,cijeli * upisano,     {
  cijeli upisati,karakter * bafer,cijeli han);                  asembler
                                                                FLD QWORD PTR [EBP+8]
cijeli * ime;                                                   FSQRT
                                                              \
cijeli funkcija Prikazistring (karakter * poruka){            }
  cijeli handle,priv,duz;
   handle:=GetStdHandle(-11);                                 cijeli funkcija Prikazidecimalnibroj(realni x)
   duz:=0;                                                    {
   dok (poruka[duz]#0) { duz:=duz+1;}                           cijeli c,nn,q;
   WriteConsoleA(0,&priv,duz,poruka,handle);                    realni o;
}                                                               c:=x;
                                                                o:=abs(x-c);
cijeli funkcija Novired () {                                    Prikazibroj(c);
  karakter * dvoznak;                                           Prikazistring(".");
  dvoznak:=" ";                                                 nn:=100000*o;
  dvoznak[0]:=13;                                               q:=10;
  dvoznak[1]:=10;                                               dok q<100000 {
  Prikazistring(dvoznak);                                         ako (nn<q) {Prikazistring("0");}
}                                                                 q:=q*10;
                                                                }
cijeli funkcija Prikazibroj (cijeli broj){                      Prikazibroj(nn);
  cijeli cifra,negativan,pokazivac,ostatak;                     Novired();
  karakter * bafer;                                           }
  bafer:="           "; ` Alociramo bafer
  cifra:=broj;                                                realni funkcija f(realni x)
` Negativne brojeve oznaci indikatorom                        {
  ako (cifra<0)                                                 sqrt(x)-2;
   {                                                          }
      negativan:=1;
      cifra:=-cifra;                                          cijeli funkcija Racun()
   }                                                          {
     inace                                                       realni x,predx,novix;
   {                                                             cijeli i,q;
     negativan:=0;                                               i:=0;
   }                                                             predx:=0;
                                                                 x:=1;
`maksimalno 9 cifara                                             dok ( (i<2000) & (abs(x-predx) >0.000001) )
  pokazivac:=9;                                                    {
  ako (cifra=0) {
    bafer[pokazivac]:='0';                                             novix:=x-(f(x)*(x-predx))/(f(x)-f(predx));
    pokazivac:=pokazivac-1;                                            predx:=x;
  }                                                                    x:=novix;
  dok (cifra>0)                                                        Prikazidecimalnibroj(x);
  {                                                                    i:=i+1;
     ostatak:=(cifra % 10); `ostatke dijeljenja u bafer            }
     bafer[pokazivac]:=ostatak+'0';                           }
     cifra:=cifra/10; ` stalno dijeli s 10
     pokazivac:=pokazivac-1;                                  {
  }                                                             Racun();
  ako (negativan=1)                                           }
  {                                                           ----------------------------
     bafer[pokazivac]:='-';                                   Rezultat
     pokazivac:=pokazivac-1;
  }                                                           2.00000
  bafer:=&(bafer[pokazivac+1]);
` Pomjeri pokazivac pocetka stringa
                                                              3.41421
  Prikazistring(bafer);                                       4.08918
}                                                             4.00341
                                                              4.00002
realni funkcija abs(realni x)                                 4.00000
{                                                             4.00000
   ako (x>0) { x;} inace {-x;}
}
                                          Sl. 9.7.1.         Primjer Metoda sekante


9.8.     Rezime poglavlja
         Zahvaljujući ugraĊenom matematiĉkom koprocesoru dodavanje realne aritmetike je razmjerno jednostavno. Realne
konstante se prosto prosljeĊuju asembleru jer svi moderni asembleri poznaju eksponencijalnu sintaksu. Koprocesor radi na
principu steka i potrebne su konverzione procedure izmeĊu koprocesorskog steka i cjelobrojnih registara.
                                                             56
Prilog 6: Verzija izvornog koda kompajlera br. 6
program Kompajler;                          trenlabela := trenlabela + 1;                  if (znak = 'e') or (znak = 'E') then
const                                       Str(trenlabela, ImeLabele);                      begin
  MAXIDENT = 1024;                        end;                                               realnakonstanta := realnakonstanta
  MAXDIM = 10;                                                                                  + znak;
  DUGAKONST =                             procedure Greska(poruka: string);                  NoviSvaki(false);
    'Konstanta prevazilazi liniju';       begin                                              if (znak = '+') or (znak = '-')
  REALKONST = 'Realna konstanta';           WriteLn(poruka);                                    then begin
  OCEKIVANO = 'Ocekivano ';                 WriteLn(brojaclinija, ':', linija);                 realnakonstanta :=
  REDEKLAR =                                Close(ulaz);                              realnakonstanta
    'Redeklarisan identifikator';           Close(izlaz);                                         + znak;
  PROSTNIZ =                                Halt;                                               NoviSvaki(false);
    'Prosti tip ne moze biti niz';        end;                                               end;
  NEKORARG =                                                                                 if (znak < '0') or (znak > '9')
    'Nekorektan broj argumenata';         procedure Emit(st: string);                           then
  NEKDODJP = 'Losa dodjela pointeru';     begin                                                 Greska(REALKONST);
  NEDEKL = 'Nedeklarisano ';                WriteLn(izlaz, st);                              while (znak >= '0') and (znak <=
  GRIZRAZ = 'Izraz';                      end;                                                  '9') do begin
  POGRMNOZ =                                                                                    realnakonstanta :=
    'Pogresan tip u ' +                   procedure Novi;                             realnakonstanta
    'mnozenju ili dijeljenju';            begin                                                   + znak;
  NEDOPFP =                                 repeat                                              NoviSvaki(false);
    ' Nedopustena FP operacija';               pozicija := pozicija + 1;                     end;
  NEDOPARIT =                                  if pozicija > Length(linija) then           end;
    'Nedopusteni tip u aritmetici';              begin                                     UzmiKonstantu := 0;
  OCEKDOD = 'Ocekivano dodjeljivanje';           brojaclinija := brojaclinija + 1;         t := realni;
  NEDODJ =                                       if not (Eof(ulaz)) then                end
    'Izraz se ne moze dodijeliti';                  ReadLn(ulaz, linija);               else begin
  DODJPOINT = 'Losa dodjela pointeru';           Emit(';' + linija);                       UzmiKonstantu := rezultat;
  TIPUSL = 'Neodgovarajuci tip uslova';          pozicija := 1;                            t := cijeli;
  TUSLPET =                                    end;                                     end;
    'Neodgovarajuci uslov u petlji';           if Length(linija) > 0 then               if (znak = ' ') or (znak = '`') then
  IMEFUN = 'Ocekivano ime funkcije';             znak := linija[pozicija]                  Novi;
  DEFFUN = 'Definicija funkcije';              else                                     dod := false;
  ARGNEKOM =                                     znak := ' ';                         end;
    'Argument nekompatibilan' +                if (znak = '`') then
    ' s operatorom';                             pozicija := Length(linija);          function Slijedi(ocekivano: string;
  OCIDENT =                                 until ((znak > ' ') and (znak <>            dslovoiza: Boolean): Boolean;
    'Ocekivan Identifikator';                  '`')) or Eof(ulaz)                     var
                                          end;                                          ureduiza: Boolean;
type                                                                                    n: integer;
  TVrsta = (funkcija, lokalna,            procedure NoviSvaki(greskakrln:               znak: char;
     globalna, parametar);                  Boolean);                                 begin
  TTip = (karakter, cijeli, realni,       begin                                         if dslovoiza then
     pkarakter, pcijeli, prealni);          pozicija := pozicija + 1;                      ureduiza := true
  TIdent = record                           if pozicija > Length(linija) then           else begin
     ime: string[20];                          begin                                       n := pozicija + Length(ocekivano);
     duzina: integer;                          if greskakrln then                          ureduiza := true;
     adresa: integer;                            Greska(DUGAKONST)                         if Length(linija) >= n then begin
     nivo: integer;                            else                                          znak := linija[n];
     vrsta: TVrsta;                              znak := ' ';                                if ((znak >= 'a') and (znak <=
     tip: TTip;                             end                                                'z')) or
     pod1: integer;                         else                                               ((znak >= 'A') and (znak <=
     pod2: integer;                            znak := linija[pozicija];                         'Z')) then
     pod3: integer;                       end;                                                 ureduiza := false
  end;                                                                                     end
                                          procedure IdiDo(z: char);                     end;
var                                       begin                                         if ureduiza and (copy(linija,
  ulaz, izlaz: text;                        if (znak <> z) then                            pozicija,
  pozicija, trenlabela, brojaclinija,          Greska(OCEKIVANO + z);                      Length(ocekivano)) = ocekivano) then
    aktnivo: integer;                       Novi;                                            begin
  znak: char;                             end;                                             Slijedi := true;
  linija, realnakonstanta: string;                                                         pozicija := pozicija +
  TabIdent: array[0..MAXIDENT] of         function UzmiKonstantu                             Length(ocekivano) - 1;
    TIdent;                                 (var t: TTip; var dod: Boolean):            end
  ukupnoident: integer;                       integer;                                  else
  t: TTip;                                var                                              Slijedi := false;
  dod: Boolean;                             rezultat: integer;                        end;
                                          begin
procedure NoviIdent(pime: string;           rezultat := 0;                            function TipDek(imetipa: string; var
  pduzina: integer;                         realnakonstanta := '';                      tip: TTip;
  padresa: integer; pnivo: integer;         while (znak >= '0') and (znak <= '9')       stip, ptip: TTip): Boolean;
     pvrsta: TVrsta;                          do begin                                begin
  ptip: TTip; ppod1: integer; ppod2:          rezultat := 10 * rezultat +               TipDek := false;
     integer; ppod3: integer);                   ord(znak) - ord('0');                  if Slijedi(imetipa, false) then begin
begin                                         realnakonstanta := realnakonstanta           TipDek := true;
  ukupnoident := ukupnoident + 1;                + znak;                                   Novi;
  with TabIdent[ukupnoident] do begin         NoviSvaki(false);                            if znak = '*' then begin
     ime := pime;                           end;                                             tip := ptip;
     duzina := pduzina;                     if (znak = '.') or (znak = 'e') or               Novi
     adresa := padresa;                       (znak = 'E') then begin                      end
     nivo := pnivo;                           if znak = '.' then begin                     else
     vrsta := pvrsta;                            realnakonstanta := realnakonstanta          tip := stip;
     tip := ptip;                                  + znak;                              end
     pod1 := ppod1;                              NoviSvaki(false);                    end;
     pod2 := ppod2;                              while (znak >= '0') and (znak <=
     pod3 := ppod3;                                '9') do begin                      function SlijediDekTipa(var tip: TTip):
  end;                                             realnakonstanta :=                   Boolean;
end;                                      realnakonstanta                             var
                                                      + znak;                           a: Boolean;
procedure NovaLabela(var ImeLabele:                NoviSvaki(false);                  begin
  string);                                       end;                                   a := false;
begin                                         end;                                      if not (a) then
                                                               57
     a := TipDek('cijeli', tip, cijeli,       (var t: TTip; var dod: Boolean);        begin
       pcijeli);                                forward;                                Emit(' ADD ESP,-8');
  if not (a) then                           procedure Blok; forward;                    Emit(' FSTP QWORD PTR [ESP]');
     a := TipDek('karakter', tip,                                                     end;
       karakter, pkarakter);                procedure PokazivacINiz(var t: TTip; var
  if not (a) then                             dod: Boolean);                         procedure StekNaFPUStek;
     a := TipDek('realni', tip, realni,     var                                      begin
       prealni);                              t1: TTip;                                Emit(' FLD QWORD PTR [ESP]');
  SlijediDekTipa := a;                      begin                                      Emit(' ADD ESP,8');
end;                                          Novi;                                  end;
                                              Emit(' PUSH EAX');
function DuzinaTipa(tip: TTip):               IzrazDodjeljivanja(t1, dod);           procedure PozivFunkcije
  Integer;                                    Emit(' POP EBX');                        (idpoz: integer; var t: TTip; var
begin                                         case t of                                   dod: Boolean);
  case tip of                                    pkarakter: begin                    var
     cijeli, pcijeli, pkarakter,                     t := karakter;                    parametara, N, velsteka: integer;
       prealni: DuzinaTipa := 4;                   end;                                t1, t2: TTip;
     karakter: DuzinaTipa := 1;                  pcijeli: begin                        ImeFunkcije, st: string;
     realni: DuzinaTipa := 8;                        Emit(' SAL EAX,2');             begin
  else                                               t := cijeli;                      ImeFunkcije := TabIdent[idpoz].ime;
     DuzinaTipa := 4;                              end;                                parametara := 0;
  end;                                           prealni: begin                        velsteka := 0;
end;                                                 Emit(' FSTP ST(0)');              IdiDo('(');
                                                     Emit(' SAL EAX,3');               while (znak <> ')') do begin
function NadjiIdent(ident: string;                   t := realni;                         IzrazDodjeljivanja(t1, dod);
  nivo, tuslova, p1: integer): integer;            end;                                   parametara := parametara + 1;
var                                           else                                        n := NadjiIdent('', idpoz, 4,
  n, poz: integer;                               Greska(PROSTNIZ)                           parametara);
  nadjen, Uslov: Boolean;                     end;                                        if n = 0 then
begin                                         Emit(' ADD EBX,EAX');                         Greska(NEKORARG);
  n := ukupnoident;                           case t of                                   t2 := TabIdent[n].tip;
  nadjen := false;                               karakter:                                if (t1 in [karakter, realni]) and
  poz := 0;                                        Emit(' MOV AL,[EBX]');                   (t2 in [pkarakter, pcijeli,
  while (n > 0) and (not (nadjen)) do            realni:                                       prealni]) then
     begin                                         Emit(' FLD QWORD PTR [EBX]')             Greska(NEKDODJP);
     case tuslova of                          else                                        if (t1 = karakter) and (t2 = cijeli)
       1: Uslov := (TabIdent[n].ime =            Emit(' MOV EAX,[EBX]');                    then
          ident) and                          end;                                          Emit(' AND EAX,0FFh');
          (TabIdent[n].vrsta in               IdiDo(']');                                 case t2 of
            [lokalna, globalna,               dod := true;                                  realni: begin
              parametar, funkcija]) and     end;                                                 velsteka := velsteka + 8;
            ((TabIdent[n].nivo = nivo) or                                                        case t1 of
              (TabIdent[n].nivo = 0));      procedure StringKonstanta(var t: TTip;                 realni: ;
       2: Uslov := (TabIdent[n].ime =         var dod: Boolean);                                   karakter:
          ident) and                        var                                                       CijeliNaFPStek('EAX',
          (TabIdent[n].vrsta in               st, strtekst: string;                                   true);
            [lokalna, globalna,             begin                                                else
              parametar, funkcija]) and       NovaLabela(strtekst);                                CijeliNaFPStek('EAX',
            ((TabIdent[n].nivo = nivo));      Emit('.DATA');                                          false);
       4: Uslov := (TabIdent[n].nivo =        st := 'L' + strtekst + ' DB ''';                   end;
          nivo) and                           repeat                                             FPUStekNaStek;
          (TabIdent[n].pod2 = p1) and            NoviSvaki(true);                              end
            (TabIdent[n].vrsta =                 if znak <> '"' then                      else begin
parametar)                                         st := st + znak;                            velsteka := velsteka + 4;
     else                                     until znak = '"';                                if t1 = realni then
       Uslov := false;                        IdiDo('"');                                        FPStekUCijeli('EAX');
     end;                                     st := st + ''',0';                               Emit(' PUSH EAX');
     if Uslov then begin                      if copy(st, length(st) - 3, 2) =              end;
       nadjen := true;                           '''''' then                              end;
       poz := n;                                 st := 'L' + strtekst + ' DB 0';          if znak <> ')' then
     end;                                     Emit(st);                                     IdiDo(',');
     n := n - 1;                              Emit('.CODE');                           end;
  end;                                        Emit(' MOV EAX,OFFSET L' + strtekst);    IdiDo(')');
  NadjiIdent := poz;                          t := pkarakter;                          if TabIdent[idpoz].pod1 <> parametara
end;                                          dod := false;                               then
                                            end;                                          Greska(NEKORARG);
procedure UzmiIdent(var ident: string);                                                Str(velsteka, st);
begin                                       procedure CijeliNaFPStek(reg: string;      Emit(' MOV ECX,' + st);
  if znak in ['a'..'z', 'A'..'Z'] then        osmobitni: Boolean);                     Emit(' CALL ' + ImeFunkcije + '@' +
     begin                                  begin                                         st);
     ident := znak;                           if osmobitni then                        dod := false;
     NoviSvaki(false);                           Emit(' AND ' + reg + ',0FFh');        t := TabIdent[idpoz].tip;
  end                                         Emit(' MOV INTTOFP,' + reg);             if t = karakter then
  else                                        Emit(' FILD DWORD PTR INTTOFP');            Emit(' AND EAX,0FFh0');
     Greska(OCIDENT);                       end;                                     end;
  while (znak in ['a'..'z', 'A'..'Z',
     '0'..'9', '_']) do begin               procedure FPStekUCijeli(reg: string);     procedure Varijabla
     ident := ident + znak;                 begin                                       (idpoz: integer; var t: TTip; var
     NoviSvaki(false);                        Emit(' ADD ESP,-4');                        dod: Boolean; glob: Boolean);
  end;                                        Emit(' FISTP DWORD PTR [ESP]');         var
  if (znak = ' ') or (znak = '`') then        Emit(' POP ' + reg);                      rezultat: integer;
     Novi;                                  end;                                        st: string;
end;                                                                                  begin
                                            procedure                                   rezultat := TabIdent[idpoz].adresa;
procedure DeklIdent(var ident: string;        CPUStekCijeliNaFPStek(osmobitni:          t := TabIdent[idpoz].tip;
  nivo: integer);                             Boolean);                                 Str(rezultat, st);
begin                                       begin                                       if glob then
  UzmiIdent(ident);                           if osmobitni then                           Emit(' LEA EBX,GLOBALV[' + st + ']')
  if NadjiIdent(ident, nivo, 2, 0) <> 0          Emit(' AND DWORD PTR [ESP],0FFh');     else begin
     then                                     Emit(' FILD DWORD PTR [ESP]');              if rezultat >= 0 then
     Greska(REDEKLAR);                        Emit(' ADD ESP,4');                            Emit(' LEA EBX,[EBP+' + st + ']')
end;                                        end;                                          else
                                                                                             Emit(' LEA EBX,[EBP' + st + ']');
procedure IzrazDodjeljivanja                procedure FPUStekNaStek;                    end;
                                                               58
  case t of                                       end;                                          else
     karakter: Emit(' MOV AL,[EBX]');           '"': begin                                         Greska(NEDOPFP);
     realni:                                        StringKonstanta(t, dod);                    end
       Emit(' FLD QWORD PTR [EBX]');              end;                                        end
     cijeli: Emit(' MOV EAX,[EBX]');            '''': begin                                   else begin
  else                                              NoviSvaki(true);                            t := cijeli;
     Emit(' MOV EAX,[EBX]');                        Emit(' MOV AL,''' + znak +                  case z of
  end;                                                 '''');                                      '*': begin
  dod := true;                                      Novi;                                              Emit(' POP EBX');
  if znak = '[' then                                IdiDo('''');                                       if t1 = karakter then
     PokazivacINiz(t, dod);                         t := karakter;                                        Emit(' AND EBX,0FFh');
end;                                              end;                                                 if t2 = karakter then
                                                '0'..'9': begin                                           Emit(' AND EAX,0FFh');
procedure Faktor(var t: TTip; var dod:              rezultat := UzmiKonstantu(t,                       Emit(' IMUL EBX');
  Boolean);                                            dod);                                         end;
var                                                 case t of                                      '/', '%': begin
  rezultat, poz: integer;                              cijeli: begin                                   Emit(' MOV EBX,EAX');
  st, fpkonst, ime, err: string;                           Str(rezultat, st);                          Emit(' POP EAX');
begin                                                      Emit(' MOV EAX,' + st);                     Emit(' CDQ');
  err := ARGNEKOM;                                       end;                                          if t1 = karakter then
  case znak of                                         realni: begin                                      Emit(' AND EAX,0FFh');
    '-': begin                                             NovaLabela(fpkonst);                        if t2 = karakter then
        Novi;                                              Emit('.DATA');                                 Emit(' AND EBX,0FFh');
        Faktor(t, dod);                                    st := 'L' + fpkonst +                       Emit(' IDIV EBX');
        case t of                                             ' DQ '+ realnakonstanta;                 if z = '%' then
           cijeli: Emit(' NEG EAX');                       Emit(st);                                      Emit(' MOV EAX,EDX');
           realni: Emit(' FCHS');                          Emit('.CODE');                            end;
        else                                               Emit(' FLD L' + fpkonst);            end;
           Greska(err);                                  end;                                 end;
        end;                                        end;                                      t1 := t;
        dod := false;                             end;                                     end;
      end;                                      '(': begin                               end;
    '~': begin                                      Novi;
        Novi;                                       IzrazDodjeljivanja(t, dod);          procedure Izraz(var t: TTip; var dod:
        Faktor(t, dod);                             IdiDo(')');                            Boolean);
        case t of                                 end;                                   var
           cijeli: Emit(' NOT EAX');            'A'..'Z', 'a'..'z': begin                  z: char;
           karakter: Emit(' NOT AL');               UzmiIdent(ime);                        t1, t2: TTip;
        else                                        poz := NadjiIdent(ime, aktnivo,      begin
           Greska(err);                                1, 0);                              Clan(t1, dod);
        end;                                        if poz = 0 then                        t := t1;
        dod := false;                                  Greska(NEDEKL + ime);               while (znak in ['+', '-', '&', '|',
      end;                                          case TabIdent[poz].vrsta of              '^']) do begin
    '&': begin                                         funkcija:                             if t1 <> realni then
        Novi;                                            PozivFunkcije(poz, t, dod);           Emit(' PUSH EAX')
        Faktor(t, dod);                                lokalna, parametar:                   else
        Emit(' MOV EAX,EBX');                            Varijabla(poz, t, dod,                FPUStekNaStek;
        case t of                                          false);                           z := znak;
           cijeli: t := pcijeli;                       globalna:                             Novi;
           karakter: t := pkarakter;                     Varijabla(poz, t, dod, true)        Clan(t2, dod);
           realni: begin                            end                                      dod := false;
               t := prealni;                      end;                                       if (not (t1 in [cijeli, karakter,
               Emit(' FSTP ST(0)');          else                                              realni])) or
             end;                               Greska(GRIZRAZ);                               (not (t2 in [cijeli, karakter,
        else                                 end;                                                 realni])) then
           t := pcijeli;                   end;                                                Greska(NEDOPARIT);
        end;                                                                                 if (t1 = realni) or (t2 = realni)
        dod := false;                      procedure Clan(var t: TTip; var dod:                then begin
      end;                                   Boolean);                                         t := realni;
    '*': begin                             var                                                 if t2 <> realni then
        Novi;                                z: char;                                             CijeliNaFPStek('EAX', t2 =
        Faktor(t, dod);                      t1, t2: TTip;                                          karakter);
        Emit(' MOV EBX,EAX');              begin                                               if t1 <> realni then
        if t = prealni then begin            Faktor(t1, dod);                                     CPUStekCijeliNaFPStek(t1 =
           Emit(' FSTP ST(0)');              t := t1;                                               karakter)
           Emit(' FLD QWORD PTR [EBX]');     while (znak in ['*', '/', '%']) do                else
        end                                    begin                                              StekNaFPUStek;
        else                                   z := znak;                                      case z of
           Emit(' MOV EAX,[EBX]');             if t1 <> realni then                               '+': Emit(' FADD ');
        case t of                                Emit(' PUSH EAX')                                '-': Emit(' FSUBR ');
           pcijeli: t := cijeli;               else                                            else
           pkarakter: begin                      FPUStekNaStek;                                   Greska(NEDOPFP);
               t := karakter;                  Novi;                                           end
               Emit(' AND EAX,0FFh');          Faktor(t2, dod);                              end
             end;                              dod := false;                                 else begin
           prealni: t := realni;               if (not (t1 in [cijeli, karakter,               case z of
        else                                     realni])) or                                     '+': begin
           Greska(err);                          (not (t2 in [cijeli, karakter,                       Emit(' POP EBX');
        end;                                        realni])) then                                    if (t1 = karakter) and (t2
        dod := true;                             Greska(POGRMNOZ);                                       = karakter) then begin
      end;                                     if (t1 = realni) or (t2 = realni)                         t := karakter;
    '!': begin                                   then begin                                              Emit(' ADD AL,BL');
        Novi;                                    t := realni;                                         end
        Faktor(t, dod);                          if t2 <> realni then                                 else begin
        case t of                                   CijeliNaFPStek('EAX', t2 =                           t := cijeli;
           cijeli: Emit(' CMP EAX,0');                karakter);                                         if t1 = karakter then
           karakter: Emit(' CMP AL,0');          if t1 <> realni then                                      Emit(' AND EBX,0FFh');
        else                                        CPUStekCijeliNaFPStek(t1 =                           if t2 = karakter then
           Greska(err);                               karakter)                                            Emit(' AND EAX,0FFh');
        end;                                     else                                                    Emit(' ADD EAX,EBX');
        Emit(' SETE AL');                           StekNaFPUStek;                                    end;
        Emit(' AND EAX,0FFh');                   case z of                                          end;
        dod := false;                               '*': Emit(' FMUL ');                          '-': begin
        t := cijeli;                                '/': Emit(' FDIVR ');                             Emit(' MOV EBX,EAX');
                                                                  59
              Emit(' POP EAX');                             CijeliNaFPStek('EAX', t2 =     if t <> cijeli then
              if (t1 = karakter) and (t2                      karakter);                      Greska(TUSLPET);
                 = karakter) then begin                                                    Emit(' CMP EAX,0');
                 t := karakter;                           if t1 <> realni then             NovaLabela(sdok);
                 Emit(' SUB AL,BL');                        CijeliNaFPStek('EBX', t1 =     NovaLabela(skrajpetlje);
              end                                              karakter)                   Emit(' JNE L' + sdok);
              else begin                                  else                             Emit(' JMP L' + skrajpetlje);
                 t := cijeli;                               StekNaFPUStek;                 IdiDo('{');
                 if t1 = karakter then                    Emit(' FCOMPP ');                Emit('L' + sdok + ':');
                   Emit(' AND EAX,0FFh');                 Emit(' FSTSW AX');               Blok;
                 if t2 = karakter then                    Emit(' SAHF');                   Emit(' JMP L' + suslov);
                   Emit(' AND EBX,0FFh');                 case z of                        Emit('L' + skrajpetlje + ':');
                 Emit(' SUB EAX,EBX');                      '=': Emit(' SETE AL');       end;
              end;                                          '>': Emit(' SETA AL');
            end;                                            '<': Emit(' SETB AL');       procedure Blok;
          '&', '|', '^': begin                              '#': Emit(' SETNE AL');      begin
              if (t1 = karakter) and (t2                  end;                             while znak <> '}' do begin
                 = karakter) then                         Emit(' AND EAX,0FFh');              if Slijedi('dok', false) then
                 t := karakter                                                                  Petlja
              else                                        t := cijeli;                        else if Slijedi('ako', false) then
                 t := cijeli;                           end                                     Uslov
              Emit(' POP EBX');                         else begin                            else if Slijedi('asembler', false)
              case z of                                   if (t1 = karakter) and (t2 =          then
                 '&':                                        karakter) then                     Asembler
                   Emit(' AND EAX,EBX');                     Emit(' CMP BL,AL')               else begin
                 '|': Emit(' OR EAX,EBX');                else begin                            IzrazDodjeljivanja(t, dod);
                 '^':                                        if t1 = karakter then              IdiDo(';');
                   Emit(' XOR EAX,EBX');                       Emit(' AND EAX,0FFh');         end;
              end;                                           if t2 = karakter then         end;
            end;                                               Emit(' AND EBX,0FFh');      IdiDo('}');
       end;                                                  Emit(' CMP EBX,EAX');       end;
     end;                                                 end;
     t1 := t;                                             case z of                      procedure DefFunkcija(ftip: TTip);
  end;                                                       '=': Emit(' SETE AL');      var
end;                                                         '>': Emit(' SETG AL');        parametara, paradresa, lokadresa,
                                                             '<': Emit(' SETL AL');          pfunkc, i: integer;
procedure IzrazDodjeljivanja                                 '#': Emit(' SETNE AL');       ImeFunkcije, imeparametra,
  (var t: TTip; var dod: Boolean);                        end;                               imevarijable, st: string;
var                                                       Emit(' AND EAX,0FFh');           tip: TTip;
  z: char;                                                t := cijeli;                     imaistogtipa: Boolean;
  t1, t2: TTip;                                         end;                             begin
  dod1: Boolean;                                      end                                  if not (((znak >= 'a') and (znak <=
begin                                          end;                                          'z')) or
  Izraz(t1, dod1);                           end;                                            ((znak >= 'A') and (znak <= 'Z')))
  t := t1;                                                                                      then
  dod := dod1;                               procedure Uslov;                                Greska(IMEFUN);
  case znak of                               var                                           DeklIdent(ImeFunkcije, 0);
    ':': begin                                 sonda, sinace, skrajuslova: string;         NoviIdent(ImeFunkcije, 4, 0, 0,
        if not (Slijedi(':=', true))         begin                                           funkcija, ftip, 0, 0, 0);
           then                                Novi;                                       pfunkc := ukupnoident;
           Greska(OCEKDOD);                    IzrazDodjeljivanja(t, dod);                 aktnivo := pfunkc;
        if not (dod1) then                     if t <> cijeli then                         IdiDo('(');
           Greska(NEDODJ);                        Greska(TIPUSL);                          parametara := 0;
        Emit(' PUSH EBX');                     Emit(' CMP EAX,0');                         lokadresa := 0;
        if (t1 = realni) then                  NovaLabela(sonda);                          paradresa := 0;
           Emit(' FSTP ST(0)');                NovaLabela(sinace);                         while znak <> ')' do begin
        Novi;                                  NovaLabela(skrajuslova);                      if SlijediDekTipa(tip) then begin
        IzrazDodjeljivanja(t2, dod);           Emit(' JNE L' + sonda);                          DeklIdent(ImeParametra, pfunkc);
        Emit(' POP EBX');                      Emit(' JMP L' + sinace);                         parametara := parametara + 1;
        if (t2 in [karakter, realni])          IdiDo('{');                                      paradresa := paradresa +
           and                                 Emit('L' + sonda + ':');                           ((DuzinaTipa(tip) - 1) div 4 +
           (t1 in [pkarakter, pcijeli,         Blok;                                                 1) * 4;
             prealni]) then                    Emit(' JMP L' + skrajuslova);                    NoviIdent(ImeParametra,
           Greska(NEKDODJP);                   Emit('L' + sinace + ':');                          DuzinaTipa(tip),
        if (t1 = realni) and (t2 <>            if Slijedi('inace', false) then begin              paradresa, pfunkc, parametar,
           realni) then                           Novi;                                              tip,
           CijeliNaFPStek('EAX', t2 =             IdiDo('{');                                     pfunkc, parametara, 0);
             karakter);                           Blok;                                      end;
        if (t1 <> realni) and (t2 =            end;                                          if znak <> ')' then
           realni) then                        Emit('L' + skrajuslova + ':');                   IdiDo(',');
           FPStekUCijeli('EAX');             end;                                          end;
        case t1 of                                                                         IdiDo(')');
           karakter:                         procedure Asembler;                           for i := ukupnoident downto 0 do
             Emit(' MOV [EBX],AL');          begin                                           if (TabIdent[i].nivo = pfunkc) and
           realni:                             repeat                                           (TabIdent[i].vrsta = parametar)
           Emit(' FSTP QWORD PTR [EBX]');         ReadLn(ulaz, linija);                           then
        else                                      if linija <> '\' then                         TabIdent[i].adresa := paradresa +
           Emit(' MOV [EBX],EAX');                  Emit(linija);                                 8 - TabIdent[i].adresa;
        end;                                      if eof(ulaz) then                        TabIdent[pfunkc].pod1 := parametara;
        t := t1;                                    linija := '\';                         case znak of
      end; {:}                                 until linija[1] = '\';                        '{': begin
    '=', '>', '<', '#': begin                  pozicija := 1;                                     IdiDo('{');
        if t1 <> realni then                   znak := linija[pozicija];                          while SlijediDekTipa(tip) do
           Emit(' PUSH EAX')                   IdiDo('\');                                           begin
        else                                 end;                                                    repeat
           FPUStekNaStek;                                                                              DeklIdent(ImeVarijable,
        z := znak;                           procedure Petlja;                                            pfunkc);
        Novi;                                var                                                       lokadresa := lokadresa +
        Izraz(t2, dod);                        sdok, skrajpetlje, suslov: string;                         DuzinaTipa(tip);
        if t1 <> realni then                 begin                                                     NoviIdent(ImeVarijable,
           Emit(' POP EBX');                   Novi;                                                      DuzinaTipa(tip),
        if (t1 = realni) or (t2 =              NovaLabela(suslov);                                        -lokadresa, pfunkc,
           realni) then begin                  Emit('L' + suslov + ':');                                    lokalna, tip,
           if t2 <> realni then                IzrazDodjeljivanja(t, dod);                                pfunkc, parametara, 0);
                                                               60
              imaistogtipa := true;           ImeVarijable, st: string;                  IdiDo('{');
              if znak = ',' then begin        tip: TTip;                                 if znak <> '}' then begin
                 Novi;                        imaistogtipa: Boolean;                        Emit('GLAVNI:');
                 imaistogtipa := false;     begin                                           Blok;
              end;                            Emit('.486');                                 Emit(' PUSH 0');
            until imaistogtipa;               Emit('.MODEL FLAT,STDCALL');                  Emit(' CALL ExitProcess@4');
            while (lokadresa mod 4) <> 0      Emit('OPTION CASEMAP:NONE');                  Emit('.DATA');
              do                              Emit('EXTRN ExitProcess@4:NEAR');             Str(globadresa, st);
              lokadresa := lokadresa + 1;     Emit('.CODE');                                Emit('GLOBALV DB ' + st +
            IdiDo(';');                       Emit('ULAZ:');                                  ' DUP(0)');
         end;                                 Emit(' FINIT');                               Emit('INTTOFP DD 0');
         Str(paradresa, st);                  Emit(' JMP GLAVNI');                          Emit('END ULAZ')
         Emit(ImeFunkcije + '@' + st +        pozicija := 0;                             end
            ':');                             globadresa := 0;                           else begin
         Emit(' PUSH EBP');                   Novi;                                         Emit('GLAVNI:');
         Emit(' MOV EBP,ESP');                while SlijediDekTipa(tip) do begin            Emit('END');
         Str(lokadresa, st);                    if Slijedi('funkcija', false) then       end;
         Emit(' SUB ESP,' + st);                   begin                               end;
         Blok;                                     Novi;
         Emit(' MOV ESP,EBP');                     DefFunkcija(tip);                   procedure Glavni;
         Emit(' POP EBP');                      end                                    var
         Str(paradresa, st);                    else begin                               linija: string;
         Emit(' RET ' + st);                       repeat                              begin
         Emit('PUBLIC ' + ImeFunkcije +              DeklIdent(ImeVarijable, 0);         trenlabela := 0;
            '@' + st);                               NoviIdent(ImeVarijable,             ukupnoident := 0;
       end;                                            DuzinaTipa(tip),                  aktnivo := 0;
     ';': begin                                        globadresa, 0, globalna, tip,     Assign(ulaz, paramstr(1));
         Str(paradresa, st);                              0, 0, 0);                      Assign(izlaz, paramstr(2));
         Emit('extrn ' + ImeFunkcije +               globadresa := globadresa +          brojaclinija := 0;
            '@' + st + ':near');                       DuzinaTipa(tip);                  linija := '';
         IdiDo(';');                                 imaistogtipa := true;               Reset(ulaz);
       end                                           if znak = ',' then begin            Rewrite(izlaz);
  else                                                 Novi;                             Prevedi;
     Greska(DEFFUN);                                   imaistogtipa := false;            Close(ulaz);
  end;                                               end;                                Close(izlaz);
  aktnivo := 0;                                    until imaistogtipa;                   WriteLn('Prevedeno bez greske');
end;                                               while (globadresa mod 4) <> 0 do    end;
                                                     globadresa := globadresa + 1;
procedure Prevedi;                                 IdiDo(';');                         begin
var                                             end                                      Glavni
  globadresa: Integer;                        end;                                     end.
                                                                     61
10.SLOŢENI TIPOVI PODATAKA
         Dosadašnje smještanje nizova, definisanih preko pointera, u statiĉki navedene stringove priliĉno ograniĉava veliĉinu
koju niz moţe da ima. Iako se taj problem moţe prevazići primjenom API funkcije GlobalAlloc, i dalje se osjeća nedostatak
definisanih nizova odreĊene veliĉine u samom programskom jeziku. Pored ovoga, treba uvesti i višedimenzionalne nizove.
Drugi sloţeni tip koji treba uvesti su slogovi (strukture u C-u), tj. skup podataka razliĉitog tipa pod istim imenom. Konaĉno, da
bi bilo moguće praviti Windows aplikacije koje rade u grafiĉkom okruţenju, neophodno je i uvesti pointere na funkcije ili neki
drugi naĉin da se funkcija moţe pozvati, iako se u trenutku kompajliranja ne zna o kojoj je funkciji rijeĉ. Kombinovano sa
slogovima, to je i korak ka jeziku koji omogućava objektno orijentisano programiranje.


10.1.        Višedimenzionalni nizovi
        Deklarisanje višedimenzionalnih nizova se vrši navoĊenjem broja elemenata svake dimenzije iza oznake tipa, pri
ĉemu je donji indeks nizova uvijek 0. Npr.,
            cijeli [2,3] a;
            će rezervisati prostor za cijele brojeve a[0,0] a[0,1] a[0,2] a[1,0] a[1,1] i a[1,2] .
        Jedan ili više pozitivnih cijelih brojeva razdvojenih zarezima unutar uglastih zagrada naziva se deklaracioni
dimenzijski modifikator. Jedan ili više numeriĉkih izraza razdvojenih zarezima unutar uglastih zagrada naziva se lista indeksa.
Sintaksno se mogu predstaviti kao na slici Sl. 10.1.1
            Deklaracioni dimenzijski modifikator                                Lista indeksa


                                                                            [          Izraz
                         Konstanta                                                                         ]
                                                       ]                               dodjeljivan
        [
                                                                                       ja


                                 ,                                                               ,
                             Sl. 10.1.1.     Deklaracioni dimenzijski modifikator i lista indeksa
            Adresa poĉetka elementa jednodimenzionalnog niza se dobija formulom
            AdresaElementa=AdresaPočetkaNiza+Index*VeličinaElementaNiza
            Za dvodimenzionalne nizove ova formula iznosi
         AdresaElementa=AdresaPočetkaNiza+(BrojElemenataDrugeDimenzije*IndexPrveDimenzije+IndexDrugeDimenzije)
*VeličinaElementaNiza
            Za trodimenzionalne nizove ova formula iznosi
        AdresaElementa=AdresaPočetkaNiza+(BrojElemenataDrugeDimenzije*BrojElemenataTrećeDimenzije*IndexPrveDi
menzije+ BrojElemenataTrećeDimenzije*IndexDrugeDimenzije+IndexTrećeDimenzije)*VeličinaElementaNiza
            Formula se moţe generalizovati

            AdresaElementa=AdresaPoĉetkaNiza+(Indexn+((i=1,n-1,Indexi)*(j=i+1,n,BrojElemenataj)))VeliĉinaElementa
          ili generisati kodom sa slike Sl. 10.1.2, (koji će svoje mjesto naći u proceduri PokazivacINiz ) uz pretpostavku da
registar EBX sadrţi adresu poĉetka niza
                             Generiši MOV EAX,0
                             Povećaj brojač dimenzija
                             Generisi PUSH EAX
                              Pozovi IzrazDodjeljivanja
                             Generisi POP EBX
                             Ako nije zadnji indeks generiši MOV DX,ProizvodBrojElemenataNarednihDimenzija i
                generiši MUL EDX
                             Generiši ADD EBX,EAX
                             Generiši MOV EAX,EBX
                             Generiši množenje EAX sa veličinom elementa
                          Sl. 10.1.2.       Pseudokod i generisanje mašinskog koda za račun elementa
                                                        višedimenzionalnog niza
                                                               62


         Preuzima se koncept iz C-a da su nizovi i pointeri kompatibilni kada se prenose kao parametri, pri ĉemu se nizu ne
moţe dodijeliti vrijednost, iako je sintaksa višedimenzionalnih nizova drugaĉija. Za niz se alocira onoliko bajtova koliki je
proizvod svih dimenzija pomnoţen sa veliĉinom pojedinaĉnog argumenta, a za pointer ĉetiri bajta. Da bi se znalo koliko
prostora treba alocirati, u slog tabele TabIdent dodaje se broj dimenzija niza i broj elemenata u svakoj dimenziji. Ovaj sadrţaj
se kopira u globalni niz dimenzije i varijablu ukdim po potrebi. Shodno ovom proširuje se procedura DuzinaTipa.
        U dosadašnjim verzijama kompajlera iza imena varijable mogao je biti opcionalni indeks niza. Sada, kada se dodaju
višedimenzionalni nizovi, slogovi i indirektni pozivi funkcija, jeziĉki pojam varijabla izgleda kao na slici Sl. 10.1.3.
         Varijabla:


                                                                       Izraz                          )
                                                         (             dodjeljivanja

                                                                                 ,




                    Identifikator                                   Lista indeksa
                                                     [




                                                  Sl. 10.1.3.        Varijabla
         Male zagrade iza imena varijable omogućavaju indirektni poziv funkcije.


10.2.     Indirektni poziv funkcije
         Pointerskoj varijabli moguće je dodijeliti ime funkcije, ĉime ona pokazuje na potprogram. Kada se iza pointerske
varijable stave zagrade, tada će se generisati poziv potprograma takav da adresa na koju se skaĉe nije konstantna, nego se ĉita s
druge adrese. Kôd koji se generiše koristeći novu proceduru IndirektniPoziv izgleda kao na slici Sl. 10.2.1.

  Generiši labelu i lokaciju na kojoj se smješta duga riječ, npr L15 DD (?)
  Generiši MOV L15,EAX
  Za svaki izraz do zatvorene zagrade pozovi IzrazDodjeljivanja i odgovarajuće smještanje podataka
  na stek
  Generiši MOV ECX,velicinasteka
  Generiši indirektni poziv CALL L15

                              Sl. 10.2.1.       Generisanje koda za indirektni poziv funkcije
          Procedura IndirektniPoziv je jako sliĉna proceduri PozivFunkcije, osim što ne provjerava tip i broj argumenata
prilikom generisanja poziva funkcije. Dosadašnja funkcija PozivFunkcije ukljuĉuje i varijantu kada iza imena funkcije ne
slijede zagrade. Tada se u EAX registru vraća adresa poĉetka funkcije.
        Tip rezultata koji vraćaju indirektno pozvane funkcije je dereferencirani tip varijable u kojoj se nalazi adresa funkcije.
Na primjer, ako je varijabli koja je pokazivaĉ na realni broj dodijeljena adresa funkcije, ova funkcija će vratiti realni broj.
         Indirektni pozivi funkcija su moćan mehanizam koji treba koristiti sa velikim oprezom pošto mala greška moţe lako
da dovede do kraha programa. Iako se argumenti ne provjeravaju prilikom indirektnog poziva, funkcije normalno prihvaćaju
samo onaj broj i tip argumenata koliko ih ima u deklaraciji. Ukoliko je funkcija pozvana sa drugaĉijim brojem argumenata od
oĉekivanog, stek pointer neće biti u ispravnom poloţaju i to će izazvati krah. S druge strane, kako ECX registar u trenutku
poziva funkcije sadrţi veliĉinu memorije koju su zauzeli argumenti, uz pomoć asemblerskih modula moguće je praviti
funkcije sa promjenjivim brojem argumenata.
         Indirektni tip poziva omogućava uzajamnu rekurziju, tj. da funkcija P poziva funkciju Q, a funkcija Q da poziva
funkciju P. To se postiţe tako da se prije definicije funkcija definišu dvije pointerske varijable, unutar samih funkcija poziv
                                                            63
uzajamno rekurzivnih vrši koristeći indirektni poziv, a dodjela adresa funkcija pointerskim varijablama obavi na poĉetku
glavnog programa.


10.3.     Slogovi
         Slogovi se definišu rekurzivno, jer ĉlan sloga moţe biti novi slog, kao i niz, odnosno matrica, a takoĊer su mogući
nizovi slogova. U mnogim programskim jezicima svaka slogovska struktura predstavlja poseban tip. Kako jezik FILDZAN-32
nema korisniĉkih tipova, sve varijable koje predstavljaju slogove su tipa slog, a kao numeriĉka oznaka pojedine slogovske
strukture koristi se polje pod3 u tabeli identifikatora.
          Dodavanje tipa slog zahtijeva izmjenu jeziĉkog pojma ImeTipa, što je prikazano na slici uz odgovarajuće promjene
funkcija TipDek i SlijediDekTipa. Dio koda iz procedure Varijabla , koji generiše kôd za ĉitanje sadrţaja pointerskih
varijabli prebaĉen je u proceduru PEmit da se izbjegne njegovo dupliranje nakon uvoĊenja pointera na slogove.
         ImeTipa:

                              cijeli                                            Deklaracioni
                                                         *                      dimenzijski
                                                                                modifikator



                              realni                                            Deklaracioni
                                                         *                      dimenzijski
                                                                                modifikator



                           karakter                                             Deklaracioni
                                                         *                      dimenzijski
                                                                                modifikator




                                                     Deklaracioni                      Deklaracija
                    slog               *             dimenzijski                       sloga
                                                     modifikator




                                             Sl. 10.3.1.         Jezički pojam ImeTipa


         Jeziĉki pojam Deklaracija sloga, implementiran u proceduri DeklaracijaSloga izgleda kao na slici Sl. 10.3.2.

                     {          ImeTipa                      Identifikator                  }
                                                             imena polja

                                                                      ,

                                             ;
                                                 Sl. 10.3.2.        Deklaracija sloga
         Primjer:
            slog
             { cijeli x1,y1;
               cijeli x2,y2;
               karakter[80] poruka;
            } texbox;
         Implementacija deklaracije sloga, prikazana na slici Sl. 10.3.3 u osnovi dodaje u tabelu identifikatora za svako polje u
slogu novi identifikator pri ĉemu se za vrstu identifikatora navodi polje. Dodatni podaci koji se navode u tabeli slogova su
oznaka sloga, oznaka podsloga i relativna pozicija polja u bajtima od poĉetka sloga.
                                                                 64

                         Povećaj ukupni broj slogova za jedan i postavi dužinu sloga na nulu.
                         Za svaki tip koji se pojavljuje u deklaraciji sloga
                             (*) Ako je tip slog ili pointer na slog, podslog se dobija rekurzivnim pozivom
            deklaracije sloga, a za proste tipove podslog je sam slog.
                             Preuzmi ime identifikatora polja.
                             Potraži da li već postoji takav identifikator u tablici identifikatora za taj nivo i tu
            oznaku sloga i ako ima prijavi grešku.
                             Upiši ime polja u tablicu identifikatora zajedno sa oznakom podsloga i samog
            sloga, te trenutnom duzinom sloga.
                             Uvećaj dužinu sloga za dužinu tipa
                             Sve dok slijedi znak „,‟ vrati se na tačku (*)
                             Dužinu sloga poravnaj na vrijednost djeljivu sa 4.
                             Očekuj simbol „;‟
                         Ako nema više tipova, očekuj simbol „}‟.

                                 Sl. 10.3.3.      Aktivnosti pri deklarisanju sloga, pseudokod
         Cijeli slog (tj. varijabla slogovnog tipa) ima svoju poziciju u tabeli identifikatora, u koju se upisuje prilikom
deklaracije varijable ili parametara funkcije. OznakaSloga nije ta pozicija, nego redni broj deklarisanog sloga koji se svaki put
kada zapoĉne deklarisanje novog sloga ili podsloga, uvećava za jedan.
          Varijabla zadnji ĉuva podatke o zadnjem definisanom ili upotrijebljenom slogu. Ti podaci su njegova duţina, redni
broj sloga po redoslijedu deklarisanja i pozicija u tabeli identifikatora gdje se nalazi njegovo ime. Pomoću varijable zadnji
prevaziĊen je problem razliĉite strukture razliĉitih slogova. Procedura DuzinaTipa će za slogove vratiti duţinu zadnjeg
definisanog ili upotrijebljenog sloga. U proceduri varijabla se provjeri da li je u pitanju niz/matrica slogova. Ako jeste, duţina
tipa se dijeli sa ukupnim brojem elemenata.
         Pretraţivaĉ identifikatora NadjiIdent treba da traţi poziciju polja u tabeli identifikatora. Do sada rezervisani, tip
pretraţivanja 3 će obaviti ovaj zadatak.
          Nad slogovima je dopušteno od operacija samo dodjeljivanje ĉitavog sloga drugom slogu. Kako konkretna slogovna
struktura nema imena uzeta je konvencija da se slog moţe dodijeliti drugom slogu samo ako su jednake duţine. Dodjela sloga
slogu ili stavljanje sloga na stek se vrši naredbom REP MOVSB. Prije ove naredbe, ESI treba da pokazuje na izvorni slog, EDI
na odredišni ili mjesto na vrhu steka, ECX na duţinu sloga, a direction flag treba biti jednak 0.
          Na slici Sl. 10.3.4 dat je generisani kôd za smještanje sloga na stek i dodjeljivanje jedne slogovne varijable drugoj.

  MOV   ECX,duzinasloga                                       PUSH EBX
  SUB   ESP,duzinasloga                                       Izraz dodjeljivanja
  MOV   ESI,EBX                                               POP EDI
  MOV   EDI,ESP                                               MOV ESI,EBX
  CLD                                                         CLD
  REP   MOVSB                                                 MOV ECX,duzina sloga
                                                              REP MOVSB
                Smještanje sloga na stek
                                                            Dodjeljivanje slogovnih varijabli
                          Sl. 10.3.4.      Generisanje koda za operacije sa kompletnim slogovima

       Implementacija elementa sloga, tj. adrese i vrijednosti polja, navedena u proceduri ElementSloga je sliĉna
implementaciji varijabli, osim što se nakon dobijanja adrese varijable (cijelog sloga) u EBX registru, generiše instrukcija ADD
EBX,pozicijapolja, kako bi registar EBX pokazivao na poĉetak samog polja.
         Realizacija elementa sloga zahtijeva izmjenu jeziĉkog pojma Faktor Sl. 10.3.5. Na kraj ovog jeziĉkog pojma se
dodaje pojam ElementSloga ukoliko se na kraju pojma Faktor nalazi simbol “.”. Napomena: Ovo je izmijenjeno u odnosu na
prethodno izdanje skripte (gdje je element sloga bio iza varijable) kako bi se moglo pristupiti elementu sloga na koji pokazuje
pointer.
                                                           65

                    -

                    ~

                    &
                                             Faktor
                    *

                    !

                                        Numeriĉka konstanta                           .   Element
                                                                                          sloga
                            (                Izraz dodjeljivanja         )


                                         Varijabla

                            "                    String
                                                 konstanta
                                                      Poziv funkcije


                                „               Slovo                        „

                                          Sl. 10.3.5.        Jezički pojam Faktor


       Kako element sloga moţe takoĊe biti slog, jeziĉki pojam ElementSloga treba da ponavlja
generisanje adresa za pristup podpoljima i njegova struktura izgleda kao na slici Sl. 10.3.6

                        Identifikator
                        imena polja

                                    .

                                    Sl. 10.3.6.          Jezički pojam ElementSloga
                                                               66



10.4.     Testni primjer
          Primjer programa u ovoj verziji jezika je jedna jednostavna Windows GUI aplikacija. Program generiše osnovni
prozor na kome se nalaze tri dugmeta, od kojih pritisak na jedno aktivira poruku na ekranu, drugo pokreće aplikaciju Solitaire,
a treće crta jedan krug na ekranu.
         Poĉevši od treće verzije jezika svi dosadašnji primjeri su bile Windows konzolne aplikacije, tj. aplikacije koje koriste
tekstualni korisniĉki interfejs i nemaju reakcija na asinhrone dogaĊaje kao što je pritisak na miša ili preklapanje izmeĊu
prozora/procesa.
        Windows GUI aplikacije, s druge strane, primaju poruke u red ĉekanja i odgovaraju na njih. To se obiĉno vrši
primjenom GetMessage i DispatchMessage API funkcija koje ĉitaju poruku i pozivaju odgovarajući potprogram da se poruka
obradi.
       Potprogram za obradu poruke (koja je zapravo jedan slog), je definisan u opisu tzv. klase prozora, u njenom polju
lpfnWndProc. Klasa prozora predstavlja slog koji se ili popunjava pri startu programa ili uzima već gotov (kao što je
“BUTTON”). Tu klasu navodimo prilikom kreiranja prozora, kao jedan od parametara funkcije CreateWindow.
          Glavni prozor odgovara na tri vrste poruka, otvaranje programa (kada kreira podprozore koji su zapravo dugmad),
zatvaranje prozora (kada šalje poruku koja završava GetMessage/DispatchMessage petlju) i komandu (kada zavisno od
podprozora koji ju je poslao poziva funkciju MessageBox za ispis poruke, WinExec za start programa ili Ellipse za prikaz
elipse ĉiji je specijalni sluĉaj krug).
         Prozori se meĊusobno identifikuju konstantom koja se zove rukovatelj prozora (handle). Pored toga, prikaz elipse
zahtijeva konstantu device context kao jedan od parametara, koji se uzima funkcijom GetDC.
      Detaljniji opis ovoga primjera oduzeo bi dosta prostora. O naĉinu programiranja za Windows pogledati u referenci
[PETZOLD-01].
         Program se prevodi sa:
             komp32v7 wincircle.jez wincircle.asm
             ml /c /coff /Fl wincircle.asm | more
             link /defaultlib: user32.lib kernel32.lib gdi32.lib /subsystem:windows wincircle.obj
         Ĉinjenica da ovaj primjer radi, pokazuje da je jezik već dovoljno moćan da se u njemu, uz dosta truda, realizuje bilo
koja aplikacija koja koristi standardni Windows API . Interesantno je da je prevedeni EXE kôd dosta kratak, svega 4608
bajtova, iako još nije implementirana optimizacija koda. U većini drugih programskih jezika, sem asemblera, ovaj primjer bi
imao veći prevedeni kôd: od 12 kilobajta (Delphi u Object Pascal reţimu) do nekoliko megabajta (neki vizuelni alati koji
zahtijevaju veliki runtime, npr. Oracle Forms)
                                                                67



cijeli funkcija RegisterClassExA(cijeli * wndclass);                               40,120,60,140,
cijeli funkcija ShowWindow ( cijeli a,cijeli b) ;                                  WSCHILD | WSVISIBLE,"Soliter","BUTTON",0);
cijeli funkcija UpdateWindow(cijeli hWnd) ;                                       kc:=CreateWindowExA (0,hInstance,0,hWnd,
cijeli funkcija GetMessageA (cijeli a, cijeli b, cijeli                            40,120,100,140,
c,cijeli * d);                                                                     WSCHILD | WSVISIBLE,"Krug","BUTTON",0);
cijeli funkcija TranslateMessage (cijeli * d) ;
cijeli funkcija DispatchMessageA (cijeli * d) ;                                   obradjena:=1;
cijeli funkcija CreateWindowExA(cijeli a,cijeli b,cijeli c,
cijeli d,cijeli e,cijeli f,                                                  }
cijeli g,cijeli h,cijeli i,
 karakter * j,karakter * k,cijeli l);                                      ako (wMessage=2) `WM_DESTROY
cijeli funkcija LoadCursorA ( cijeli a,cijeli b) ;                           {
cijeli funkcija GetStockObject ( cijeli a) ;                                    PostQuitMessage (0) ;
cijeli funkcija PostQuitMessage ( cijeli a) ;                                   obradjena:=1;
cijeli funkcija DefWindowProcA (cijeli a, cijeli b, cijeli                   }
c,cijeli d);
cijeli funkcija MessageBoxA (cijeli a, karakter * b,                        ako (wMessage=273) `WM_COMMAND
karakter * c,cijeli d);                                                      {
cijeli funkcija WinExec (karakter * b, karakter * c);
cijeli funkcija GetModuleHandleA ( cijeli a) ;                                   ako (lParam=ka) {
cijeli funkcija GetDC ( cijeli a) ;                                                MessageBoxA (0,"Poruka","Pritisnut taster",0);
cijeli funkcija Ellipse (cijeli a, cijeli b, cijeli c,cijeli                     }
d,cijeli e);                                                                     ako (lParam=kb) {
cijeli funkcija ReleaseDC (cijeli a, cijeli b);                                    WinExec (" ","c:\windows\sol.exe");
                                                                                 }
cijeli hWnd ;                                                                    ako (lParam=kc) {
cijeli ka,kb,kc;                                                                   hDC:=GetDC (hWnd);
slog                                                                               Ellipse(200,200,0,0,hDC);
  {                                                                                ReleaseDC(hDC,hWnd);
     cijeli hwnd;                                                                }
     cijeli message;
     cijeli wParam;                                                              obradjena:=1;
     cijeli lParam;                                                          }
     cijeli time;
     slog                                                                  ako (obradjena=0)
       {                                                                     {
          cijeli x;                                                             DefWindowProcA (lParam,wParam,wMessage,hWnd) ;
          cijeli y;                                                          }
       } pt;                                                           }
  } msg ;         ` a message structure
                                                                   {
slog                                                                  nCmdShow:=10;
  {                                                                   hInstance:=GetModuleHandleA (0);
    cijeli cbsize;                                                    wndclass.cbsize:=48;
    cijeli   style;                                                   wndclass.style := 0 ;
    cijeli * lpfnWndProc;                                             wndclass.lpfnWndProc := WndProc ;
    cijeli   cbClsExtra;                                              wndclass.cbClsExtra := 0 ;
    cijeli   cbWndExtra;                                              wndclass.cbWndExtra := 0 ;
    cijeli   hInstance;                                               wndclass.hInstance := hInstance ;
    cijeli   hIcon;                                                   wndclass.hIcon := 0 ;
    cijeli   hCursor;                                                 wndclass.hCursor      := LoadCursorA (32512,0) ;
    cijeli   hbrBackground;                                       `IDC_ARROW
    karakter * lpszMenuName;                                          wndclass.hbrBackground := GetStockObject(2);
    karakter * lpszClassName;                                         wndclass.lpszMenuName     := 0;
    cijeli hIconSm;                                                   wndclass.lpszClassName := "PROBNA" ;
  } wndclass ; ` window class structure                               wndclass.hIconSm:=0;
                                                                      ako (!(RegisterClassExA (&wndclass)))
cijeli nCmdShow;                                                        {
karakter * lpszCmdLine;                                                     0 ;
cijeli hPrevInstance;                                                   }
cijeli hInstance;                                                     inace
karakter[30] pstr;                                                      {
cijeli funkcija WndProc(cijeli lParam,cijeli wParam,cijeli                hWnd := CreateWindowExA ( 0,hInstance,0,0,
wMessage,cijeli hWnd)                                                       400,400,4,4,13565952, `WS_OVERLAPPEDWINDOW
  { cijeli obradjena,WSCHILD,WSVISIBLE,hDC;                               "Prim","PROBNA",512);
                                                                          ShowWindow ( nCmdShow,hWnd) ;
       obradjena:=0;                                                      UpdateWindow(hWnd) ;
       ako (wMessage=1) `WM_CREATE                                        dok (GetMessageA (0, 0, 0,&msg))
         {                                                                   {
             WSCHILD := 1073741824; `$40000000;                                 TranslateMessage (&msg) ;
             WSVISIBLE := 268435456; `$10000000;                                DispatchMessageA (&msg) ;
             ka:=CreateWindowExA (0,hInstance,0,hWnd,                        }
              40,120,20,140,                                              msg.wParam ;
              WSCHILD | WSVISIBLE,"Poruka","BUTTON",0);                 }
             kb:=CreateWindowExA (0,hInstance,0,hWnd,               }
                                           Sl. 10.4.1.       Windows grafička aplikacija

10.5.      Rezime poglavlja
         Višedimenzionalni nizovi zahtijevaju nešto sloţeniji algoritam pristupa odgovarajućem elementu niza od
jednodimenzionalnih. Pojam varijable je proširen tako da moţe da predstavlja i element višedimenzionalnog niza, polje sloga
ili da predstavlja adresu funkcije koja se moţe indirektno pozvati navoĊenjem argumenata u zagradi iza imena varijable.
Indirektni poziv predstavlja CALL instrukciju na adresu koja je navedena u pointerskoj varijabli. Slogovi se sastoje od polja
koja se upisuju u tabelu identifikatora, ali i svaki definisani slog ima svoju oznaku. Uvijek se pamti koji je zadnji definisani ili
korišteni slog. U sadašnjoj verziji jezika moguće je pisati i grafiĉke aplikacije.
                                                              68
Prilog 7: Verzija izvornog koda kompajlera br. 7
program Kompajler;                           zadnji: TZadnjiSlog;                   end;
const                                        dimenzije: array[0..MAXDIM]of integer;
  MAXIDENT = 1024;                                                                  function UzmiKonstantu
  MAXDIM = 10;                             procedure NoviIdent(pime: string;          (var t: TTip; var dod: Boolean):
  DUGAKONST =                                pduzina: integer;                           integer;
    'Konstanta prevazilazi liniju';          padresa: integer; pnivo: integer;      var
  REALKONST = 'Realna konstanta';               pvrsta: TVrsta;                       rezultat: integer;
  OCEKIVANO = 'Ocekivano ';                  ptip: TTip; ppod1: integer; ppod2:     begin
  REDEKLAR='Redeklarisan identifikator';        integer; ppod3: integer);             rezultat := 0;
  PROSTNIZ =                               var                                        realnakonstanta := '';
    'Prosti tip ne moze biti niz';           i: integer;                              while (znak >= '0') and (znak <= '9')
  NEKORARG='Nekorektan broj argumenata';   begin                                         do begin
  NEKDODJP = 'Losa dodjela pointeru';        ukupnoident := ukupnoident + 1;             rezultat := 10 * rezultat +
  NEDEKL = 'Nedeklarisano ';                 with TabIdent[ukupnoident] do begin           ord(znak) - ord('0');
  GRIZRAZ = 'Izraz';                            ime := pime;                             realnakonstanta := realnakonstanta
  POGRMNOZ =                                    duzina := pduzina;                         + znak;
    'Pogresan tip u ' +                         adresa := padresa;                       NoviSvaki(false);
    'mnozenju ili dijeljenju';                  nivo := pnivo;                        end;
  NEDOPFP =                                     vrsta := pvrsta;                      if (znak = '.') or (znak = 'e') or
    ' Nedopustena FP operacija';                tip := ptip;                             (znak = 'E') then begin
  NEDOPARIT =                                   pod1 := ppod1;                           if znak = '.' then begin
    'Nedopusteni tip u aritmetici';             pod2 := ppod2;                             realnakonstanta := realnakonstanta
  OCEKDOD = 'Ocekivano dodjeljivanje';          pod3 := ppod3;                                + znak;
  NEDODJ ='Izraz se ne moze dodijeliti';        ukupdim := ukdim;                          NoviSvaki(false);
  DODJPOINT = 'Losa dodjela pointeru';          for i := 0 to MAXDIM do                    while (znak >= '0') and (znak <=
  TIPUSL = 'Neodgovarajuci tip uslova';           dim[i] := dimenzije[i];                     '9') do begin
  TUSLPET =                                  end;                                             realnakonstanta:=realnakonstanta
    'Neodgovarajuci uslov u petlji';       end;                                                 + znak;
  IMEFUN = 'Ocekivano ime funkcije';                                                          NoviSvaki(false);
  DEFFUN = 'Definicija funkcije';          procedure NovaLabela(var ImeLabele:             end;
  ARGNEKOM =                                 string);                                    end;
    'Argument nekompatibilan' +            begin                                         if (znak = 'e') or (znak = 'E') then
    ' s operatorom';                         trenlabela := trenlabela + 1;                 begin
  OCIDENT = 'Ocekivan Identifikator';        Str(trenlabela, ImeLabele);                   realnakonstanta := realnakonstanta
  MAXDIMOV ='Maksimalan broj dimenzija';   end;                                               + znak;
  INDSTATC =                                                                               NoviSvaki(false);
    'Indeks statickog niza nije cijeli';   procedure Greska(poruka: string);               if (znak = '+') or (znak = '-')
  PREVDIM =                                begin                                              then begin
    'Prevazidjen broj dimenzija';            WriteLn(poruka);                                 realnakonstanta:=realnakonstanta
  NESLDIM =                                  WriteLn(brojaclinija, ':', linija);                + znak;
    'Ne slaze se broj dimenzija';            Close(ulaz);                                     NoviSvaki(false);
  POLJEPOS = 'Polje vec postoji';            Close(izlaz);                                 end;
  SLOGPOLJE =                                Halt;                                         if (znak<'0')or(znak>'9') then
    'Samo slogovi mogu imati polja';       end;                                               Greska(REALKONST);
  NEDEKPOLJE = 'Nedeklarisano polje';                                                      while (znak >= '0') and (znak <=
  SLOGSLOGU =                              procedure Emit(st: string);                        '9') do begin
    'Slog se moze dodijeliti samoslogu';   begin                                              realnakonstanta :=
  SLOGRAZDUZ =                               WriteLn(izlaz, st);                                realnakonstanta+ znak;
    'Slogovi razlicite duzine';            end;                                               NoviSvaki(false);
  INDNOPOINT =                                                                             end;
    'Indirektna funkcija bez pointera';    procedure Novi;                               end;
  SLOGNEPOR =                              begin                                         UzmiKonstantu := 0;
    'Slogovi se ne mogu porediti';           repeat                                      t := realni;
                                                pozicija := pozicija + 1;             end
type                                            if pozicija > Length(linija) then     else begin
  TVrsta = (funkcija, lokalna,                    begin                                  UzmiKonstantu := rezultat;
     globalna, parametar, polje);                 brojaclinija := brojaclinija + 1;      t := cijeli;
  TTip = (karakter, cijeli, realni,               if not (Eof(ulaz)) then             end;
     slog, pkarakter,                                ReadLn(ulaz, linija);            if (znak = ' ') or (znak = '`') then
     pcijeli, prealni, pslog);                    Emit(';' + linija);                    Novi;
  TIdent = record                                 pozicija := 1;                      dod := false;
     ime: string[20];                           end;                                end;
     duzina: integer;                           if Length(linija) > 0 then
     adresa: integer;                             znak := linija[pozicija]          function Slijedi(ocekivano: string;
     nivo: integer;                             else                                  dslovoiza: Boolean): Boolean;
     vrsta: TVrsta;                               znak := ' ';                      var
     tip: TTip;                                 if (znak = '`') then                  ureduiza: Boolean;
     pod1: integer;                               pozicija := Length(linija);         n: integer;
     pod2: integer;                          until ((znak > ' ') and (znak <>         znak: char;
     pod3: integer;                             '`')) or Eof(ulaz)                  begin
     ukupdim: integer;                     end;                                       if dslovoiza then
     dim: array[0..MAXDIM] of integer;                                                   ureduiza := true
  end;                                     procedure NoviSvaki(greskakrln:            else begin
                                             Boolean);                                   n := pozicija + Length(ocekivano);
  TZadnjiSlog = record                     begin                                         ureduiza := true;
    duzina: integer;                         pozicija := pozicija + 1;                   if Length(linija) >= n then begin
    pozimena: integer;                       if pozicija > Length(linija) then             znak := linija[n];
    idopisasloga: integer                       begin                                      if ((znak >= 'a') and (znak <=
  end;                                          if greskakrln then                            'z')) or
                                                  Greska(DUGAKONST)                           ((znak >= 'A') and (znak <=
var                                             else                                            'Z')) then
  ulaz, izlaz: text;                              znak := ' ';                                ureduiza := false
  pozicija, trenlabela, brojaclinija,        end                                         end
    aktnivo: integer;                        else                                     end;
  znak: char;                                   znak := linija[pozicija];             if ureduiza and (copy(linija,
  linija, realnakonstanta: string;         end;                                          pozicija,
  TabIdent: array[0..MAXIDENT] of                                                        Length(ocekivano)) = ocekivano) then
    TIdent;                                procedure IdiDo(z: char);                       begin
  ukupnoident, ukupnoslogova, ukdim:       begin                                         Slijedi := true;
    integer;                                 if (znak <> z) then                         pozicija := pozicija +
  t: TTip;                                      Greska(OCEKIVANO + z);                     Length(ocekivano) - 1;
  dod: Boolean;                              Novi;                                    end
                                                             69
  else                                         realni: DuzinaTipa := 8;                 Emit(' PUSH EAX');
     Slijedi := false;                         slog: DuzinaTipa := zadnji.duzina;       Emit(' MOV EAX,0');
end;                                        else                                        repeat
                                               DuzinaTipa := 4;                            Novi;
function TipDek(imetipa: string; var        end;                                           navdim := navdim + 1;
  tip: TTip;                              end;                                             if navdim > MAXDIM then
  stip, ptip: TTip): Boolean;                                                                Greska(PREVDIM);
var                                       function NadjiIdent(ident: string;               Emit(' PUSH EAX');
  tipind: TTip;                             nivo, tuslova, p1: integer): integer;          IzrazDodjeljivanja(t1, dod);
  kraj, x, poi: Boolean;                  var                                              Emit(' POP EBX');
begin                                       n, poz: integer;                               if znak = ',' then begin
  TipDek := false;                          nadjen, Uslov: Boolean;                          dsvedim:=1;
  poi := false;                           begin                                              for i:=navdim+1 to
  if Slijedi(imetipa, false) then begin     n := ukupnoident;                                 TabIdent[idpoz].ukupdim do
     TipDek := true;                        nadjen := false;                                     dsvedim:=dsvedim*
     Novi;                                  poz := 0;                                             TabIdent[idpoz].dim[i];
     if znak = '*' then begin               while (n > 0) and (not (nadjen)) do              Str(dsvedim, st);
       tip := ptip;                            begin                                         Emit(' MOV EDX,' + st);
       poi := true;                            case tuslova of                               Emit(' MUL EDX');
       Novi                                      1: Uslov := (TabIdent[n].ime =            end;
     end                                            ident) and                             Emit(' ADD EBX,EAX');
     else                                           (TabIdent[n].vrsta in                  Emit(' MOV EAX,EBX');
       tip := stip;                                   [lokalna, globalna,               until znak <> ',';
     ukdim := 0;                                        parametar, funkcija]) and       Emit(' POP EBX');
     if znak = '[' then begin                         ((TabIdent[n].nivo = nivo) or     if (navdim <> TabIdent[idpoz].ukupdim)
       if poi then                                      (TabIdent[n].nivo = 0));           and (not ((navdim = 1) and
          tip := pcijeli                         2: Uslov := (TabIdent[n].ime =            (TabIdent[idpoz].ukupdim = 0))) then
       else                                         ident) and                             Greska(NESLDIM);
          tip := ptip;                              (TabIdent[n].vrsta in               IdiDo(']');
       IdiDo('[');                                    [lokalna, globalna,               case t of
       repeat                                           parametar, funkcija]) and          pkarakter: begin
          ukdim := ukdim + 1;                         ((TabIdent[n].nivo = nivo));              t := karakter;
          if ukdim > MAXDIM then                 3: Uslov := (TabIdent[n].ime =              end;
            Greska(MAXDIMOV);                       ident) and                             pcijeli: begin
          dimenzije[ukdim] :=                       (TabIdent[n].vrsta = polje) and             Emit(' SAL EAX,2');
            UzmiKonstantu(tipind, x);                 (TabIdent[n].nivo = nivo) and             t := cijeli;
          if tipind <> cijeli then                      (TabIdent[n].pod3 = p1);             end;
            Greska(INDSTATC);                    4: Uslov := (TabIdent[n].nivo =           prealni: begin
          kraj := true;                             nivo) and                                   Emit(' FSTP ST(0)');
          if znak = ',' then begin                  (TabIdent[n].pod2 = p1) and                 Emit(' SAL EAX,3');
            Novi;                                     (TabIdent[n].vrsta =                      t := realni;
            kraj := false;                parametar)                                         end;
          end;                                 else                                        pslog: begin
       until kraj;                               Uslov := false;                                t := slog;
       IdiDo(']');                             end;                                             Str(DuzinaTipa(t), st);
     end;                                      if Uslov then begin                              Emit(' MOV EDX,' + st);
  end                                            nadjen := true;                                Emit(' MUL EDX');
end;                                             poz := n;                                   end;
                                               end;                                     else
function SlijediDekTipa(var tip: TTip):        n := n - 1;                                 Greska(PROSTNIZ)
  Boolean;                                  end;                                        end;
var                                         NadjiIdent := poz;                          Emit(' ADD EBX,EAX');
  a: Boolean;                             end;                                          case t of
begin                                                                                      karakter:
  a := false;                             procedure UzmiIdent(var ident: string);            Emit(' MOV AL,[EBX]');
  if not (a) then                         begin                                            realni:
     a := TipDek('cijeli', tip, cijeli,     if znak in ['a'..'z', 'A'..'Z'] then             Emit(' FLD QWORD PTR [EBX]')
       pcijeli);                               begin                                    else
  if not (a) then                              ident := znak;                              Emit(' MOV EAX,[EBX]');
     a := TipDek('karakter', tip,              NoviSvaki(false);                        end;
       karakter, pkarakter);                end                                         dod := true;
  if not (a) then                           else                                      end;
     a := TipDek('realni', tip, realni,        Greska(OCIDENT);
       prealni);                            while (znak in ['a'..'z', 'A'..'Z',    procedure StringKonstanta(var t: TTip;
  if not (a) then                              '0'..'9', '_']) do begin              var dod: Boolean);
     a := TipDek('slog', tip, slog,            ident := ident + znak;              var
       pslog);                                 NoviSvaki(false);                     st, strtekst: string;
  SlijediDekTipa := a;                      end;                                   begin
end;                                        if (znak = ' ') or (znak = '`') then     NovaLabela(strtekst);
                                               Novi;                                 Emit('.DATA');
function DuzinaTipa(tip: TTip):           end;                                       st := 'L' + strtekst + ' DB ''';
  Integer;                                                                           repeat
var                                       procedure DeklIdent(var ident: string;        NoviSvaki(true);
  elem, i: integer;                         nivo: integer);                             if znak <> '"' then
begin                                     begin                                           st := st + znak;
  case tip of                               UzmiIdent(ident);                        until znak = '"';
    cijeli: DuzinaTipa := 4;                if NadjiIdent(ident, nivo, 2, 0) <> 0    IdiDo('"');
    pcijeli, pkarakter, prealni, pslog:        then                                  st := st + ''',0';
      begin                                    Greska(REDEKLAR);                     if copy(st, length(st) - 3, 2) =
        if ukdim = 0 then                 end;                                          '''''' then
           DuzinaTipa := 4                                                              st := 'L' + strtekst + ' DB 0';
        else begin                        procedure IzrazDodjeljivanja               Emit(st);
           elem := 4 * ord(tip = pcijeli)   (var t: TTip; var dod: Boolean);         Emit('.CODE');
             + 1 * ord(tip = pkarakter) +      forward;                              Emit(' MOV EAX,OFFSET L' + strtekst);
             8 * ord(tip = prealni) +     procedure Blok; forward;                   t := pkarakter;
             zadnji.duzina * ord(tip =                                               dod := false;
               pslog);                    procedure PokazivacINiz(var t: TTip; var end;
           for i := 1 to ukdim do           dod: Boolean; idpoz: Integer);
             elem := elem *               var                                      procedure PEmit(idpoz: Integer);
               dimenzije[i];                t1: TTip;                              var
           DuzinaTipa := elem;              navdim,dsvedim,i: Integer;               i: integer;
        end                                 st: string;                            begin
      end;                                begin                                      if TabIdent[idpoz].ukupdim = 0 then
    karakter: DuzinaTipa := 1;              navdim := 0;                                Emit(' MOV EAX,[EBX]')
                                                              70
  else                                                    TabIdent[poz].duzina;             if t2 = slog then
     Emit(' MOV EAX,EBX');                             zadnji.pozimena := poz;                 duzdrugogsloga :=
  ukdim := TabIdent[idpoz].ukupdim;                    zadnji.idopisasloga :=                     TabIdent[n].duzina;
  for i := 0 to MAXDIM do                                 TabIdent[poz].pod3;               if (t1 in [karakter, realni]) and
     dimenzije[i] :=                                 end;                                      (t2 in [pkarakter, pcijeli,
       TabIdent[idpoz].dim[i];                    cijeli: Emit(' MOV EAX,[EBX]');                 prealni]) then
end;                                            else                                           Greska(NEKDODJP);
                                                  PEmit(poz);                               if (t1 = karakter) and (t2 =
function DeklaracijaSloga(nivo:                 end;                                           cijeli) then
  integer): integer;                         end;                                              Emit(' AND EAX,0FFh');
var                                        end;                                             if ((t1 = slog) and (t2 <> slog))
  ImePolja: string;                                                                            or
  oznakasloga, podslog, duzinasloga,       procedure CijeliNaFPStek(reg: string;               ((t1 <> slog) and (t2 = slog))
     zapukdim, i, poz: integer;              osmobitni: Boolean);                                 then
  tip: TTip;                               begin                                               Greska(SLOGSLOGU);
  imaistogtipa: Boolean;                     if osmobitni then                              case t2 of
  zdimenzije: array[0..MAXDIM] of               Emit(' AND ' + reg + ',0FFh');                 slog: begin
     integer;                                Emit(' MOV INTTOFP,' + reg);                           if duzprvogsloga <>
begin                                        Emit(' FILD DWORD PTR INTTOFP');                          duzdrugogsloga then
  zapukdim := ukdim;                       end;                                                        Greska(SLOGRAZDUZ);
  for i := 0 to MAXDIM do                                                                           m1 := ((duzprvogsloga - 1)
     zdimenzije[i] := dimenzije[i];        procedure FPStekUCijeli(reg: string);                       div 4 + 1) * 4;
  IdiDo('{');                              begin                                                    velsteka := velsteka + m1;
  ukupnoslogova := ukupnoslogova + 1;        Emit(' ADD ESP,-4');                                   Str(duzprvogsloga, st);
  oznakasloga := ukupnoslogova;              Emit(' FISTP DWORD PTR [ESP]');                        Emit(' MOV ECX,' + st);
  duzinasloga := 0;                          Emit(' POP ' + reg);                                   Str(m1, st);
  poz := 0;                                end;                                                     Emit(' SUB ESP,' + st);
  while SlijediDekTipa(tip) do begin                                                                Emit(' MOV ESI,EBX');
     if (tip = slog) or (tip = pslog)      procedure                                                Emit(' MOV EDI,ESP');
       then                                  CPUStekCijeliNaFPStek(osmobitni:                       Emit(' CLD');
       podslog := DeklaracijaSloga(nivo)     Boolean);                                              Emit(' REP MOVSB');
     else                                  begin                                                  end;
       podslog := oznakasloga;               if osmobitni then                                 realni: begin
     repeat                                     Emit(' AND DWORD PTR [ESP],0FFh');                  velsteka := velsteka + 8;
       UzmiIdent(ImePolja);                  Emit(' FILD DWORD PTR [ESP]');                         case t1 of
       poz := NadjiIdent(ImePolja, nivo,     Emit(' ADD ESP,4');                                       realni: ;
          3, podslog);                     end;                                                        karakter:
       if poz <> 0 then                                                                                  CijeliNaFPStek('EAX',
          Greska(POLJEPOS);                procedure FPUStekNaStek;                                      true);
       NoviIdent(ImePolja,                 begin                                                    else
          DuzinaTipa(tip),                   Emit(' ADD ESP,-8');                                      CijeliNaFPStek('EAX',
          0, nivo, polje, tip, podslog,      Emit(' FSTP QWORD PTR [ESP]');                              false);
            duzinasloga, oznakasloga);     end;                                                     end;
       duzinasloga := duzinasloga +                                                                 FPUStekNaStek;
          DuzinaTipa(tip);                 procedure StekNaFPUStek;                               end
       imaistogtipa := true;               begin                                            else begin
       if znak = ',' then begin              Emit(' FLD QWORD PTR [ESP]');                        velsteka := velsteka + 4;
          Novi;                              Emit(' ADD ESP,8');                                  if t1 = realni then
          imaistogtipa := false;           end;                                                     FPStekUCijeli('EAX');
       end;                                                                                       Emit(' PUSH EAX');
     until imaistogtipa;                   procedure PozivFunkcije                             end;
     while (duzinasloga mod 4) <> 0 do       (idpoz: integer; var t: TTip; var              end;
       duzinasloga := duzinasloga + 1;         dod: Boolean);                               if znak <> ')' then
     IdiDo(';');                           var                                                 IdiDo(',');
  end;                                       parametara, N, velsteka,                     end;
  IdiDo('}');                                  duzprvogsloga,                             IdiDo(')');
  zadnji.duzina := duzinasloga;                duzdrugogsloga, m1: integer;               if TabIdent[idpoz].pod1 <>
  zadnji.pozimena := poz;                    t1, t2: TTip;                                  parametara then
  zadnji.idopisasloga := OznakaSloga;        ImeFunkcije, st: string;                       Greska(NEKORARG);
  DeklaracijaSloga := OznakaSloga;         begin                                          Str(velsteka, st);
  ukdim := zapukdim;                         ImeFunkcije := TabIdent[idpoz].ime;          Emit(' MOV ECX,' + st);
  for i := 0 to MAXDIM do                    parametara := 0;                             Emit(' CALL ' + ImeFunkcije + '@' +
     dimenzije[i] := zdimenzije[i];          velsteka := 0;                                 st);
end;                                         duzprvogsloga := 0;                          dod := false;
                                             duzdrugogsloga := 0;                         t := TabIdent[idpoz].tip;
procedure ElementSloga                       if znak <> '(' then begin                    if t = karakter then
  (idpoz: integer; var t: TTip; var            velsteka := 0;                               Emit(' AND EAX,0FFh');
    dod: Boolean);                             for parametara := 1 to                  end;
var                                              TabIdent[idpoz].pod1 do begin       end;
  poz, nivo, idsloga: integer;                   n := NadjiIdent('', idpoz, 4,       procedure IndirektniPoziv(var t: TTip);
  Imepolja, st: string;                             parametara);                     var
begin                                            velsteka := velsteka + (              m1, velsteka, duzsloga: Integer;
  if t <> slog then                                 (TabIdent[n].duzina - 1) div 4     straddr, st: string;
    Greska(SLOGPOLJE);                                + 1) * 4;                        t1: TTip;
  nivo := TabIdent[idpoz].nivo;                end;                                  begin
  idsloga := TabIdent[idpoz].pod3;             Str(velsteka, st);                      velsteka := 0;
  while znak = '.' do begin                    Emit(' MOV EAX,OFFSET ' +               NovaLabela(straddr);
    Novi;                                        imefunkcije + '@' + st);              Emit('.DATA');
    UzmiIdent(ImePolja);                       t := pcijeli;                           st := 'L' + straddr + ' DD ?';
    poz := NadjiIdent(ImePolja, nivo,          dod := false;                           Emit(st);
      3, idsloga);                           end                                       Emit('.CODE');
    if poz = 0 then                          else begin                                Emit(' MOV L' + straddr + ',EAX');
      Greska(NEDEKPOLJE);                      IdiDo('(');                             IdiDo('(');
    Str(TabIdent[poz].pod2, st);               while (znak <> ')') do begin            while (znak <> ')') do begin
    Emit(' ADD EBX,' + st);                      IzrazDodjeljivanja(t1, dod);             IzrazDodjeljivanja(t1, dod);
    t := TabIdent[poz].tip;                      if t1 = slog then                        case t1 of
    case t of                                       duzprvogsloga :=                        slog: begin
      karakter: Emit(' MOV AL,[EBX]');                DuzinaTipa(t1);                             duzsloga := DuzinaTipa(t1);
      realni:                                    parametara := parametara + 1;                    m1 := ((duzsloga - 1) div 4 +
        Emit(' FLD QWORD PTR [EBX]');            n := NadjiIdent('', idpoz, 4,                      1) * 4;
      slog: begin                                   parametara);                                  velsteka := velsteka + m1;
          idsloga :=                             if n = 0 then                                    Str(duzsloga, st);
            TabIdent[poz].pod1;                     Greska(NEKORARG);                             Emit(' MOV ECX,' + st);
          zadnji.duzina :=                       t2 := TabIdent[n].tip;                           Str(m1, st);
                                                             71
            Emit(' SUB ESP,' + st);         Boolean);                                         t := karakter;
            Emit(' MOV ESI,EBX');         var                                               end;
            Emit(' MOV EDI,ESP');           rezultat, poz: integer;                       '0'..'9': begin
            Emit(' CLD');                   st, fpkonst, ime, err: string;                    rezultat := UzmiKonstantu(t,
            Emit(' REP MOVSB');           begin                                                  dod);
          end;                              err := ARGNEKOM;                                  case t of
       realni: begin                        case znak of                                         cijeli: begin
            velsteka := velsteka + 8;         '-': begin                                             Str(rezultat, st);
            FPUStekNaStek;                        Novi;                                              Emit(' MOV EAX,' + st);
          end                                     Faktor(t, dod);                                  end;
     else begin                                   case t of                                      realni: begin
          velsteka := velsteka + 4;                  cijeli: Emit(' NEG EAX');                       NovaLabela(fpkonst);
          Emit(' PUSH EAX');                         realni: Emit(' FCHS');                          Emit('.DATA');
       end;                                       else                                               st := 'L' + fpkonst +
     end;                                            Greska(err);                                       ' DQ '+ realnakonstanta;
     if znak <> ')' then                          end;                                               Emit(st);
       IdiDo(',');                                dod := false;                                      Emit('.CODE');
  end;                                          end;                                                 Emit(' FLD L' + fpkonst);
  IdiDo(')');                                 '~': begin                                           end;
  Str(velsteka, st);                              Novi;                                       end;
  Emit(' MOV ECX,' + st);                         Faktor(t, dod);                           end;
  Emit(' CALL L' + straddr);                      case t of                               '(': begin
  case t of                                          cijeli: Emit(' NOT EAX');                Novi;
     pcijeli: t := cijeli;                           karakter: Emit(' NOT AL');               IzrazDodjeljivanja(t, dod);
     prealni: t := realni;                        else                                        IdiDo(')');
     pkarakter: t := karakter;                       Greska(err);                           end;
     pslog: t := slog;                            end;                                    'A'..'Z', 'a'..'z': begin
  else                                            dod := false;                               UzmiIdent(ime);
     Greska(INDNOPOINT)                         end;                                          poz := NadjiIdent(ime, aktnivo,
  end;                                        '&': begin                                         1, 0);
end;                                              Novi;                                       if poz = 0 then
                                                  Faktor(t, dod);                                Greska(NEDEKL + ime);
procedure Varijabla                               Emit(' MOV EAX,EBX');                       case TabIdent[poz].vrsta of
  (idpoz: integer; var t: TTip; var               case t of                                      funkcija:
     dod: Boolean; glob: Boolean);                   cijeli: t := pcijeli;                         PozivFunkcije(poz, t, dod);
var                                                  karakter: t := pkarakter;                   lokalna, parametar:
  rezultat: integer;                                 slog: t := pslog;                             Varijabla(poz, t, dod,
  st: string;                                        realni: begin                                   false);
begin                                                    t := prealni;                           globalna:
  rezultat := TabIdent[idpoz].adresa;                    Emit(' FSTP ST(0)');                      Varijabla(poz, t, dod, true)
  t := TabIdent[idpoz].tip;                            end;                                   end
  Str(rezultat, st);                              else                                      end;
  if glob then                                       t := pcijeli;                     else
     Emit(' LEA EBX,GLOBALV[' + st + ']')         end;                                    Greska(GRIZRAZ);
  else begin                                      dod := false;                        end;
     if rezultat >= 0 then                      end;                                   if znak = '.' then
       Emit(' LEA EBX,[EBP+' + st + ']')      '*': begin                                  ElementSloga(zadnji.pozimena,t,dod);
     else                                         Novi;                              end;
       Emit(' LEA EBX,[EBP' + st + ']');          Faktor(t, dod);
  end;                                            Emit(' MOV EBX,EAX');              procedure Clan(var t: TTip; var dod:
  case t of                                       if t = prealni then begin            Boolean);
     karakter: Emit(' MOV AL,[EBX]');                Emit(' FSTP ST(0)');            var
     realni:                                         Emit(' FLD QWORD PTR [EBX]');     z: char;
       Emit(' FLD QWORD PTR [EBX]');              end                                  t1, t2: TTip;
          slog: begin                             else                               begin
          zadnji.duzina :=                           Emit(' MOV EAX,[EBX]');           Faktor(t1, dod);
            TabIdent[idpoz].duzina;               case t of                            t := t1;
          zadnji.pozimena := idpoz;                  pcijeli: t := cijeli;             while (znak in ['*', '/', '%']) do
          zadnji.idopisasloga :=                     pkarakter: begin                    begin
            TabIdent[idpoz].pod3;                        t := karakter;                  z := znak;
       end;                                              Emit(' AND EAX,0FFh');          if t1 <> realni then
     pslog: begin                                      end;                                Emit(' PUSH EAX')
          rezultat:=1;                               prealni: t := realni;               else
          for i:=1 to TabIdent[idpoz].               pslog: begin                          FPUStekNaStek;
           ukupdim do                                    t := slog;                      Novi;
            rezultat:=rezultat*                        end;                              Faktor(t2, dod);
            TabIdent[idpoz].dim[i];               else                                   dod := false;
          if rezultat<>0 then                        Greska(err);                        if (not (t1 in [cijeli, karakter,
            zadnji.duzina :=                      end;                                     realni])) or
           TabIdent[idpoz].duzina                 dod := true;                             (not (t2 in [cijeli, karakter,
           div rezultat                         end;                                          realni])) then
          else                                '!': begin                                   Greska(POGRMNOZ);
            zadnji.duzina:=4;                     Novi;                                  if (t1 = realni) or (t2 = realni)
          zadnji.pozimena := idpoz;               Faktor(t, dod);                          then begin
          zadnji.idopisasloga :=                  case t of                                t := realni;
            TabIdent[idpoz].pod3;                    cijeli: Emit(' CMP EAX,0');           if t2 <> realni then
          PEmit(idpoz);                              karakter: Emit(' CMP AL,0');             CijeliNaFPStek('EAX', t2 =
       end;                                       else                                          karakter);
     cijeli: Emit(' MOV EAX,[EBX]');                 Greska(err);                          if t1 <> realni then
  else                                            end;                                        CPUStekCijeliNaFPStek(t1 =
     PEmit(idpoz);                                Emit(' SETE AL');                             karakter)
  end;                                            Emit(' AND EAX,0FFh');                   else
  if TabIdent[idpoz].ukupdim = 0 then             dod := false;                               StekNaFPUStek;
     dod := true                                  t := cijeli;                             case z of
  else                                          end;                                          '*': Emit(' FMUL ');
     dod := false;                            '"': begin                                      '/': Emit(' FDIVR ');
  while znak ='[' do begin                        StringKonstanta(t, dod);                 else
     PokazivacINiz(t, dod, idpoz);              end;                                          Greska(NEDOPFP);
  end;                                        '''': begin                                  end
  if znak = '(' then                              NoviSvaki(true);                       end
     IndirektniPoziv(t);                          Emit(' MOV AL,''' + znak +             else begin
end;                                                 '''');                                t := cijeli;
                                                  Novi;                                    case z of
procedure Faktor(var t: TTip; var dod:            IdiDo('''');                                '*': begin
                                                              72
              Emit(' POP EBX');                             if t1 = karakter then                else
              if t1 = karakter then                            Emit(' AND EAX,0FFh');              Emit(' MOV [EBX],EAX');
                 Emit(' AND EBX,0FFh');                     if t2 = karakter then                end;
              if t2 = karakter then                            Emit(' AND EBX,0FFh');            t := t1;
                 Emit(' AND EAX,0FFh');                     Emit(' SUB EAX,EBX');              end; {:}
              Emit(' IMUL EBX');                          end;                               '=', '>', '<', '#': begin
            end;                                       end;                                      if t1 <> realni then
          '/', '%': begin                            '&', '|', '^': begin                          Emit(' PUSH EAX')
              Emit(' MOV EBX,EAX');                       if (t1 = karakter) and (t2             else
              Emit(' POP EAX');                             = karakter) then                       FPUStekNaStek;
              Emit(' CDQ');                                 t := karakter                        z := znak;
              if t1 = karakter then                       else                                   Novi;
                 Emit(' AND EAX,0FFh');                     t := cijeli;                         Izraz(t2, dod);
              if t2 = karakter then                       Emit(' POP EBX');                      if (t1 = slog) or (t2 = slog)
                 Emit(' AND EBX,0FFh');                   case z of                                then
              Emit(' IDIV EBX');                            '&':                                   Greska(SLOGNEPOR);
              if z = '%' then                                  Emit(' AND EAX,EBX');             if t1 <> realni then
                 Emit(' MOV EAX,EDX');                      '|': Emit(' OR EAX,EBX');              Emit(' POP EBX');
            end;                                            '^':                                 if (t1 = realni) or (t2 =
       end;                                                    Emit(' XOR EAX,EBX');               realni) then begin
     end;                                                 end;                                     if t2 <> realni then
     t1 := t;                                          end;                                           CijeliNaFPStek('EAX', t2 =
  end;                                            end;                                                  karakter);
end;                                            end;                                               if t1 <> realni then
                                                t1 := t;                                              CijeliNaFPStek('EBX', t1 =
procedure Izraz(var t: TTip; var dod:        end;                                                       karakter)
  Boolean);                                end;                                                    else
var                                        procedure IzrazDodjeljivanja                               StekNaFPUStek;
  z: char;                                   (var t: TTip; var dod: Boolean);                      Emit(' FCOMPP ');
  t1, t2: TTip;                            var                                                     Emit(' FSTSW AX');
begin                                        z: char;                                              Emit(' SAHF');
  Clan(t1, dod);                             t1, t2: TTip;                                         case z of
  t := t1;                                   dod1: Boolean;                                           '=': Emit(' SETE AL');
  while (znak in ['+', '-', '&', '|',        duzprvogsloga, duzdrugogsloga:                           '>': Emit(' SETA AL');
    '^']) do begin                              Integer;                                              '<': Emit(' SETB AL');
    if t1 <> realni then                     st: string;                                              '#': Emit(' SETNE AL');
      Emit(' PUSH EAX')                    begin                                                   end;
    else                                     duzprvogsloga := 0;                                   Emit(' AND EAX,0FFh');
      FPUStekNaStek;                         duzdrugogsloga := 0;                                  t := cijeli;
    z := znak;                               Izraz(t1, dod1);                                    end
    Novi;                                    if t1 = slog then                                   else begin
    Clan(t2, dod);                              duzprvogsloga := DuzinaTipa(t1);                   if (t1 = karakter) and (t2 =
    dod := false;                            t := t1;                                                 karakter) then
    if (not (t1 in [cijeli, karakter,        dod := dod1;                                             Emit(' CMP BL,AL')
      realni])) or                           case znak of                                          else begin
      (not (t2 in [cijeli, karakter,            ':': begin                                            if t1 = karakter then
         realni])) then                              if not (Slijedi(':=', true))                       Emit(' AND EAX,0FFh');
      Greska(NEDOPARIT);                               then                                           if t2 = karakter then
    if (t1 = realni) or (t2 = realni)                  Greska(OCEKDOD);                                 Emit(' AND EBX,0FFh');
      then begin                                     if not (dod1) then                               Emit(' CMP EBX,EAX');
      t := realni;                                     Greska(NEDODJ);                             end;
      if t2 <> realni then                           Emit(' PUSH EBX');                            case z of
         CijeliNaFPStek('EAX', t2 =                  if (t1 = realni) then                            '=': Emit(' SETE AL');
           karakter);                                  Emit(' FSTP ST(0)');                           '>': Emit(' SETG AL');
      if t1 <> realni then                           Novi;                                            '<': Emit(' SETL AL');
         CPUStekCijeliNaFPStek(t1 =                  IzrazDodjeljivanja(t2, dod);                     '#': Emit(' SETNE AL');
           karakter)                                 if t2 = slog then                             end;
      else                                             duzdrugogsloga :=                           Emit(' AND EAX,0FFh');
         StekNaFPUStek;                                   DuzinaTipa(t2);                          t := cijeli;
      case z of                                      if ((t1 = slog) and (t2 <>                  end;
         '+': Emit(' FADD ');                          slog)) or                               end
         '-': Emit(' FSUBR ');                         ((t1 <> slog) and (t2 = slog))     end;
      else                                                then                          end;
         Greska(NEDOPFP);                              Greska(SLOGSLOGU);               procedure Uslov;
      end                                            if t1 = slog then begin            var
    end                                                if duzprvogsloga <>                sonda, sinace, skrajuslova: string;
    else begin                                            duzdrugogsloga then           begin
      case z of                                           Greska(SLOGRAZDUZ);             Novi;
         '+': begin                                    Emit(' POP EDI');                  IzrazDodjeljivanja(t, dod);
             Emit(' POP EBX');                         Emit(' MOV ESI,EBX');              if t <> cijeli then
             if (t1 = karakter) and (t2                Emit(' CLD');                         Greska(TIPUSL);
                = karakter) then begin                 Str(duzprvogsloga, st);            Emit(' CMP EAX,0');
                t := karakter;                         Emit(' MOV ECX,' + st);            NovaLabela(sonda);
                Emit(' ADD AL,BL');                  end                                  NovaLabela(sinace);
             end                                     else                                 NovaLabela(skrajuslova);
             else begin                                Emit(' POP EBX');                  Emit(' JNE L' + sonda);
                t := cijeli;                         if (t2 in [karakter, realni])        Emit(' JMP L' + sinace);
                if t1 = karakter then                  and                                IdiDo('{');
                  Emit(' AND EBX,0FFh');               (t1 in [pkarakter, pcijeli,        Emit('L' + sonda + ':');
                if t2 = karakter then                     prealni]) then                  Blok;
                  Emit(' AND EAX,0FFh');               Greska(DODJPOINT);                 Emit(' JMP L' + skrajuslova);
                Emit(' ADD EAX,EBX');                if (t1 = realni) and (t2 <>          Emit('L' + sinace + ':');
             end;                                      realni) then                       if Slijedi('inace', false) then begin
           end;                                        CijeliNaFPStek('EAX', t2 =            Novi;
         '-': begin                                       karakter);                         IdiDo('{');
             Emit(' MOV EBX,EAX');                   if (t1 <> realni) and (t2 =             Blok;
             Emit(' POP EAX');                         realni) then                       end;
             if (t1 = karakter) and (t2                FPStekUCijeli('EAX');              Emit('L' + skrajuslova + ':');
                = karakter) then begin               case t1 of                         end;
                t := karakter;                         karakter:
                Emit(' SUB AL,BL');                       Emit(' MOV [EBX],AL');        procedure Asembler;
             end                                       realni:                          begin
             else begin                                Emit(' FSTP QWORD PTR [EBX]');     repeat
                t := cijeli;                           slog: Emit(' REP MOVSB');            ReadLn(ulaz, linija);
                                                               73
     if linija <> '\' then                        paradresa := paradresa +                Emit('.486');
       Emit(linija);                                 ((DuzinaTipa(tip)-1)div 4+1)*4;      Emit('.MODEL FLAT,STDCALL');
     if eof(ulaz) then                            NoviIdent(ImeParametra,                 Emit('OPTION CASEMAP:NONE');
       linija := '\';                                DuzinaTipa(tip),                     Emit('EXTRN ExitProcess@4:NEAR');
  until linija[1] = '\';                             paradresa, pfunkc, parametar,        Emit('.CODE');
  pozicija := 1;                                       tip,                               Emit('ULAZ:');
  znak := linija[pozicija];                          pfunkc, parametara, p3);             Emit(' FINIT');
  IdiDo('\');                                   end;                                      Emit(' JMP GLAVNI');
end;                                            if znak <> ')' then                       pozicija := 0;
                                                  IdiDo(',');                             globadresa := 0;
procedure Petlja;                            end;                                         Novi;
var                                          IdiDo(')');                                  while SlijediDekTipa(tip) do begin
  sdok, skrajpetlje, suslov: string;         for i := ukupnoident downto 0 do                if Slijedi('funkcija', false) then
begin                                           if (TabIdent[i].nivo = pfunkc) and             begin
  Novi;                                           (TabIdent[i].vrsta=parametar)then            Novi;
  NovaLabela(suslov);                             TabIdent[i].adresa := paradresa +            DefFunkcija(tip);
  Emit('L' + suslov + ':');                          8 - TabIdent[i].adresa;                 end
  IzrazDodjeljivanja(t, dod);                TabIdent[pfunkc].pod1 := parametara;            else begin
  if t <> cijeli then                        case znak of                                      if (tip = slog) or (tip = pslog)
     Greska(TUSLPET);                           '{': begin                                       then
  Emit(' CMP EAX,0');                                IdiDo('{');                                 p3 := DeklaracijaSloga(0)
  NovaLabela(sdok);                                  while SlijediDekTipa(tip) do              else
  NovaLabela(skrajpetlje);                             begin                                     p3 := 0;
  Emit(' JNE L' + sdok);                               if (tip = slog) or (tip =               repeat
  Emit(' JMP L' + skrajpetlje);                           pslog) then                            DeklIdent(ImeVarijable, 0);
  IdiDo('{');                                             p3 :=                                  NoviIdent(ImeVarijable,
  Emit('L' + sdok + ':');                                   DeklaracijaSloga(pfunkc)                DuzinaTipa(tip),
  Blok;                                                else                                         globadresa, 0, globalna, tip,
  Emit(' JMP L' + suslov);                                p3 := 0;                                    0, 0, p3);
  Emit('L' + skrajpetlje + ':');                       repeat                                    globadresa := globadresa +
end;                                                      DeklIdent(ImeVarijable,                   DuzinaTipa(tip);
                                                            pfunkc);                             imaistogtipa := true;
procedure Blok;                                           lokadresa := lokadresa +               if znak = ',' then begin
begin                                                       DuzinaTipa(tip);                        Novi;
  while znak <> '}' do begin                              NoviIdent(ImeVarijable,                   imaistogtipa := false;
     if Slijedi('dok', false) then                          DuzinaTipa(tip),                     end;
       Petlja                                               -lokadresa, pfunkc,                until imaistogtipa;
     else if Slijedi('ako', false) then                        lokalna, tip,                   while (globadresa mod 4) <> 0 do
       Uslov                                                pfunkc, parametara, p3);             globadresa := globadresa + 1;
     else if Slijedi('asembler', false)                   imaistogtipa := true;                IdiDo(';');
       then                                               if znak = ',' then begin           end
       Asembler                                             Novi;                         end;
     else begin                                             imaistogtipa := false;        IdiDo('{');
       IzrazDodjeljivanja(t, dod);                        end;                            if znak <> '}' then begin
       IdiDo(';');                                     until imaistogtipa;                   Emit('GLAVNI:');
     end;                                              while (lokadresa mod 4)<>0do          Blok;
  end;                                                    lokadresa := lokadresa + 1;        Emit(' PUSH 0');
  IdiDo('}');                                          IdiDo(';');                           Emit(' CALL ExitProcess@4');
end;                                                 end;                                    Emit('.DATA');
procedure DefFunkcija(ftip: TTip);                   Str(paradresa, st);                     Str(globadresa, st);
var                                                  Emit(ImeFunkcije+'@'+st+':');           Emit('GLOBALV DB '+st+' DUP(0)');
  parametara, paradresa, lokadresa,                  Emit(' PUSH EBP');                      Emit('INTTOFP DD 0');
     pfunkc, i, p3: integer;                         Emit(' MOV EBP,ESP');                   Emit('END ULAZ')
  ImeFunkcije, imeparametra,                         Str(lokadresa, st);                  end
     imevarijable, st: string;                       Emit(' SUB ESP,' + st);              else begin
  tip: TTip;                                         Blok;                                   Emit('GLAVNI:');
  imaistogtipa: Boolean;                             Emit(' MOV ESP,EBP');                   Emit('END');
begin                                                Emit(' POP EBP');                    end;
  if not (((znak >= 'a') and (znak <=                Str(paradresa, st);                end;
     'z')) or                                        Emit(' RET ' + st);                procedure Glavni;
     ((znak >= 'A') and (znak <= 'Z')))              Emit('PUBLIC '+ImeFunkcije+        var
       then                                            '@' + st);                         linija: string;
     Greska(IMEFUN);                              end;                                  begin
  DeklIdent(ImeFunkcije, 0);                    ';': begin                                trenlabela := 0;
  NoviIdent(ImeFunkcije, 4, 0, 0,                    Str(paradresa, st);                  ukupnoident := 0;
     funkcija, ftip, 0, 0, 0);                       Emit('extrn ' + ImeFunkcije +        aktnivo := 0;
  pfunkc := ukupnoident;                               '@' + st + ':near');               ukupnoslogova := 0;
  aktnivo := pfunkc;                                 IdiDo(';');                          Assign(ulaz, paramstr(1));
  IdiDo('(');                                     end                                     Assign(izlaz, paramstr(2));
  parametara := 0;                           else                                         brojaclinija := 0;
  lokadresa := 0;                               Greska(DEFFUN);                           linija := '';
  paradresa := 0;                            end;                                         Reset(ulaz);
  while znak <> ')' do begin                 aktnivo := 0;                                Rewrite(izlaz);
     if SlijediDekTipa(tip) then begin     end;                                           Prevedi;
       if (tip = slog) or (tip = pslog)    procedure Prevedi;                             Close(ulaz);
          then                             var                                            Close(izlaz);
          p3 := DeklaracijaSloga(pfunkc)     globadresa, p3: Integer;                     WriteLn('Prevedeno bez greske');
       else                                  ImeVarijable, st: string;                  end;
          p3 := 0;                           tip: TTip;                                 begin
       DeklIdent(ImeParametra, pfunkc);      imaistogtipa: Boolean;                       Glavni
       parametara := parametara + 1;       begin                                        end.
                                                               74
11.PREDPROCESIRANJE I OPTIMIZACIJA KODA
          Došlo se do faze u kojoj se sam kompajler više neće mijenjati. Uoĉljivo je, meĊutim, da jeziku nedostaju predefinisani
tipovi, konstante te makronaredbe, odnosno ukljuĉivanje kompletnih datoteka izvornog koda, kako se iste sekvence koda ne bi
morale više puta kucati. Svi ovi problemi se mogu riješiti predprocesorom. Osim toga, već u prvoj verziji kompajlera je uoĉeno
da je generisani kôd prevelik, pa je potrebno pristupiti optimizaciji generisanog koda.


11.1.     Struktura kompajlera
         Predprocesor i postprocesor se nalaze u posebnim modulima (unit) i u suštini predstavljaju velika proširenja
dosadašnjih procedura Novi i Emit. Ove procedure su premještene iz glavnog modula u module predpr8.pas i postpr8.pas.
Posljednja verzija kompajlera nema oznaka izmjena u odnosu na prethodnu verziju


11.2.     Predprocesorska direktiva #definiraj
        Predprocesor je sliĉan predprocesoru iz jezika C. Ako se na poĉetku linije              nalazi znak #, to predstavlja
predprocesorsku direktivu. Tipiĉna sintaksa direktive #definiraj izgleda ovako:
#definiraj SIMBOL TekstSimbola
         U daljnjem radu prilikom obrade linije sve pojave navedenog simbola zamjenjuju se tekstom. Ako je tekst simbola
duţi od jedne linije, na njenom kraju se stavlja znak \.
         Primjer:
           #definiraj PI 3.14159265
           #definiraj PETLJA dok(i<2)\
             { i:=i+1;}
        U ovom primjeru je definisana konstanta PI i sada je u korisniĉkom programu moguće pisati a:=PI/2. Pored ovoga
navoĊenjem simbola PETLJA, zamjenjuje se cijela petlja navedena u njegovom tijelu.
         Definisanje konstanti predprocesorom rješava pitanje imena tipova. Tako se moţe navesti:
         #definiraj KOMPLEKSNI slog {realni x;realni i;}
         i dalje pisati
         KOMPLEKSNI a,b,c,d;
         Uz pomoć predprocesora, ĉak je moguće uvesti objekte sa jednim nivoom nasljeĊivanja. Na slici Sl. 11.2.1 se vidi
kako se uz pomoć predprocesora moţe, uz dosta discipline pri pisanju, postići sintaksa sliĉna sintaksi u objektno orijentisanim
jezicima, tj. “metode” (u suštini pointeri na funkcije) , “klase” (zapravo slogovi) i “nasljeĊivanje” (ponavljanje istih polja uz
pomoć predprocesora).
    #definiraj METODA cijeli *                             OBJEKT OTAC INSTANCE xxx;
    #definiraj OTAC cijeli p1,p2; METODA a;                OBJEKT SIN INSTANCE yyy;
    #definiraj SIN OTAC cijeli p3;                         {
    #definiraj OBJEKT slog {                                  xxx INIT
    #definiraj INSTANCE }                                     yyy INIT
    #definiraj INIT .a:=x;                                   xxx.p1:=2;
    cijeli funkcija x (cijeli a)                             yyy.p1:=3;
    { 1;                                                     yyy.p3:=3;
    ` tijelo metode                                          xxx.a(50);
    }                                                      }
                               Sl. 11.2.1.       Rudimentarno OOP uz pomoć predprocesora

11.3.     Direktive uslovnog kompajliranja
         U jeziku FILDZAN-32 omogućeno je da se odreĊeni dijelovi koda kompajliraju ako je neki simbol definisan (ili
nedefiniran) koristeći direktivu #definiraj. U protivnom, linije izvornog koda se ignorišu kao da su komentari. Direktive
uslovnog kompajliranja su #postoji, #nepostoji i #dalje.
   #postoji SIMBOL
         Ako je navedeni simbol ranije definisan, naredni dio programa će se prevoditi, a ako ne ignorisat će se. Ovo
ignorisanje će ići sve do direktive #dalje
  #nepostoji SIMBOL
        Ako navedeni simbol nije ranije definisan, naredni dio programa će se prevoditi, a ako je definisan ignorisat će se.
Ovo ignorisanje će ići sve do direktive #dalje
   #dalje
        Završava blok zapoĉet naredbama #postoji ili #nepostoji.
                                                               75



                      #definiraj WINDOWS 1
                      #postoji WINDOWS
                       MessageBox(0,”Poruka”,”Na ekranu”,0);
                      #dalje
                      #nepostoji WINDOWS
                      UpisiUDatoteku(”Poruka”);
                      #dalje

                                Sl. 11.3.1.       Upotreba direktiva #postoji i #nepostoji
       U primjeru sa slike Sl. 11.3.1 se, ako je definisan simbol WINDOWS, prikazuje poruka koristeći funkciju
MessageBox, a ako ne, poruka se upisuje u datoteku.


11.4.     Direktiva #dodaj za uključivanje datoteke
         Sintaksa naredbe za ukljuĉivanje kompletne datoteke sa izvornim kodom glasi:
            #dodaj ImeDatoteke
         Od mjesta u izvornom kodu programa neposredno iza direktive #dodaj se ukljuĉuje kompletna datoteka i sada se
generiše asemblerski kôd iz te datoteke, sve dok se ona ne iscrpi. Nakon toga se nastavlja kompajliranje glavne datoteke. Nije
dopušteno gnijeţĊenje datoteka
         Primjer:
            #dodaj osnovniprozor.h

11.5.     Realizacija predprocesora
          Realizacija predprocesora nije pretjerano sloţena. Treba definisati bafer od (npr.) 200 K u kome će stojati stringovi
koji predstavljaju vrijednost koja se stavlja i niz definicija koje sadrţe imena simbola te poziciju u ovom baferu gdje se nalazi
dati string.
         Procedura Novi sada izgleda nešto drugaĉije nego u sedmoj verziji kompajlera. Kako se direktivom #dodaj moţe
preusmjeriti na drugu ulaznu datoteku, provjerava se koja je ulazna datoteka u pitanju i ReadLn obavlja iz nje. Nakon
instrukcije ReadLn se poziva rutina Predprocesiraj. U okviru ove rutine se provjerava da li linija poĉinje predprocesorskom
direktivom.
         Najviše posla ima ako se prepozna direktiva #definiraj. Ona je implementirana u proceduri PpDefin i najprije rastavi
ime simbola od njegove vrijednosti. Definisanje simbola se vrši njegovim dodavanjem u tabelu simbola, a njegova definicija se
dodaje u bafer opisa simbola simbola.
         Direktive #postoji i #nepostoji (implementirane u procedurama PpPostoji i PpNePostoji) provjeravaju prisustvo
navedenog simbola u tabeli i tako postave varijablu ObradaLinije na true ili false. U rutini Predprocesiraj se ova varijabla
provjeri i ako je jednaka false, linija teksta se proglašava praznom. Direktiva #dalje (implementirana u Predprocesiraj)
postavlja tu varijablu na true. Direktiva #dodaj (implementirana u Predprocesiraj) otvara pomoćnu datoteku i preusmjerava
ĉitanje na nju.
         U drugom dijelu rutine Predprocesiraj se proĊe kroz cijelu tabelu predprocesorskih simbola i koristeći paskalsku
funkciju Pos pretraţuje pojava danih simbola u ulaznoj liniji. Ako ih ima, simbol na tom mjesto u izvornom kodu se
zamjenjuje kompletnim stringom koji se nalazi u definiciji. Ako definicija simbola sadrţi drugi simbol, ova će petlja
ekspandovati i njega.
        Rutina se zasniva na ĉinjenici da stringovi u 32-bitnim implementacijama Pascala mogu biti veoma dugaĉki.
Eventualno portiranje kompajlera u drugi programski jezik treba imati tu ĉinjenicu u vidu.
         Jezik FILDZAN-32 je završen, ukljuĉujući i predprocesor. U prilogu 9 dat je izvorni kôd predprocesora .


11.6.     Optimizacija koda

        Gledano makroskopski, ovaj kompajler generiše veoma kratak kôd. U usporedbi sa bilo kojim kompajlerom viših
programskih jezika za Windows, koji u izvršni kôd ukljuĉuju velike biblioteke, manje od 3 Kb za prazan program izgleda
skoro kao rekord. Razlog ovome je što FILDZAN-32 generiše vrlo mali startni kôd.
         Ali, posmatrajući pojedinaĉne naredbe, kako su prevedene, uviĊa se da ima jako mnogo nepotrebnih asemblerskih
instrukcija. Razlog ovome je što kompajler kada prevodi aritmetiĉke izraze prilikom nailaska na operator ne zna unaprijed da li
                                                               76
će slijediti konstanta, varijabla ili kompletan izraz, pa se priprema za najgori sluĉaj. To rezultuje vrlo ĉestim stavljanjem
podataka na stek, ili pomoćne registre. Za primjer se moţe uzeti prevoĊenje proste instrukcije n:=n+1; Ona se prevodi u
;           n:=n+1;
    LEA EBX,GLOBALV[400]
    MOV EAX,[EBX]
    PUSH EBX
    LEA EBX,GLOBALV[400]
    MOV EAX,[EBX]
    PUSH EAX
    MOV EAX,1
    POP EBX
    ADD EAX,EBX
    POP EBX
    MOV [EBX],EAX

          dok je najkraći mogući kôd
;          n:=n+1;
    INC GLOBALV[400]


        Uklanjanje nepotrebnih instrukcija se moţe izvesti modifikacijom procedure Emit. Umjesto da se generisana
asemblerska naredba odmah šalje u izlaznu datoteku, ona se najprije stavlja u bafer od 15 instrukcija. Kada se ovaj bafer
popuni, prvo se traţi nekoliko karakteristiĉnih uzoraka sekvenci asemblerskih naredbi i one se pokušavaju zamijeniti kraćim
sekvencama. Ako to ne uspije, naredba koja je najranije ušla u bafer se šalje u izlaznu datoteku i stvara se mjesto za novu
naredbu u baferu. Ovo se zove peephole optimizacija. Prepozna li se pseudo instrukcija .END, optimizacija se izvede još
jednom i pošalju se u datoteku sve instrukcije iz bafera.
        Prepoznavanje uzoraka je sloţen problem. Sekvenca koja je na procesoru 386 brţa, moţe biti sporija na procesoru
Pentium IV od neke druge sekvence. Ovaj zadatak priliĉno usporava kompajler, pa će se realizovati optimizovanje samo
nekoliko najĉešćih uzoraka.
         Uzorci se sastoje od više instrukcija, a one mogu da sadrţe parametre. Parametri se oznaĉavaju sa $C1, $C2 za
proizvoljne literale, ili sa $N1, $N2 za brojeve. Stoga se se uzorci ne mogu prepoznavati prostim poreĊenjem, nego je potrebna
odgovarajuća funkcija. Ta funkcija se zove Uzorak i ima ĉetiri string parametra: string koji se traţi, stvarna vrijednost,
varijable u koje vraćamo vrijednosti prvog i drugog $ parametra u uzorku. Primjer
       uzorak(„ MOV EAX,$C1‟,‟ MOV EAX,ECX‟,v1,v2) će vratiti true, jer su uzorci sliĉni, u varijabli v1 se dobija string
„ECX‟ dok v2 dobija prazan string.
          Funkcija uzorak poredi uzorke algoritmom sa slike Sl. 11.6.1.

                Ako su traženi i stvarni string jednaki, odmah se vrati s tačnom vrijednošću
                Postavi pokazivače na početak traženog i stvarnog stringa
                Izvršavaj petlju do kraja traženog stringa
                Ako se u traženom stringu na datom mjestu nalazi simbol $, uvećaj pokazivač u
    traženom stringu za 1, provjeri da li slijede simboli C ili N, a iza njih simboli 1 ili 2, oba puta
    uvećavajući pokazivač u traženom stringu. Ukoliko se prepoznaju sekvence $C1, $C2, $N1 ili $N2
    treba ih specijalno obraditi. Specijalna obrada nadovezuje redom znakove stvarnog stringa, stalno
    uvećavajući njegov pokazivač, na prvu ili drugu izlaznu varijablu sve dok se ne doĎe do kraja
    stvarnog stringa, znaka zarez, a za numeričke konstante i prvog nenumeričkog znaka.

                Ako su znakovi na trenutnoj poziciji u traženom i stvarnom stringu različiti, izaĎi iz
    funkcije s netačnim rezultatom.
                Uvećaj za jedan pokazivače traženog i stvarnog stringa.
                Na kraju petlje izaĎi iz funkcije sa tačnim rezultatom

                                       Sl. 11.6.1.      Algoritam pretraživanja uzorka
          Obrada sluĉajeva za $C i $N sekvence realizovana je u procedurama KarakterSl i BrojSl.
                                                                                77



ADD $C1,$C2   Ako bilo koji od $C1 ili $C2 sadrţi EAX ili EBX, koristi ih.

              Ako je $C1 jednak ESP relativna promjena ESP je $C2

AND $C1,$C2   Ako bilo koji od $C1 ili $C2 sadrţi EAX ili EBX, koristi ih.

CALL $C1      Pretpostavlja se da briše EAX, EBX i koristi FPU

CDQ           Koristi EAX

CLD           Irelevantna

CMP $C1,$C2   Ako bilo koji od $C1 ili $C2 sadrţi EAX ili EBX, koristi ih.

FADD          Koristi FPU

FCHS          Koristi FPU

FCOMPP        Koristi FPU

FDIVR         Koristi FPU

FILD $C1      Koristi FPU

FINIT         Koristi FPU

FISTP $C1     Koristi FPU

FLD $C1       Koristi FPU

FMUL          Koristi FPU

FSTP $C1      Koristi FPU

FSTSW AX      Koristi FPU, briše EAX

FSUBR         Koristi FPU

IDIV $C1      Koristi EAX, ako je $C1 jednak EBX, koristi i EBX

IMUL $C1      Koristi EAX, ako je $C1 jednak EBX, koristi i EBX

JMP $C1       Pretpostavlja se da briše EAX, EBX i koristi FPU

JNE $C1       Pretpostavlja se da briše EAX, EBX i koristi FPU

LEA $C1,$C2   Ako je $C1 jednak EAX (AL) ili EBX (BL), briše ih. Ako $C2 sadrţi EAX ili EBX, koristi ih.

MOV $C1,$C2   Ako je $C1 jednak EAX (AL) ili EBX (BL), briše ih. Ako $C2 sadrţi EAX ili EBX, koristi ih. Ako $C1 sadrţi EAX ili EBX, a nije
              jednak njima koristi ih.

MUL $C1       Koristi EAX, ako je $C1 jednak EBX, koristi i EBX

NEG $C1       Ako $C1 sadrţi EAX ili EBX, koristi ih.

NOT $C1       Ako $C1 sadrţi EAX ili EBX, koristi ih.

OR $C1,$C2    Ako bilo koji od $C1 ili $C2 sadrţi EAX ili EBX, koristi ih.

POP $C1       Ako je $C1 jednak EAX ili EBX, briše ih. Relativna promjena ESP je -4

PUSH $C1      Ako $C1 sadrţi EAX ili EBX, koristi ih. Relativna promjena ESP je –4

REP MOVSB     Irelevantna

RET $N1       Relativna promjena ESP je $N1+4

SAHF          Koristi EAX

SAL EAX,$N1   Koristi EAX

SETA AL       Briše EAX

SETB AL       Briše EAX

SETE AL       Briše EAX

SETG AL       Briše EAX

SETL AL       Briše EAX

SETNE AL      Briše EAX

SUB $C1,$C2   Ako bilo koji od $C1 ili $C2 sadrţi EAX ili EBX, koristi ih.

XOR $C1,$C2   Ako bilo koji od $C1 ili $C2 sadrţi EAX ili EBX, koristi ih.

                              Sl. 11.6.2.               Efekti pojedinih instrukcija relevantni za optimizaciju
                                                               78
        Da bi se znalo koje instrukcije iz peephole bafera je moguće izbaciti treba aţurirati sljedeće indikatore:
        -   Da li grupa instrukcija mijenja EAX prije nego ga ĉita
        -   Da li grupa instrukcija uopšte ĉita EAX
        -   Da li grupa instrukcija mijenja EBX prije nego ga ĉita
        -   Da li grupa instrukcija uopšte ĉita EBX
        -   Da li grupa instrukcija koristi floating point instrukcije
        -   Na kojoj se poziciji nalazi ESP registar u odnosu na poĉetak grupe instrukcija
        Procedura obradistanje za svaku od instrukcija koja joj se proslijedi aţurira navedenih šest indikatora.
        Instrukcije koje su korištene za generisanje koda se mogu smjestiti u tabelu na slici Sl. 11.6.2 po njihovom ponašanju:


        Optimizacijska pravila implementirana u osmoj verziji kompajlera su:
        1) Sekvenca PUSH EAX / instrukcije koje ne mijenjaju EAX / POP EAX povlaĉi izbacivanje PUSH EAX i
           POP EAX instrukcija. Unutar ove sekvence ESP mora biti na istom nivou, dakle sekvenca mora imati jednak
           broj PUSH i POP instrukcija. Dualno pravilo se primjenjuje ako se zamijene EAX i EBX.
        2) Sekvenca PUSH EAX / instrukcije koje ne mijenjaju EBX / POP EBX povlaĉi izbacivanje POP EBX i
           zamjenu PUSH EAX instrukcije instrukcijom MOV EBX,EAX. Unutar ove sekvence ESP mora biti na istom
           nivou, dakle sekvenca mora imati jednak broj PUSH i POP instrukcija. Dualno pravilo se primjenjuje ako se
           zamijene EAX i EBX.
        3) Sekvenca LEA EBX,adresa / PUSH EBX / instrukcije koje ne mijenjaju EBX / POP EBX povlaĉi
           izbacivanje LEA EBX,adresa i PUSH EBX te zamjenu POP EBX instrukcije instrukcijom LEA EBX,adresa.
           Unutar ove sekvence ESP mora biti na istom nivou, dakle sekvenca mora imati jednak broj PUSH i POP
           instrukcija
        4) Ako nakon instrukcije LEA EBX,adresa slijedi instrukcija koja briše EBX prije instrukcije koja ga koristi,
           instrukcija LEA EBX, adresa se moţe obrisati.
        5) Ako nakon instrukcije MOV EAX,adresa slijedi instrukcija koja briše EAX prije instrukcije koja ga koristi,
           instrukcija MOV EAX, adresa se moţe obrisati. Dualno pravilo se primjenjuje ako se zamijene EAX i EBX.
        6) Ako iza instrukcije FLD slijedi sekvenca instrukcija koje ne koriste FPU a nakon njih instrukcija FSTP ST(0)
           (odbacivanje podatka) instrukcije FLD i FSTP ST(0) se mogu obrisati.
        7) U sekvenci ADD ESP,-8 / FSTP QWORD PTR [ESP] / Instrukcije koje ne koriste FPU/ FLD QWORD
           PTR [ESP] / ADD ESP,8 sve ĉetiri instrukcije koje uokviruju ostale instrukcije se mogu brisati.
        8) Instrukcije koje nemaju efekta kao što su MOV EAX,EAX ; MOV EBX,EBX ;ADD EAX,0 ili ADD EBX,0 se
           mogu brisati
        9) Ako su dvije uzastopne iste MOV instrukcije , jedna se moţe brisati
        10) Ako iza MOV registar,konst slijedi ADD registar,konst ovo se moţe svesti na jednu MOV instrukciju koja
            dodjeljuje implicitni zbir
        11) Ako iza instrukcije MOV registar,konst slijedi NEG registar, to se moţe zamijeniti sa MOV registar,-konst.
            Ovim je riješen problem unarnog minusa koji je u nekim jezicima sastavni dio konstante.
        12) Ako su dvije uzastopne iste ADD instrukcije , mogu se svesti na jednu sa implicitnim zbirom
        13) Sekvence tipa MOV reg1,reg2 / ADD reg3,reg1 / MOV reg1,reg3 se mijenjaju sekvencama ADD reg3,reg2 /
            MOV reg1,reg3. Umjesto registara ovdje se mogu javljati i memorijske lokacije, a pored ADD instrukcije ista
            sekvenca je moguća i sa instrukcijama AND, SUB, MOV, OR, XOR.
        14) Sekvence tipa PUSH reg1 / MOV reg2,reg3 / MOV reg1,reg4 / POP reg4 znaĉe da se reg1 i reg4 mogu
            obrisati. Ova sekvenca se javlja kao rezultat drugih optimizacija.


        Procedura Optimizuj, koja se poziva iz procedure Emit provjerava sve ove sluĉajeve i izbacuje odnosno zamjenjuje
nepotrebne instrukcije.
         Ovih 14 jednostavnih pravila skraćuju asemblerski generisani program za oko 30 %. Realizacija samog optimizatora
je nešto usloţnjena kako bi pretraţivanje išlo brţe. UvoĊenje optimizacije usporava proces kompajliranja. Sedma verzija
kompajlera je prevodila prethodni primjer na Pentium-u 100 za 0,2 s, dok osmoj verziji za isti zadatak treba oko 2,5 s.
                                                                79
11.7.     Testni primjer optimizacije
          Kao testni primjer uzet je program predstavljen u prvoj koloni slike Sl. 11.7.1 :
               cijeli a;
               {
                 a:=2;
                 a:=a+a+1;
               }


Izvorni          Neoptimizirani kôd          Uoĉene redundante                Optimizovani kôd iz 8. verzije
kôd              iz 7. Verzije               sekvence
                 kompajlera
cijeli a;        .486                        Nepotrebno MOV EAX               .486
{                .MODEL FLAT,STDCALL         13 MOV EAX,[EBX]                 .MODEL FLAT,STDCALL
   a:=2;         OPTION CASEMAP:NONE         14 PUSH EBX                      OPTION CASEMAP:NONE
   a:=a+a+1;     EXTRN ExitProcess@4:NEAR    15 MOV EAX,2                     EXTRN ExitProcess@4:NEAR
}                .CODE                       Nepotrebno LEA/PUSH/POP          .CODE
                 ULAZ:                       12 LEA EBX,GLOBALV[0]            ULAZ:
                   FINIT                     13 PUSH EBX                        FINIT
                   JMP GLAVNI                14 MOV EAX,2                       JMP GLAVNI
                 ;cijeli a;                  15 POP EBX                       ;
                 ;{                          Nasao nepotrebno LEA             ;cijeli a;
                 ;    a:=2;                  12 LEA EBX,GLOBALV[0]            ;{
                 GLAVNI:                     13 MOV [EBX],EAX                 ;    a:=2;
                   LEA EBX,GLOBALV[0]        14;   a:=a+a+1;                  GLAVNI:
                   MOV EAX,[EBX]             15 LEA EBX,GLOBALV[0]              MOV EAX,2
                   PUSH EBX                   Nepotrebno MOV EAX                MOV DWORD PTR GLOBALV[0],EAX
                   MOV EAX,2                 12 MOV EAX,[EBX]                 ;    a:=a+a+1;
                   POP EBX                   13 PUSH EBX                        MOV EBX,DWORD PTR GLOBALV[0]
                   MOV [EBX],EAX             14 LEA EBX,GLOBALV[0]              MOV EAX,DWORD PTR GLOBALV[0]
                 ;    a:=a+a+1;              15 MOV EAX,[EBX]                   ADD EAX,EBX
                   LEA EBX,GLOBALV[0]        Nasao nepotrebno LEA               MOV EBX,EAX
                   MOV EAX,[EBX]             12 LEA EBX,GLOBALV[0]              MOV EAX,1
                   PUSH EBX                  13 MOV EAX,[EBX]                   ADD EAX,EBX
                   LEA EBX,GLOBALV[0]        14 PUSH EAX                        MOV DWORD PTR GLOBALV[0],EAX
                   MOV EAX,[EBX]             15 LEA EBX,GLOBALV[0]            ;}
                   PUSH EAX                  Nasao nepotrebno LEA             ;}
                   LEA EBX,GLOBALV[0]        13 LEA EBX,GLOBALV[0]              PUSH 0
                   MOV EAX,[EBX]             14 MOV EAX,[EBX]                   CALL ExitProcess@4
                   POP EBX                   15 POP EBX                       .DATA
                   ADD EAX,EBX               Nepotrebno PUSH /POP EBX         GLOBALV DB 4 DUP(0)
                   PUSH EAX                  12 PUSH EAX                      INTTOFP DD 0
                   MOV EAX,1                 13 MOV EAX,DWORD PTR             END ULAZ
                   POP EBX                   GLOBALV[0]
                   ADD EAX,EBX               14 POP EBX                                Optimalni kôd
                   POP EBX                   Nepotrebna trojka
                   MOV [EBX],EAX             11 MOV EAX,DWORD PTR
                 ;}                          GLOBALV[0]                       .486
                 ;}                          12 MOV EBX,EAX                   .MODEL FLAT,STDCALL
                   PUSH 0                    13 MOV EAX,DWORD PTR             OPTION CASEMAP:NONE
                   CALL ExitProcess@4        GLOBALV[0]                       EXTRN ExitProcess@4:NEAR
                 .DATA                       Nepotrebno PUSH /POP EBX         .CODE
                 GLOBALV DB 4 DUP(0)         13 PUSH EAX                      ULAZ:
                 INTTOFP DD 0                14 MOV EAX,1                        JMP GLAVNI
                 END ULAZ                    15 POP EBX                       ;
                                             Nepotrebno LEA/PUSH/POP          ;cijeli a;
                                             7 LEA EBX,GLOBALV[0]             ;{
                                             8 PUSH EBX                       ;    a:=2;
                                             9 MOV EBX,DWORD PTR              GLAVNI:
                                             GLOBALV[0]                         MOV DWORD PTR GLOBALV[0],2
                                             10 MOV EAX,DWORD PTR             ;    a:=a+a+1;
                                             GLOBALV[0]                         MOV EAX,DWORD PTR GLOBALV[0]
                                             11 ADD EAX,EBX                     ADD EAX,DWORD PTR GLOBALV[0]
                                             12 MOV EBX,EAX                     INC EAX
                                             13 MOV EAX,1                       MOV DWORD PTR GLOBALV[0],EAX
                                             14 ADD EAX,EBX                   ;}
                                             15 POP EBX                       ;}
                                             Nasao nepotrebno LEA               PUSH 0
                                             10 LEA EBX,GLOBALV[0]              CALL ExitProcess@4
                                             11 MOV [EBX],EAX                 .DATA
                                             12;}                             GLOBALV DB 4 DUP(0)
                                             13;}                             INTTOFP DD 0
                                             14 PUSH 0                        END ULAZ
                                             15 CALL ExitProcess@4
                                             Prevedeno bez greske
                                           Sl. 11.7.1.       Primjer rada optimizatora
        Kada ne bi bilo optimizacije, (kao u verziji 7 kompajlera) prevedeni kôd bi izgledao kao u drugoj koloni. U
kompajleru je ukljuĉeno da prikazuje sekvence koje pronalazi optimizator nakon zakljuĉka da se one mogu zamijeniti kraćim
sekvencama. U trećoj koloni se vidi da je optimizator djelovao ukupno 11 puta u ovako malom programu.
                                                               80
         Rezultat optimizacije je dat u gornjem dijelu ĉetvrte kolone na slici Sl. 11.7.1. Ovo još nije najbolji kôd koji se moţe
generisati. Uz povećanje broja pravila (što u ovom radu nije uĉinjeno) moţe se pribliţiti optimalnom kodu iz donjeg dijela
ĉetvrte kolone.
           I na većim programima uoĉavaju se uštede od oko 30%-40%, iako je implementirano priliĉno malo optimizacijskih
pravila.



11.8.      Rezime poglavlja
         Predprocesor omogućava zamjenu dijelova koda konstantama, ukljuĉivanje ĉitavih listinga izvornog koda, te uslovno
kompajliranje. Predprocesor je baziran na baferu u kome se ĉuvaju definicije zamjenskih simbola. Promijenjene su procedure
Novi i Emit i projekt organizovan u tri modula. Optimizator radi na principu zadrške nekoliko instrukcija i traţenja
karakteristiĉnih sekvenci koje se zamjenjuju kraćim sekvencama. Pri izboru sekvenci prati se upotreba registara EAX, EBX,
ESP i FP steka.
           Ovim je razvoj jezika, na nivou ovog rada, završen. Sada treba isprobati nekoliko primjera iz realnog svijeta.
                                                              81
12. TESTNI PRIMJERI
         Nakon realizacije posljednje verzije kompajlera slijedi njegovo testiranje. Kompajler je isproban na aplikacijama iz
realnog svijeta, iz raznih oblasti primjene.


12.1.    Primjer: Baze podataka i korisnički interfejs
         Pošto su baze podataka uz igre, obradu teksta i sistemski softver najpopularnija kategorija softvera, završni primjer
programa u jeziku FILDZAN-32 je mala baza podataka u Accessovom MDB formatu kojoj se pristupa koristeći SQL i ODBC.
Ne bi bilo bitne razlike ni da je u pitanju MS SQL Server ili Oracle RDBMS. Sastoji se od jedne tabele koja predstavlja
telefonski imenik. Imenik se moţe pretraţivati, a u njega se mogu unositi podaci. Polja u tabeli IMENIK su
        IME CHAR(20), PREZIME CHAR(20), ADRESA CHAR(20), TELEFON CHAR(20)
        Ovaj database primjer koristi, pored Windows API funkcija navedenih u prethodnom poglavlju i mnoge API funkcije
iz oblasti ODBC-a. Konekcija sa ODBC sistemom se uspostavlja koristeći SQLAllocEnv, za pripremu okruţenja,
SQLAllocConnect za rezervisanje prostora u memoriji za konekciju, SQLDriverConnect koji zaista vrši konekciju sa datim
sistemom za upravljanje bazom podataka. Prostor u memoriji za naredbu se rezerviše koristeći SQLAllocStmt, a oslobaĊa
                                                     koristeći SQLFreeStmt.
                                                                SQL Naredba se izvršava peko funkcije SQLExecDirect.
                                                        Ako ona vraća podatke, slog se preuzima koristeći SQLFetch, a
                                                        odgovarajuće polje se dobije funkcijom SQLGetData. Konekcija se
                                                        prekida   sa   SQLDisconnect        a   memorija oslobaĊa    sa
                                                        SQLFreeConnect.
                                                        Na slici se vidi prozor sa formularom za pretraţivanje i unošenje
                                                        navedene baze podataka. Na njemu se nalaze ĉetiri labele, ĉetiri editna
                                                        polja i tri tastera.
                                                        Obrada poruka koje generišu ovi tasteri se vrši na standardan naĉin,
                                                        kao u primjeru iz prethodnog poglavlja




                             Sl. 12.1.1.       Izgled ekrana demonstracione ODBC aplikacije
Kompajliranje i linkovanje ovog primjera zahtijeva još jednu dodatnu biblioteku prilikom linkovanja.
komp32v7 odbc.jez odbc.asm
ml /c /coff /Fl odbc.asm
link /defaultlib: user32.lib kernel32.lib gdi32.lib odbc.lib /subsystem:windows odbc.obj

        Datoteke odbc.jez i odbc.h sa finalnim primjerima date su na slikama Sl. 12.1.2 i Sl. 12.1.3.
                                                             82
#dodaj odbc.h                                                          SetWindowTextA(prazna,ka);
cijeli funkcija Konekcija()                                            SetWindowTextA(prazna,kb);
{                                                                      SetWindowTextA(prazna,kc);
  cijeli velicina,rez;                                                 SetWindowTextA(prazna,kd);
  karakter [2000] punistring;                                      }
  rez:=SQLAllocEnv(&ehan);
                                                              cijeli funkcija WndProc(cijeli lParam,cijeli wParam,cijeli
   rez:=SQLAllocConnect(&chan,ehan);                          wMessage,cijeli hWnd)
   rez:=SQLDriverConnect(0,&velicina, 1900, punistring,         { cijeli obradjena;
     70,"DRIVER={Microsoft Access Driver                            obradjena:=0;
(*.mdb)};DBQ=test.mdb",hWnd,chan);                                  ako (wMessage=1) `WM_CREATE
   rez:=SQLAllocStmt(&shan,chan);                                     {
}                                                             ka:=CreateWindowExA(0,hInstance,0,hWnd,20,120,20,140,
cijeli funkcija Diskonekcija()                                 UOKVIRENO,0,"EDIT",0);
{ cijeli rez;                                                 kb:=CreateWindowExA(0,hInstance,0,hWnd,20,120,60,140,
   rez:=SQLFreeStmt(0,shan);                                   UOKVIRENO,0,"EDIT",0);
   rez:=SQLDisconnect(chan);                                  kc:=CreateWindowExA(0,hInstance,0,hWnd,20,120,100,140,
   rez:=SQLFreeConnect(chan);                                 UOKVIRENO,0,"EDIT",0);
}                                                             kd:=CreateWindowExA(0,hInstance,0,hWnd,20,120,140,140,
cijeli funkcija Insert()                                      UOKVIRENO,0,"EDIT",0);
{ karakter [500] komanda;                                     ke:=CreateWindowExA(0,hInstance,0,hWnd,20,120,180,140,
   karakter * kk;                                             UOKVIRENO,"Nadji","BUTTON",0);
   karakter [30] polje;                                       kf:=CreateWindowExA(0,hInstance,0,hWnd,20,120,220,140,
   karakter [2] navodnik;                                     UOKVIRENO,"Unesi","BUTTON",0);
   cijeli rez;                                                kk:=CreateWindowExA(0,hInstance,0,hWnd,20,120,260,140,
   navodnik [0]:=39;navodnik[1]:=0;                           UOKVIRENO,"Prazna forma","BUTTON",0);
   komanda[0]:=0;                                             kg:=CreateWindowExA (0,hInstance,0,hWnd,20,120,20,10,
   lstrcat(                                                    UOKVIRENO,"Ime ","STATIC",0);
"INSERT INTO IMENIK(IME,PREZIME,ADRESA,TELEFON) VALUES("      kh:=CreateWindowExA (0,hInstance,0,hWnd,20,120,60,10,
,komanda);                                                     UOKVIRENO,"Prezime ","STATIC",0);
   GetWindowTextA(30,polje,ka);                               ki:=CreateWindowExA(0,hInstance,0,hWnd,20,120,100,10,
   NAV;POLJE;NAV;ZAREZ;                                        UOKVIRENO,"Adresa ","STATIC",0);
   GetWindowTextA(30,polje,kb);                               kj:=CreateWindowExA(0,hInstance,0,hWnd,20,120,140,10,
   NAV;POLJE;NAV;ZAREZ;                                        UOKVIRENO,"Telefon ","STATIC",0);
   GetWindowTextA(30,polje,kc);                                   obradjena:=1;
   NAV;POLJE;NAV;ZAREZ;                                               }
   GetWindowTextA(30,polje,kd);                                     ako (wMessage=2) `WM_QUIT
   NAV;POLJE;NAV;                                                     {PostQuitMessage (0) ; obradjena:=1; }
   lstrcat(")",komanda);                                           ako (wMessage=273) `WM_COMMAND
   ako (lstrlenA(polje)>4)                                            {
   {                                                                     ako (lParam=ke)
     Konekcija();                                                          { Select(); }
     rez:=SQLExecDirect(lstrlenA(komanda),komanda,shan);                 ako (lParam=kf)
     Diskonekcija();                                                       { Insert(); }
   }                                                                     ako (lParam=kk)
   inace { MessageBoxA(0,"Greska","Kratak broj",0);}                       { PraznaForma(); }
}                                                                        obradjena:=1;
cijeli funkcija Select()                                              }
{ karakter[500] komanda;                                            ako (obradjena=0)
   karakter [2] navodnik;                                             { DefWindowProcA lParam,wParam,wMessage,hWnd); }
   karakter [30] polje;                                         }
   cijeli rez,indikator;
   navodnik [0]:=39;navodnik[1]:=0;                            {
   komanda[0]:=0;                                                 nCmdShow:=10;
   lstrcat(                                                       hInstance:=GetModuleHandleA (0);
"SELECT IME,PREZIME,ADRESA,TELEFON FROM IMENIK WHERE 1=1 "        wndclass.cbsize:=48;
,komanda);                                                        wndclass.style := 0 ;
   GetWindowTextA(30,polje,ka);                                   wndclass.lpfnWndProc := WndProc ;
   ako (lstrlenA(polje))>1 { lstrcat(                             wndclass.cbClsExtra := 0 ;
" AND IME=",komanda);NAV;POLJE;NAV; }                             wndclass.cbWndExtra := 0 ;
   GetWindowTextA(30,polje,kb);                                   wndclass.hInstance := hInstance ;
   ako (lstrlenA(polje))>1 { lstrcat(                             wndclass.hIcon := 0 ;
" AND PREZIME=",komanda);NAV;POLJE;NAV; }                         wndclass.hCursor     := LoadCursorA (32512,0) ;
   GetWindowTextA(30,polje,kc);                                   wndclass.hbrBackground := GetStockObject(3);
   ako (lstrlenA(polje))>1 { lstrcat(                             wndclass.lpszMenuName    := 0;
" AND ADRESA=",komanda);NAV;POLJE;NAV; }                          wndclass.lpszClassName := "PROBNA" ;
   GetWindowTextA(30,polje,kd);                                   wndclass.hIconSm:=0;
   ako (lstrlenA(polje))>1 { lstrcat(                             ako (!(RegisterClassExA (&wndclass)))
" AND TELEFON=",komanda);NAV;POLJE;NAV; }                           { 0 ; }
   Konekcija();                                                   inace
   rez:=SQLExecDirect(lstrlenA(komanda),komanda,shan);              {
   rez:=SQLFetch(shan);                                               hWnd := CreateWindowExA ( 0,hInstance,0,0,
  rez:=SQLGetData(&indikator,30,polje,SQLCHAR,1,shan);                  400,400,4,4,13565952,
   SetWindowTextA(polje,ka);                                  "ODBC Database Demo","PROBNA",512);
  rez:=SQLGetData(&indikator,30,polje,SQLCHAR,2,shan);                ShowWindow ( nCmdShow,hWnd) ;
   SetWindowTextA(polje,kb);                                          UpdateWindow(hWnd) ;
  rez:=SQLGetData(&indikator,30,polje,SQLCHAR,3,shan);                dok (GetMessageA (0, 0, 0,&msg))
   SetWindowTextA(polje,kc);                                             {
  rez:=SQLGetData(&indikator,30,polje,SQLCHAR,4,shan);                     TranslateMessage (&msg) ;
   SetWindowTextA(polje,kd);                                               DispatchMessageA (&msg) ;
   Diskonekcija();                                                       }
}                                                                     msg.wParam ;
cijeli funkcija PraznaForma()                                       }
   { karakter [1] prazna;                                       }
     prazna[0]:=0;

                                            Sl. 12.1.2.        Datoteka ODBC.JEZ
                                                               83
cijeli funkcija RegisterClassExA(cijeli * wndclass);               cijeli * TargetValue,cijeli TargetType,cijeli
cijeli funkcija ShowWindow ( cijeli a,cijeli b) ;                ColumnNumber,
cijeli funkcija UpdateWindow(cijeli hWnd) ;                        cijeli StatementHandle);
cijeli funkcija GetMessageA (cijeli a, cijeli b, cijeli          cijeli hWnd ;
c,cijeli * d);                                                   slog
cijeli funkcija TranslateMessage (cijeli * d) ;                    {
cijeli funkcija DispatchMessageA (cijeli * d) ;                       cijeli hwnd;
cijeli funkcija CreateWindowExA(cijeli a,cijeli b,cijeli c,           cijeli message;
 cijeli d,cijeli e,cijeli f,cijeli g,cijeli h,cijeli i,               cijeli wParam;
 karakter * j,karakter * k,cijeli l);                                 cijeli lParam;
cijeli funkcija LoadCursorA ( cijeli a,cijeli b) ;                    cijeli time;
cijeli funkcija GetStockObject ( cijeli a) ;                          slog
cijeli funkcija PostQuitMessage ( cijeli a) ;                           {
cijeli funkcija DefWindowProcA (cijeli a, cijeli b, cijeli                 cijeli x;
c,cijeli d);                                                               cijeli y;
cijeli funkcija MessageBoxA (cijeli a, karakter * b,                    } pt;
karakter * c,cijeli d);                                            } msg ;         ` a message structure
cijeli funkcija GetModuleHandleA ( cijeli a) ;
cijeli funkcija lstrcat ( karakter * a,karakter * b) ;           slog
cijeli funkcija GetWindowTextA (cijeli a, karakter *               {
b,cijeli c);                                                          cijeli cbsize;
cijeli funkcija SetWindowTextA (karakter * b,cijeli c);               cijeli   style;
                                                                      cijeli * lpfnWndProc;
cijeli funkcija SQLAllocEnv(cijeli * EnvironHandle);                  cijeli   cbClsExtra;
cijeli funkcija SQLAllocConnect(cijeli *                              cijeli   cbWndExtra;
ConnectionHandle,cijeli EnvironHandle);                               cijeli   hInstance;
cijeli funkcija SQLDriverConnect(cijeli                               cijeli   hIcon;
DriverCompletion,cijeli * StringLengthDPtr,                           cijeli   hCursor;
    cijeli BufferLength, cijeli * OutConnectionString,                cijeli   hbrBackground;
    cijeli StringLengthJ,cijeli * InConnectionString,cijeli           karakter * lpszMenuName;
WindowHandle,                                                         karakter * lpszClassName;
    cijeli ConnectionHandle);                                         cijeli hIconSm;
` DRIVER={Microsoft Access Driver (*.mdb)};DBQ=                     } wndclass ; ` window class structure
cijeli funkcija   SQLAllocStmt(cijeli *
StatementHandle,cijeli ConnectionHandle);                        cijeli nCmdShow;
cijeli funkcija   SQLExecDirect(cijeli TextLen,cijeli *          karakter * lpszCmdLine;
StatementText,cijeli StatementHandle);                           cijeli hPrevInstance;
cijeli funkcija   SQLDisconnect(cijeli ConnectionHandle);        cijeli hInstance;
cijeli funkcija   SQLFreeConnect(cijeli ConnectionHandle);       cijeli ka,kb,kc,kd,ke,kf,kg,kh,ki,kj,kk;
cijeli funkcija lstrlenA (karakter * a);                         cijeli ehan,chan,shan;
cijeli funkcija wvsprintfA(realni * broj,karakter * format,
  karakter * bafer );                                            #definiraj   UOKVIRENO 1350631424
cijeli funkcija SQLFreeStmt(cijeli fOption,cijeli hstmt);        #definiraj   NAV lstrcat(navodnik,komanda)
cijeli funkcija SQLFetch(cijeli StatementHandle);                #definiraj   POLJE lstrcat(polje,komanda)
cijeli funkcija SQLGetData(cijeli * StrLenOrInd,cijeli           #definiraj   ZAREZ lstrcat(",",komanda)
BufferLength,                                                    #definiraj   SQLDRIVERPROMPT 2
                                                                 #definiraj   SQLCHAR 1
                                                 Sl. 12.1.3.        Datoteka ODBC.H


12.2.      Primjer: Multimedija
        Na slici Sl. 12.2.1 je dat prosti program koji šalje na zvuĉnik sadrţaj WAV datoteke, koristeći funkciju PlaySound.
Ovaj primjer ujedno ilustruje uĉitavanje dinamiĉkih biblioteka. Funkcija LoadLibraryA uĉitava cijelu dinamiĉku biblioteku,
dok funkcija GetProcAddress vraća adresu pojedine procedure u njoj.
cijeli * PlaySound;
cijeli funkcija LoadLibraryA(karakter * ime);
cijeli funkcija GetProcAddress(karakter * ime,cijeli hl);
  cijeli hl;
{

    hl:=LoadLibraryA("WINMM.DLL");
    PlaySound:=GetProcAddress("PlaySound",hl);
    PlaySound(131072,0,"c:\PJESMA.WAV");
}
                                                 Sl. 12.2.1.        Datoteka sound.jez


12.3.      Primjer: Web Server
         U jeziku FILDZAN-32 napisan je mali Web server, sposoban da prikazuje statiĉke web stranice sa hiperlinkovima, na
mašini, lokalnoj mreţi ili Internetu. Web server koristi Winsock biblioteku, odnosno funkcije WSAStartup (inicijalizacija
okruţenja), WSACleanup (uklanjanje okruţenja), accept (prihvatanje konekcije i njeno povezivanje s soketom), closesocket
(uklanjanje soketa iz tabele), send (slanje podataka prijemnom soketu) , recv (prijem podatka od drugog soketa), socket
(kreiranje krajnje taĉke za komunikaciju i vraćanje soketa), listen (slušanje da li u konekciji nailazi neki soket i bind (dodjela
lokalnog imena neimenovanom soketu).
         Listing programa dat je na slici Sl. 12.3.1. Princip Web servera je u suštini jednostavan. Nakon što je povezan soket
da osluškuje port 80 (HTTP) oĉekuje se zahtjev od strane klijenta. U okviru ovog zahtjeva obiĉno dolazi komanda GET
praćena imenom datoteke i verzijom protokola. Nakon parsiranja imena, otvara se datoteka sa tim imenom i njen sadrţaj se
pošalje klijentskom soketu koristeći funkciju send.
                                                                84

#definiraj HTTPPORT 80                     cijeli funkcija recv(cijeli a,cijeli                  petlja :=1;
#definiraj CETRSTOCETIRI "HTTP/1.1\ 404    b,cijeli * c,cijeli sock);                            bytes := 1;
Content-Type: text/html \ <h1>Nema         cijeli funkcija lstrcmp(karakter *                    dok (bytes # 0 ) & petlja {
stranice</h1><hr><i>Ibrik\ Web Server,     a,karakter * b);                                         dalje:=1;
v1.0-(c) 2002-2003 by \ Kenan Kalajdzic"   cijeli funkcija lstrcpy(karakter *                       bytes := recv(0,BUFSIZE-pos,
#definiraj CETRSTO "HTTP/1.1 400 \         a,karakter * b);                                           &buf[pos], newsd);
Content-Type: text/html <h1>Bad \          slog {                                                   ako (bytes = SOCKETERROR) {
Request</h1><hr><i>Ibrik Web \ Server,       karakter [METODLEN] method;                               ako (closesocket(newsd) =
v1.0 - (c) 2002-2003 by \ Kenan              karakter [PAGELEN] page;                                     SOCKETERROR) {
Kalajdzic"                                 } req;                                                           errexit("closesocket");
#definiraj INDEXPAGE "/index.htm"          cijeli funkcija hasnewline(karakter *                       }
#definiraj WEBDIR "D:/thp/%s"              ptr)                                                        dalje :=0;
#definiraj METODLEN 16                     { cijeli ima,n;                                          }
#definiraj PAGELEN 256                       ima:=0;                                                ako(hasnewline(buf)&dalje) {
#definiraj SOCKADDRIN slog { \               dok (* ptr # 0) & (ima =0) {                              dalje := 0;
karakter fam1,fam2,port1,port2; \               ako (* ptr = 13) {                                     petlja := 0;
cijeli inaddr; karakter [8] \                   * ptr := 0;                                         }
sinzero; }                                      ima:=1;                                             ako dalje {
#definiraj BUFSIZE 1024                         }                                                      pos := pos+bytes;
#definiraj SOCKET cijeli                     ptr:=&(ptr[1]);                                        }
#definiraj SOCKSTREAM 1                      }                                                   }
#definiraj SOCKETERROR (-1)                  n:=ima;                                             getstr( req.page,
#definiraj INVALIDSOCKET (~0)              }                                                        getstr(req.method, buf,
#definiraj INADDRANY 0                     karakter * funkcija getstr(karakter *                       METODLEN),PAGELEN);
#definiraj PFINET 2                        dest, karakter * src, cijeli max)                     dalje :=1;
#definiraj STRADDRINLEN 16                 { karakter * rez;                                     ako (lstrcmp("GET",
#definiraj FILEATTRIBUTENORMAL 128           karakter m;                                            req.method)){
#definiraj OPENEXISTING 3                    max := max-1;                                          dalje :=1;
#definiraj GENERICREAD 2147483648            dok ( src[0] # ' ') & (max >0) {                       send(0,100,CETRSTO,newsd);
#definiraj INVALIDHANDLEVALUE (-1)              dest[0] := src[0];                                  ako (closesocket(newsd) =
#definiraj WSADATA slog { cijeli \              src := &(src[1]);                                     SOCKETERROR) {
 wVersion;\                                     dest := &(dest[1]);                                    errexit("closesocket");
 cijeli wHighVersion;\                          max := max-1;                                       }
 karakter [257] szDescription;\              }                                                      dalje := 0;
 karakter [129] szSystemStatus;\             * dest := 0;                                        }
 cijeli iMaxSocketsiMaxUdpDg;\               rez := &(src[1]);                                   ako(!lstrcmp("/",req.page)&
 karakter * lpVendorInfo;}                 }                                                       dalje) {
SOCKET sd, newsd;                          cijeli funkcija errexit(karakter *                       lstrcpy(INDEXPAGE,req.page);
cijeli f,imebr;                            title)                                                }
cijeli wsVersion;                          {                                                     ako dalje {
cijeli bytes, pos;                           MessageBoxA(0,"Upozorenje", title,0);                  imebr:=req.page;
karakter [BUFSIZE] buf;                      WSACleanup();                                          imebr:=imebr+1;
karakter * ptr, ptr2 ;                       ExitProcess(-1);                                      wvsprintfA(&imebr,WEBDIR,buf);
SOCKADDRIN sin, rhost; cijeli rlen;        }                                                     f := CreateFileA(0,
cijeli dalje,petlja;                                                                             FILEATTRIBUTENORMAL,
WSADATA wsaData;                           {                                                     OPENEXISTING,0,0,
cijeli funkcija WSAStartup (cijeli *           ako (GetVersion() < 2147483648) {                 GENERICREAD,buf);
adr,cijeli ver);                                  wsVersion := 2;     ` Win NT                      ako f = INVALIDHANDLEVALUE {
cijeli funkcija WSACleanup ();                 }                                                       send(0,80,
cijeli funkcija GetVersion ();                 inace {                                                   CETRSTOCETIRI,newsd);
cijeli funkcija accept(cijeli * a,cijeli          wsVersion := 257;     ` Win 9x                       ako (closesocket(newsd)<0){
* b,cijeli c);                                 }                                                          errexit("closesocket");
cijeli funkcija closesocket(cijeli             ako (WSAStartup                                         }
socket);                                         (&wsaData,wsVersion )){                               dalje:=0;
cijeli funkcija send(cijeli a, cijeli b,          errexit("WSAStartup");                            }
karakter * c,cijeli d);                        }                                                    inace {
cijeli funkcija socket(cijeli a,cijeli         sd:= socket(0,SOCKSTREAM,PFINET);                       petlja:=1;
b,cijeli c);                                   ako (sd=INVALIDSOCKET) {                                dok (petlja ) {
cijeli funkcija listen(cijeli a,cijeli            errexit("socket");                                      ako (!ReadFile(0,&bytes,
b);                                            }                                                             BUFSIZE,buf,f)) {
cijeli funkcija bind(cijeli a,cijeli *         sin.fam1 := PFINET;                                           petlja:=0;
sockp,cijeli sock);                            sin.fam2 := 0;                                             }
cijeli funkcija wvsprintfA(cijeli *            sin.port1 := 0;                                         ako (bytes = 0) {
kom,karakter * fmt,karakter * dest);           sin.port2 := HTTPPORT;                                     petlja:=0;
cijeli funkcija CreateFileA(cijeli             sin.inaddr := INADDRANY;                                }
hTemplateFile, cijeli                          ako (bind(STRADDRINLEN,&sin,sd)=                        ako petlja {
dwFlagsAndAttributes,cijeli                       SOCKETERROR){                                           ako send(0,bytes,buf,
dwCreationDisposition,                            errexit("bind");                                          newsd) =SOCKETERROR) {
   karakter * lpSecurityAttributes,            }                                                             petlja:=0;
   cijeli dwShareMode,cijeli                   ako (listen(1,sd)=SOCKETERROR) {                           }
dwDesiredAccess,karakter * lpFileName,            errexit("listen");                                   }
);                                             }                                                    }
cijeli funkcija ReadFile( cijeli               dok (1 ) {                                           ako (!CloseHandle(f)) {
lpOverlapped, cijeli *                            rlen := STRADDRINLEN;                                errexit("CloseHandle");
lpNumberOfBytesRead,                              newsd:=accept(&rlen,&rhost,sd);                   }
   cijeli nNumberOfBytesToRead, cijeli *          ako (newsd= INVALIDSOCKET) {                   }
lpBuffer, cijeli hFile);                            errexit("accept");                           ako (closesocket(newsd) =
cijeli funkcija CloseHandle(cijeli                }                                                SOCKETERROR) {
hobject);                                         pos := 0;                                         errexit("closesocket");
cijeli funkcija MessageBoxA(cijeli                bytes :=0;                                     }
opcije,karakter * poruka, karakter *              dok (bytes < BUFSIZE) {                    }
naslov,cijeli handle);cijeli funkcija               buf[bytes]:=0;                       }
ExitProcess(cijeli kod);                            bytes := bytes+1;                }
                                                  }
                                                      Sl. 12.3.1.      Web server
                                                              85

12.4.    Primjer: Numerička analiza
        Pogledati primjer “Metoda sekante” na slici Sl. 9.7.1 s obzirom da se oĉuvala kompatibilnost sa tom verzijom
kompajlera.



12.5.    Rezime poglavlja
         Završni primjeri pokazuju zrelost koju je jezik dostigao. Unatoĉ jednostavnom optimizatoru i kompajleru, izvršne
verzije svih testnih programa su duţine ispod 10 kilobajta. Raznovrsnost oblasti a već odliĉno demonstrira da se ovim
kompajlerom mogu praviti gotovo sve klasiĉne aplikacije. Testni primjeri su posluţili za otkrivanje grešaka u kompajleru, ali i
pokazali da je sa ovom verzijom jezika moguće praviti aplikacije iz oblasti korisniĉkog interfejsa, baza podataka, multimedije,
dvodimenzionalne i trodimenzionalne grafike, lokalnih i globalnih mreţa, numeriĉke analize i gotovo svih drugih oblasti
softvera. FILDZAN-32 definitivno nije najjednostavniji programski jezik za realizaciju ovih aplikacija, ali je jedan od rijetkih
koji pruţa uvid u internu implementaciju softvera.
                                                              86
        Prilog 8: Verzija izvornog koda kompajlera br. 8, glavni program
program Kompajler;                           ukupnoident, ukupnoslogova, ukdim:               + znak;
uses predpr8, postpr8;                         integer;                                    NoviSvaki(false);
const                                        t: TTip;                                      while (znak >= '0') and (znak <=
  MAXIDENT = 1024;                           dod: Boolean;                                    '9') do begin
  MAXDIM = 10;                               zadnji: TZadnjiSlog;                             realnakonstanta :=
  DUGAKONST =                                dimenzije: array[0..MAXDIM] of         realnakonstanta
    'Konstanta prevazilazi liniju';            integer;                                         + znak;
  REALKONST = 'Realna konstanta';                                                             NoviSvaki(false);
  OCEKIVANO = 'Ocekivano ';                procedure NoviIdent(pime: string;               end;
  REDEKLAR =                                 pduzina: integer;                           end;
    'Redeklarisan identifikator';            padresa: integer; pnivo: integer;           if (znak = 'e') or (znak = 'E') then
  PROSTNIZ =                                    pvrsta: TVrsta;                            begin
    'Prosti tip ne moze biti niz';           ptip: TTip; ppod1: integer; ppod2:            realnakonstanta := realnakonstanta
  NEKORARG =                                    integer; ppod3: integer);                     + znak;
    'Nekorektan broj argumenata';          var                                             NoviSvaki(false);
  NEKDODJP = 'Losa dodjela pointeru';        i: integer;                                   if (znak = '+') or (znak = '-')
  NEDEKL = 'Nedeklarisano ';               begin                                              then begin
  GRIZRAZ = 'Izraz';                         ukupnoident := ukupnoident + 1;                  realnakonstanta :=
  POGRMNOZ =                                 with TabIdent[ukupnoident] do begin               realnakonstanta + znak;
    'Pogresan tip u ' +                         ime := pime;                                  NoviSvaki(false);
    'mnozenju ili dijeljenju';                  duzina := pduzina;                         end;
  NEDOPFP =                                     adresa := padresa;                         if (znak < '0') or (znak > '9')
    ' Nedopustena FP operacija';                nivo := pnivo;                                then
  NEDOPARIT =                                   vrsta := pvrsta;                              Greska(REALKONST);
    'Nedopusteni tip u aritmetici';             tip := ptip;                               while (znak >= '0') and (znak <=
  OCEKDOD = 'Ocekivano dodjeljivanje';          pod1 := ppod1;                                '9') do begin
  NEDODJ =                                      pod2 := ppod2;                                realnakonstanta :=
    'Izraz se ne moze dodijeliti';              pod3 := ppod3;                                 realnakonstanta + znak;
  DODJPOINT = 'Losa dodjela pointeru';          ukupdim := ukdim;                             NoviSvaki(false);
  TIPUSL = 'Neodgovarajuci tip uslova';         for i := 0 to MAXDIM do                    end;
  TUSLPET =                                       dim[i] := dimenzije[i];                end;
    'Neodgovarajuci uslov u petlji';         end;                                        UzmiKonstantu := 0;
  IMEFUN = 'Ocekivano ime funkcije';       end;                                          t := realni;
  DEFFUN = 'Definicija funkcije';                                                     end
  ARGNEKOM =                               procedure NovaLabela(var ImeLabele:        else begin
    'Argument nekompatibilan' +              string);                                    UzmiKonstantu := rezultat;
    ' s operatorom';                       begin                                         t := cijeli;
  OCIDENT =                                  trenlabela := trenlabela + 1;            end;
    'Ocekivan Identifikator';                Str(trenlabela, ImeLabele);              if (znak = ' ') or (znak = '`') then
  MAXDIMOV =                               end;                                          Novi;
    'Maksimalan broj dimenzija';                                                      dod := false;
  INDSTATC =                               procedure Greska(poruka: string);        end;
    'Indeks statickog niza nije cijeli';   begin
  PREVDIM =                                  WriteLn(poruka);                       function Slijedi(ocekivano: string;
    'Prevazidjen broj dimenzija';            WriteLn(brojaclinija, ':', linija);      dslovoiza: Boolean): Boolean;
  NESLDIM =                                  Close(ulaz);                           var
    'Ne slaze se broj dimenzija';            Close(izlaz);                            ureduiza: Boolean;
  POLJEPOS = 'Polje vec postoji';            Halt;                                    n: integer;
  SLOGPOLJE =                              end;                                       znak: char;
    'Samo slogovi mogu imati polja';                                                begin
  NEDEKPOLJE = 'Nedeklarisano polje';      procedure NoviSvaki(greskakrln:            if dslovoiza then
  SLOGSLOGU =                                Boolean);                                   ureduiza := true
    'Slog se moze dodijeliti samo          begin                                      else begin
slogu';                                      pozicija := pozicija + 1;                   n := pozicija + Length(ocekivano);
  SLOGRAZDUZ =                               if pozicija > Length(linija) then           ureduiza := true;
    'Slogovi razlicite duzine';                 begin                                    if Length(linija) >= n then begin
  INDNOPOINT =                                  if greskakrln then                         znak := linija[n];
    'Indirektna funkcija bez pointera';           Greska(DUGAKONST)                        if ((znak >= 'a') and (znak <=
  SLOGNEPOR =                                   else                                         'z')) or
    'Slogovi se ne mogu porediti';                znak := ' ';                               ((znak >= 'A') and (znak <=
                                             end                                               'Z')) then
type                                         else                                            ureduiza := false
  TVrsta = (funkcija, lokalna,                  znak := linija[pozicija];                end
     globalna, parametar, polje);          end;                                       end;
  TTip = (karakter, cijeli, realni,                                                   if ureduiza and (copy(linija,
     slog, pkarakter,                      procedure IdiDo(z: char);                     pozicija,
     pcijeli, prealni, pslog);             begin                                         Length(ocekivano)) = ocekivano) then
  TIdent = record                            if (znak <> z) then                           begin
     ime: string[20];                           Greska(OCEKIVANO + z);                   Slijedi := true;
     duzina: integer;                        Novi;                                       pozicija := pozicija +
     adresa: integer;                      end;                                            Length(ocekivano) - 1;
     nivo: integer;                                                                   end
     vrsta: TVrsta;                        function UzmiKonstantu                     else
     tip: TTip;                              (var t: TTip; var dod: Boolean):            Slijedi := false;
     pod1: integer;                            integer;                             end;
     pod2: integer;                        var
     pod3: integer;                          rezultat: integer;                      function TipDek(imetipa: string; var
     ukupdim: integer;                     begin                                       tip: TTip;
     dim: array[0..MAXDIM] of integer;       rezultat := 0;                            stip, ptip: TTip): Boolean;
  end;                                       realnakonstanta := '';                  var
                                             while (znak >= '0') and (znak <= '9')     tipind: TTip;
  TZadnjiSlog = record                         do begin                                kraj, x, poi: Boolean;
    duzina: integer;                           rezultat := 10 * rezultat +           begin
    pozimena: integer;                            ord(znak) - ord('0');                TipDek := false;
    idopisasloga: integer                      realnakonstanta := realnakonstanta      poi := false;
  end;                                            + znak;                              if Slijedi(imetipa, false) then begin
                                               NoviSvaki(false);                         TipDek := true;
var                                          end;                                        Novi;
  trenlabela, aktnivo: integer;              if (znak = '.') or (znak = 'e') or          if znak = '*' then begin
  realnakonstanta: string;                     (znak = 'E') then begin                     tip := ptip;
  TabIdent: array[0..MAXIDENT] of              if znak = '.' then begin                    poi := true;
    TIdent;                                       realnakonstanta := realnakonstanta       Novi
                                                             87
     end                                            (TabIdent[n].vrsta in                  Emit(' MOV EAX,EBX');
     else                                             [lokalna, globalna,               until znak <> ',';
       tip := stip;                                     parametar, funkcija]) and       Emit(' POP EBX');
     ukdim := 0;                                      ((TabIdent[n].nivo = nivo) or     if (navdim <> TabIdent[idpoz].ukupdim)
     if znak = '[' then begin                           (TabIdent[n].nivo = 0));           and (not ((navdim = 1) and
       if poi then                               2: Uslov := (TabIdent[n].ime =            (TabIdent[idpoz].ukupdim = 0))) then
          tip := pcijeli                            ident) and                             Greska(NESLDIM);
       else                                         (TabIdent[n].vrsta in               IdiDo(']');
          tip := ptip;                                [lokalna, globalna,               case t of
       IdiDo('[');                                      parametar, funkcija]) and          pkarakter: begin
       repeat                                         ((TabIdent[n].nivo = nivo));             t := karakter;
          ukdim := ukdim + 1;                    3: Uslov := (TabIdent[n].ime =              end;
          if ukdim > MAXDIM then                    ident) and                             pcijeli: begin
            Greska(MAXDIMOV);                       (TabIdent[n].vrsta = polje) and            Emit(' SAL EAX,2');
          dimenzije[ukdim] :=                         (TabIdent[n].nivo = nivo) and            t := cijeli;
            UzmiKonstantu(tipind, x);                   (TabIdent[n].pod3 = p1);             end;
          if tipind <> cijeli then               4: Uslov := (TabIdent[n].nivo =           prealni: begin
            Greska(INDSTATC);                       nivo) and                                  Emit(' FSTP ST(0)');
          kraj := true;                             (TabIdent[n].pod2 = p1) and                Emit(' SAL EAX,3');
          if znak = ',' then begin                    (TabIdent[n].vrsta =                     t := realni;
            Novi;                         parametar)                                         end;
            kraj := false;                     else                                        pslog: begin
          end;                                   Uslov := false;                               t := slog;
       until kraj;                             end;                                            Str(DuzinaTipa(t), st);
       IdiDo(']');                             if Uslov then begin                             Emit(' MOV EDX,' + st);
     end;                                        nadjen := true;                               Emit(' MUL EDX');
  end                                            poz := n;                                   end;
end;                                           end;                                     else
                                               n := n - 1;                                 Greska(PROSTNIZ)
function SlijediDekTipa(var tip: TTip):     end;                                        end;
  Boolean;                                  NadjiIdent := poz;                          Emit(' ADD EBX,EAX');
var                                       end;                                          case t of
  a: Boolean;                                                                              karakter:
begin                                     procedure UzmiIdent(var ident: string);            Emit(' MOV AL,[EBX]');
  a := false;                             begin                                            realni:
  if not (a) then                           if znak in ['a'..'z', 'A'..'Z'] then             Emit(' FLD QWORD PTR [EBX]')
     a := TipDek('cijeli', tip, cijeli,        begin                                    else
       pcijeli);                               ident := znak;                              Emit(' MOV EAX,[EBX]');
  if not (a) then                              NoviSvaki(false);                        end;
     a := TipDek('karakter', tip,           end                                         dod := true;
       karakter, pkarakter);                else                                      end;
  if not (a) then                              Greska(OCIDENT);
     a := TipDek('realni', tip, realni,     while (znak in ['a'..'z', 'A'..'Z',     procedure StringKonstanta(var t: TTip;
       prealni);                               '0'..'9', '_']) do begin               var dod: Boolean);
  if not (a) then                              ident := ident + znak;               var
     a := TipDek('slog', tip, slog,            NoviSvaki(false);                      st, strtekst: string;
       pslog);                              end;                                    begin
  SlijediDekTipa := a;                      if (znak = ' ') or (znak = '`') then      NovaLabela(strtekst);
end;                                           Novi;                                  Emit('.DATA');
                                          end;                                        st := 'L' + strtekst + ' DB ''';
function DuzinaTipa(tip: TTip):                                                       repeat
  Integer;                                 procedure DeklIdent(var ident: string;        NoviSvaki(true);
var                                          nivo: integer);                             if znak <> '"' then
  elem, i: integer;                        begin                                           st := st + znak;
begin                                        UzmiIdent(ident);                        until znak = '"';
  case tip of                                if NadjiIdent(ident, nivo, 2, 0) <> 0    IdiDo('"');
     cijeli: DuzinaTipa := 4;                   then                                  st := st + ''',0';
     pcijeli, pkarakter, prealni, pslog:        Greska(REDEKLAR);                     if copy(st, length(st) - 3, 2) =
       begin                               end;                                          '''''' then
         if ukdim = 0 then                                                               st := 'L' + strtekst + ' DB 0';
            DuzinaTipa := 4                procedure IzrazDodjeljivanja               Emit(st);
         else begin                          (var t: TTip; var dod: Boolean);         Emit('.CODE');
            elem := 4*ord(tip = pcijeli)+       forward;                              Emit(' MOV EAX,OFFSET L' + strtekst);
              1 * ord(tip = pkarakter) +   procedure Blok; forward;                   t := pkarakter;
              8 * ord(tip = prealni) +                                                dod := false;
              zadnji.duzina * ord(tip =    procedure PokazivacINiz(var t: TTip; var end;
                pslog);                      dod: Boolean; idpoz: Integer);
            for i := 1 to ukdim do         var
              elem := elem * dimenzije[i];   t1: TTip;                              procedure PEmit(idpoz: Integer);
            DuzinaTipa := elem;              navdim,dsvedim,i: Integer;             var
         end                                 st: string;                              i: integer;
       end;                                begin                                    begin
     karakter: DuzinaTipa := 1;              navdim := 0;                             if TabIdent[idpoz].ukupdim = 0 then
     realni: DuzinaTipa := 8;                Emit(' PUSH EAX');                          Emit(' MOV EAX,[EBX]')
     slog: DuzinaTipa := zadnji.duzina;      Emit(' MOV EAX,0');                      else
  else                                       repeat                                      Emit(' MOV EAX,EBX');
     DuzinaTipa := 4;                           Novi;                                 ukdim := TabIdent[idpoz].ukupdim;
  end;                                          navdim := navdim + 1;                 for i := 0 to MAXDIM do
end;                                            if navdim > MAXDIM then                  dimenzije[i] :=
                                                  Greska(PREVDIM);                         TabIdent[idpoz].dim[i];
function NadjiIdent(ident: string;              Emit(' PUSH EAX');                  end;
  nivo, tuslova, p1: integer): integer;         IzrazDodjeljivanja(t1, dod);
var                                             Emit(' POP EBX');                   function DeklaracijaSloga(nivo:
  n, poz: integer;                              if znak = ',' then begin              integer): integer;
  nadjen, Uslov: Boolean;                         dsvedim:=1;                       var
begin                                             for i:=navdim+1 to                  ImePolja: string;
  n := ukupnoident;                                TabIdent[idpoz].ukupdim do         oznakasloga, podslog, duzinasloga,
  nadjen := false;                                    dsvedim:=dsvedim*                  zapukdim, i, poz: integer;
  poz := 0;                                            TabIdent[idpoz].dim[i];        tip: TTip;
  while (n > 0) and (not (nadjen)) do             Str(dsvedim, st);                   imaistogtipa: Boolean;
     begin                                        Emit(' MOV EDX,' + st);             zdimenzije: array[0..MAXDIM] of
     case tuslova of                              Emit(' MUL EDX');                      integer;
       1: Uslov := (TabIdent[n].ime =           end;                                begin
         ident) and                             Emit(' ADD EBX,EAX');                 zapukdim := ukdim;
                                                              88
  for i := 0 to MAXDIM do                                                                           m1 := ((duzprvogsloga - 1)
     zdimenzije[i] := dimenzije[i];        procedure FPStekUCijeli(reg: string);                      div 4 + 1) * 4;
  IdiDo('{');                              begin                                                    velsteka := velsteka + m1;
  ukupnoslogova := ukupnoslogova + 1;        Emit(' ADD ESP,-4');                                   Str(duzprvogsloga, st);
  oznakasloga := ukupnoslogova;              Emit(' FISTP DWORD PTR [ESP]');                        Emit(' MOV ECX,' + st);
  duzinasloga := 0;                          Emit(' POP ' + reg);                                   Str(m1, st);
  poz := 0;                                end;                                                     Emit(' SUB ESP,' + st);
  while SlijediDekTipa(tip) do begin                                                                Emit(' MOV ESI,EBX');
     if (tip = slog) or (tip = pslog)      procedure                                                Emit(' MOV EDI,ESP');
       then                                  CPUStekCijeliNaFPStek(osmobitni:                       Emit(' CLD');
       podslog := DeklaracijaSloga(nivo)     Boolean);                                              Emit(' REP MOVSB');
     else                                  begin                                                 end;
       podslog := oznakasloga;               if osmobitni then                                 realni: begin
     repeat                                     Emit(' AND DWORD PTR [ESP],0FFh');                  velsteka := velsteka + 8;
       UzmiIdent(ImePolja);                  Emit(' FILD DWORD PTR [ESP]');                         case t1 of
       poz := NadjiIdent(ImePolja, nivo,     Emit(' ADD ESP,4');                                      realni: ;
          3, podslog);                     end;                                                       karakter:
       if poz <> 0 then                                                                                  CijeliNaFPStek('EAX',
          Greska(POLJEPOS);                procedure FPUStekNaStek;                                      true);
       NoviIdent(ImePolja,                 begin                                                    else
          DuzinaTipa(tip),                   Emit(' ADD ESP,-8');                                     CijeliNaFPStek('EAX',
          0, nivo, polje, tip, podslog,      Emit(' FSTP QWORD PTR [ESP]');                              false);
            duzinasloga, oznakasloga);     end;                                                     end;
       duzinasloga := duzinasloga +                                                                 FPUStekNaStek;
          DuzinaTipa(tip);                 procedure StekNaFPUStek;                              end
       imaistogtipa := true;               begin                                            else begin
       if znak = ',' then begin              Emit(' FLD QWORD PTR [ESP]');                       velsteka := velsteka + 4;
          Novi;                              Emit(' ADD ESP,8');                                 if t1 = realni then
          imaistogtipa := false;           end;                                                     FPStekUCijeli('EAX');
       end;                                                                                      Emit(' PUSH EAX');
     until imaistogtipa;                   procedure PozivFunkcije                             end;
     while (duzinasloga mod 4) <> 0 do       (idpoz: integer; var t: TTip; var              end;
       duzinasloga := duzinasloga + 1;         dod: Boolean);                               if znak <> ')' then
     IdiDo(';');                           var                                                 IdiDo(',');
  end;                                       parametara, N, velsteka,                     end;
  IdiDo('}');                                  duzprvogsloga,                             IdiDo(')');
  zadnji.duzina := duzinasloga;                duzdrugogsloga, m1: integer;               if TabIdent[idpoz].pod1 <>
  zadnji.pozimena := poz;                    t1, t2: TTip;                                  parametara then
  zadnji.idopisasloga := OznakaSloga;        ImeFunkcije, st: string;                       Greska(NEKORARG);
  DeklaracijaSloga := OznakaSloga;         begin                                          Str(velsteka, st);
  ukdim := zapukdim;                         ImeFunkcije := TabIdent[idpoz].ime;          Emit(' MOV ECX,' + st);
  for i := 0 to MAXDIM do                    parametara := 0;                             Emit(' CALL ' + ImeFunkcije + '@' +
     dimenzije[i] := zdimenzije[i];          velsteka := 0;                                 st);
end;                                         duzprvogsloga := 0;                          dod := false;
                                             duzdrugogsloga := 0;                         t := TabIdent[idpoz].tip;
procedure ElementSloga                       if znak <> '(' then begin                    if t = karakter then
  (idpoz: integer; var t: TTip; var            velsteka := 0;                               Emit(' AND EAX,0FFh');
     dod: Boolean);                            for parametara := 1 to                  end;
var                                              TabIdent[idpoz].pod1 do begin       end;
  poz, nivo, idsloga: integer;                   n := NadjiIdent('', idpoz, 4,
  Imepolja, st: string;                             parametara);                     procedure IndirektniPoziv(var t: TTip);
begin                                            velsteka := velsteka + (            var
  if t <> slog then                                 (TabIdent[n].duzina - 1) div 4     m1, velsteka, duzsloga: Integer;
     Greska(SLOGPOLJE);                                + 1) * 4;                       straddr, st: string;
  nivo := TabIdent[idpoz].nivo;                end;                                    t1: TTip;
  idsloga := TabIdent[idpoz].pod3;             Str(velsteka, st);                    begin
  while znak = '.' do begin                    Emit(' MOV EAX,OFFSET ' +               velsteka := 0;
     Novi;                                       imefunkcije + '@' + st);              NovaLabela(straddr);
     UzmiIdent(ImePolja);                      t := pcijeli;                           Emit('.DATA');
     poz := NadjiIdent(ImePolja, nivo,         dod := false;                           st := 'L' + straddr + ' DD ?';
       3, idsloga);                          end                                       Emit(st);
     if poz = 0 then                         else begin                                Emit('.CODE');
       Greska(NEDEKPOLJE);                     IdiDo('(');                             Emit(' MOV L' + straddr + ',EAX');
     Str(TabIdent[poz].pod2, st);              while (znak <> ')') do begin            IdiDo('(');
     Emit(' ADD EBX,' + st);                     IzrazDodjeljivanja(t1, dod);          while (znak <> ')') do begin
     t := TabIdent[poz].tip;                     if t1 = slog then                       IzrazDodjeljivanja(t1, dod);
     case t of                                      duzprvogsloga :=                     case t1 of
       karakter: Emit(' MOV AL,[EBX]');                DuzinaTipa(t1);                      slog: begin
       realni:                                   parametara := parametara + 1;                   duzsloga := DuzinaTipa(t1);
          Emit(' FLD QWORD PTR [EBX]');          n := NadjiIdent('', idpoz, 4,                   m1 := ((duzsloga - 1) div 4 +
       slog: begin                                  parametara);                                   1) * 4;
            idsloga :=                           if n = 0 then                                   velsteka := velsteka + m1;
               TabIdent[poz].pod1;                  Greska(NEKORARG);                            Str(duzsloga, st);
            zadnji.duzina :=                     t2 := TabIdent[n].tip;                          Emit(' MOV ECX,' + st);
               TabIdent[poz].duzina;             if t2 = slog then                               Str(m1, st);
            zadnji.pozimena := poz;                 duzdrugogsloga :=                            Emit(' SUB ESP,' + st);
            zadnji.idopisasloga :=                     TabIdent[n].duzina;                       Emit(' MOV ESI,EBX');
               TabIdent[poz].pod3;               if (t1 in [karakter, realni]) and               Emit(' MOV EDI,ESP');
          end;                                      (t2 in [pkarakter, pcijeli,                  Emit(' CLD');
       cijeli: Emit(' MOV EAX,[EBX]');                 prealni]) then                            Emit(' REP MOVSB');
     else                                           Greska(NEKDODJP);                         end;
       PEmit(poz);                               if (t1 = karakter) and (t2 =               realni: begin
     end;                                           cijeli) then                                 velsteka := velsteka + 8;
  end;                                              Emit(' AND EAX,0FFh');                       FPUStekNaStek;
end;                                             if ((t1 = slog) and (t2 <> slog))            end
                                                    or                                   else begin
procedure CijeliNaFPStek(reg: string;               ((t1 <> slog) and (t2 = slog))            velsteka := velsteka + 4;
  osmobitni: Boolean);                                 then                                   Emit(' PUSH EAX');
begin                                               Greska(SLOGSLOGU);                      end;
  if osmobitni then                              case t2 of                              end;
     Emit(' AND ' + reg + ',0FFh');                 slog: begin                          if znak <> ')' then
  Emit(' MOV INTTOFP,' + reg);                           if duzprvogsloga <>                IdiDo(',');
  Emit(' FILD DWORD PTR INTTOFP');                          duzdrugogsloga then        end;
end;                                                        Greska(SLOGRAZDUZ);        IdiDo(')');
                                                           89
  Str(velsteka, st);                            Novi;                                        end;
  Emit(' MOV ECX,' + st);                       Faktor(t, dod);                            end;
  Emit(' CALL L' + straddr);                    case t of                                '(': begin
  case t of                                        cijeli: Emit(' NOT EAX');                 Novi;
     pcijeli: t := cijeli;                         karakter: Emit(' NOT AL');                IzrazDodjeljivanja(t, dod);
     prealni: t := realni;                      else                                         IdiDo(')');
     pkarakter: t := karakter;                     Greska(err);                            end;
     pslog: t := slog;                          end;                                     'A'..'Z', 'a'..'z': begin
  else                                          dod := false;                                UzmiIdent(ime);
     Greska(INDNOPOINT)                       end;                                           poz := NadjiIdent(ime, aktnivo,
  end;                                      '&': begin                                          1, 0);
end;                                            Novi;                                        if poz = 0 then
                                                Faktor(t, dod);                                 Greska(NEDEKL + ime);
procedure Varijabla                             Emit(' MOV EAX,EBX');                        case TabIdent[poz].vrsta of
  (idpoz: integer; var t: TTip; var             case t of                                       funkcija:
     dod: Boolean; glob: Boolean);                 cijeli: t := pcijeli;                          PozivFunkcije(poz, t, dod);
var                                                karakter: t := pkarakter;                    lokalna, parametar:
  rezultat: integer;                               slog: t := pslog;                              Varijabla(poz, t, dod,
  st: string;                                      realni: begin                                    false);
begin                                                   t := prealni;                           globalna:
  rezultat := TabIdent[idpoz].adresa;                   Emit(' FSTP ST(0)');                      Varijabla(poz, t, dod, true)
  t := TabIdent[idpoz].tip;                          end;                                    end
  Str(rezultat, st);                            else                                       end;
  if glob then                                     t := pcijeli;                      else
     Emit(' LEA EBX,GLOBALV[' + st + ']')       end;                                     Greska(GRIZRAZ);
  else begin                                    dod := false;                         end;
     if rezultat >= 0 then                    end;                                    if znak = '.' then
       Emit(' LEA EBX,[EBP+' + st + ']')    '*': begin                                   ElementSloga(zadnji.pozimena,t,pod);
     else                                       Novi;                               end;
       Emit(' LEA EBX,[EBP' + st + ']');        Faktor(t, dod);
  end;                                          Emit(' MOV EBX,EAX');               procedure Clan(var t: TTip; var dod:
  case t of                                     if t = prealni then begin             Boolean);
     karakter: Emit(' MOV AL,[EBX]');              Emit(' FSTP ST(0)');             var
     realni:                                       Emit(' FLD QWORD PTR [EBX]');      z: char;
       Emit(' FLD QWORD PTR [EBX]');            end                                   t1, t2: TTip;
     slog: begin                                else                                begin
          zadnji.duzina :=                         Emit(' MOV EAX,[EBX]');            Faktor(t1, dod);
            TabIdent[idpoz].duzina;             case t of                             t := t1;
          zadnji.pozimena := idpoz;                pcijeli: t := cijeli;              while (znak in ['*', '/', '%']) do
          zadnji.idopisasloga :=                   pkarakter: begin                     begin
            TabIdent[idpoz].pod3;                       t := karakter;                  z := znak;
       end;                                             Emit(' AND EAX,0FFh');          if t1 <> realni then
     pslog: begin                                    end;                                 Emit(' PUSH EAX')
          rezultat:=1;                             prealni: t := realni;                else
          for i:=1 to TabIdent[idpoz].             pslog: begin                           FPUStekNaStek;
           ukupdim do                                   t := slog;                      Novi;
            rezultat:=rezultat*                    end;                                 Faktor(t2, dod);
            TabIdent[idpoz].dim[i];             else                                    dod := false;
          if rezultat<>0 then                      Greska(err);                         if (not (t1 in [cijeli, karakter,
           zadnji.duzina :=                     end;                                      realni])) or
             TabIdent[idpoz].                   dod := true;                              (not (t2 in [cijeli, karakter,
               duzina div rezultat            end;                                           realni])) then
          else                              '!': begin                                    Greska(POGRMNOZ);
            zadnji.duzina:=4;                   Novi;                                   if (t1 = realni) or (t2 = realni)
          zadnji.pozimena := idpoz;             Faktor(t, dod);                           then begin
          zadnji.idopisasloga :=                case t of                                 t := realni;
            TabIdent[idpoz].pod3;                  cijeli: Emit(' CMP EAX,0');            if t2 <> realni then
          PEmit(idpoz);                            karakter: Emit(' CMP AL,0');              CijeliNaFPStek('EAX', t2 =
       end;                                     else                                           karakter);
    cijeli: Emit(' MOV EAX,[EBX]');                Greska(err);                           if t1 <> realni then
  else                                          end;                                         CPUStekCijeliNaFPStek(t1 =
     PEmit(idpoz);                              Emit(' SETE AL');                              karakter)
  end;                                          Emit(' AND EAX,0FFh');                    else
  if TabIdent[idpoz].ukupdim = 0 then           dod := false;                                StekNaFPUStek;
     dod := true                                t := cijeli;                              case z of
  else                                        end;                                           '*': Emit(' FMUL ');
     dod := false;                          '"': begin                                       '/': Emit(' FDIVR ');
  while znak ='[' do begin                      StringKonstanta(t, dod);                  else
     PokazivacINiz(t, dod, idpoz);            end;                                           Greska(NEDOPFP);
  end;                                      '''': begin                                   end
  if znak = '(' then                            NoviSvaki(true);                        end
     IndirektniPoziv(t);                        Emit(' MOV AL,''' + znak +              else begin
end;                                               '''');                                 t := cijeli;
                                                Novi;                                     case z of
procedure Faktor(var t: TTip; var dod:          IdiDo('''');                                 '*': begin
  Boolean);                                     t := karakter;                                   Emit(' POP EBX');
var                                           end;                                               if t1 = karakter then
  rezultat, poz: integer;                   '0'..'9': begin                                         Emit(' AND EBX,0FFh');
  st, fpkonst, ime, err: string;                rezultat := UzmiKonstantu(t,                     if t2 = karakter then
begin                                              dod);                                            Emit(' AND EAX,0FFh');
  err := ARGNEKOM;                              case t of                                        Emit(' IMUL EBX');
  case znak of                                     cijeli: begin                               end;
    '-': begin                                          Str(rezultat, st);                   '/', '%': begin
        Novi;                                           Emit(' MOV EAX,' + st);                  Emit(' MOV EBX,EAX');
        Faktor(t, dod);                              end;                                        Emit(' POP EAX');
        case t of                                  realni: begin                                 Emit(' CDQ');
           cijeli: Emit(' NEG EAX');                    NovaLabela(fpkonst);                     if t1 = karakter then
           realni: Emit(' FCHS');                       Emit('.DATA');                              Emit(' AND EAX,0FFh');
        else                                            st := 'L' + fpkonst +                    if t2 = karakter then
           Greska(err);                                   ' DQ '+realnakonstanta;                   Emit(' AND EBX,0FFh');
        end;                                            Emit(st);                                Emit(' IDIV EBX');
        dod := false;                                   Emit('.CODE');                           if z = '%' then
      end;                                              Emit(' FLD L' + fpkonst);                   Emit(' MOV EAX,EDX');
    '~': begin                                       end;                                      end;
                                                             90
       end;                                         end;                                            if t2 <> realni then
     end;                                        end;                                                  CijeliNaFPStek('EAX', t2 =
     t1 := t;                                  end;                                                      karakter);
  end;                                         t1 := t;                                             if t1 <> realni then
end;                                        end;                                                       CijeliNaFPStek('EBX', t1 =
                                          end;                                                           karakter)
procedure Izraz(var t: TTip; var dod:                                                               else
  Boolean);                                procedure IzrazDodjeljivanja                                StekNaFPUStek;
var                                          (var t: TTip; var dod: Boolean);                       Emit(' FCOMPP ');
  z: char;                                 var                                                      Emit(' FSTSW AX');
  t1, t2: TTip;                              z: char;                                               Emit(' SAHF');
begin                                        t1, t2: TTip;                                          case z of
  Clan(t1, dod);                             dod1: Boolean;                                            '=': Emit(' SETE AL');
  t := t1;                                   duzprvogsloga, duzdrugogsloga:                            '>': Emit(' SETA AL');
  while (znak in ['+', '-', '&', '|',          Integer;                                                '<': Emit(' SETB AL');
    '^']) do begin                           st: string;                                               '#': Emit(' SETNE AL');
    if t1 <> realni then                   begin                                                    end;
      Emit(' PUSH EAX')                      duzprvogsloga := 0;                                    Emit(' AND EAX,0FFh');
    else                                     duzdrugogsloga := 0;                                   t := cijeli;
      FPUStekNaStek;                         Izraz(t1, dod1);                                     end
    z := znak;                               if t1 = slog then                                    else begin
    Novi;                                      duzprvogsloga := DuzinaTipa(t1);                     if (t1 = karakter) and (t2 =
    Clan(t2, dod);                           t := t1;                                                  karakter) then
    dod := false;                            dod := dod1;                                              Emit(' CMP BL,AL')
    if (not (t1 in [cijeli, karakter,        case znak of                                           else begin
      realni])) or                             ':': begin                                              if t1 = karakter then
      (not (t2 in [cijeli, karakter,               if not (Slijedi(':=', true))                          Emit(' AND EAX,0FFh');
         realni])) then                               then                                             if t2 = karakter then
      Greska(NEDOPARIT);                              Greska(OCEKDOD);                                   Emit(' AND EBX,0FFh');
    if (t1 = realni) or (t2 = realni)              if not (dod1) then                                  Emit(' CMP EBX,EAX');
      then begin                                      Greska(NEDODJ);                               end;
      t := realni;                                 Emit(' PUSH EBX');                               case z of
      if t2 <> realni then                         if (t1 = realni) then                               '=': Emit(' SETE AL');
         CijeliNaFPStek('EAX', t2 =                   Emit(' FSTP ST(0)');                             '>': Emit(' SETG AL');
           karakter);                              Novi;                                               '<': Emit(' SETL AL');
      if t1 <> realni then                         IzrazDodjeljivanja(t2, dod);                        '#': Emit(' SETNE AL');
         CPUStekCijeliNaFPStek(t1 =                if t2 = slog then                                end;
           karakter)                                  duzdrugogsloga :=                             Emit(' AND EAX,0FFh');
      else                                              DuzinaTipa(t2);                             t := cijeli;
         StekNaFPUStek;                            if ((t1 = slog) and (t2 <>                     end;
      case z of                                       slog)) or                                 end
         '+': Emit(' FADD ');                         ((t1 <> slog) and (t2 = slog))     end;
         '-': Emit(' FSUBR ');                          then                           end;
      else                                            Greska(SLOGSLOGU);
         Greska(NEDOPFP);                          if t1 = slog then begin             procedure Uslov;
      end                                             if duzprvogsloga <>              var
    end                                                 duzdrugogsloga then              sonda, sinace, skrajuslova: string;
    else begin                                          Greska(SLOGRAZDUZ);            begin
      case z of                                       Emit(' POP EDI');                  Novi;
         '+': begin                                   Emit(' MOV ESI,EBX');              IzrazDodjeljivanja(t, dod);
             Emit(' POP EBX');                        Emit(' CLD');                      if t <> cijeli then
             if (t1 = karakter) and (t2               Str(duzprvogsloga, st);               Greska(TIPUSL);
                = karakter) then begin                Emit(' MOV ECX,' + st);            Emit(' CMP EAX,0');
                t := karakter;                     end                                   NovaLabela(sonda);
                Emit(' ADD AL,BL');                else                                  NovaLabela(sinace);
             end                                      Emit(' POP EBX');                  NovaLabela(skrajuslova);
             else begin                            if (t2 in [karakter, realni])         Emit(' JNE L' + sonda);
                t := cijeli;                          and                                Emit(' JMP L' + sinace);
                if t1 = karakter then                 (t1 in [pkarakter, pcijeli,        IdiDo('{');
                  Emit(' AND EBX,0FFh');                prealni]) then                   Emit('L' + sonda + ':');
                if t2 = karakter then                 Greska(DODJPOINT);                 Blok;
                  Emit(' AND EAX,0FFh');           if (t1 = realni) and (t2 <>           Emit(' JMP L' + skrajuslova);
                Emit(' ADD EAX,EBX');                 realni) then                       Emit('L' + sinace + ':');
             end;                                     CijeliNaFPStek('EAX', t2 =         if Slijedi('inace', false) then begin
           end;                                         karakter);                          Novi;
         '-': begin                                if (t1 <> realni) and (t2 =              IdiDo('{');
             Emit(' MOV EBX,EAX');                    realni) then                          Blok;
             Emit(' POP EAX');                        FPStekUCijeli('EAX');              end;
             if (t1 = karakter) and (t2            case t1 of                            Emit('L' + skrajuslova + ':');
                = karakter) then begin                karakter:                        end;
                t := karakter;                          Emit(' MOV [EBX],AL');
                Emit(' SUB AL,BL');                   realni:                          procedure Asembler;
             end                                       Emit(' FSTP QWORD PTR[EBX]');   begin
             else begin                               slog: Emit(' REP MOVSB');          repeat
                t := cijeli;                       else                                     ReadLn(ulaz, linija);
                if t1 = karakter then                 Emit(' MOV [EBX],EAX');               if linija <> '\' then
                  Emit(' AND EAX,0FFh');           end;                                       Emit(linija);
                if t2 = karakter then              t := t1;                                 if eof(ulaz) then
                  Emit(' AND EBX,0FFh');         end; {:}                                     linija := '\';
                Emit(' SUB EAX,EBX');          '=', '>', '<', '#': begin                 until linija[1] = '\';
             end;                                  if t1 <> realni then                  pozicija := 1;
           end;                                       Emit(' PUSH EAX')                  znak := linija[pozicija];
         '&', '|', '^': begin                      else                                  IdiDo('\');
             if (t1 = karakter) and (t2               FPUStekNaStek;                   end;
                = karakter) then                   z := znak;
                t := karakter                      Novi;                               procedure Petlja;
             else                                  Izraz(t2, dod);                     var
                t := cijeli;                       if (t1 = slog) or (t2 = slog)         sdok, skrajpetlje, suslov: string;
             Emit(' POP EBX');                        then                             begin
             case z of                                Greska(SLOGNEPOR);                 Novi;
                '&': Emit(' AND EAX,EBX');         if t1 <> realni then                  NovaLabela(suslov);
                '|': Emit(' OR EAX,EBX');             Emit(' POP EBX');                  Emit('L' + suslov + ':');
                '^': Emit(' XOR EAX,EBX');         if (t1 = realni) or (t2 =             IzrazDodjeljivanja(t, dod);
             end;                                     realni) then begin                 if t <> cijeli then
                                                               91
     Greska(TUSLPET);                                     DeklIdent(ImeVarijable,         IdiDo('{');
  Emit(' CMP EAX,0');                                        pfunkc);                     if znak <> '}' then begin
  NovaLabela(sdok);                                       lokadresa := lokadresa +           Emit('GLAVNI:');
  NovaLabela(skrajpetlje);                                   DuzinaTipa(tip);                Blok;
  Emit(' JNE L' + sdok);                                  NoviIdent(ImeVarijable,            Emit(' PUSH 0');
  Emit(' JMP L' + skrajpetlje);                              DuzinaTipa(tip),                Emit(' CALL ExitProcess@4');
  IdiDo('{');                                                -lokadresa, pfunkc,             Emit('.DATA');
  Emit('L' + sdok + ':');                                      lokalna, tip,                 Str(globadresa, st);
  Blok;                                                      pfunkc, parametara, p3);        Emit('GLOBALV DB '+st+' DUP(0)');
  Emit(' JMP L' + suslov);                                imaistogtipa := true;              Emit('INTTOFP DD 0');
  Emit('L' + skrajpetlje + ':');                          if znak = ',' then begin           Emit('END ULAZ')
end;                                                         Novi;                        end
                                                             imaistogtipa := false;       else begin
procedure Blok;                                           end;                               Emit('GLAVNI:');
begin                                                   until imaistogtipa;                  Emit('END');
  while znak <> '}' do begin                            while (lokadresa mod 4) <> 0      end;
     if Slijedi('dok', false) then                        do                            end;
       Petlja                                             lokadresa := lokadresa + 1;
     else if Slijedi('ako', false) then                 IdiDo(';');                     procedure Glavni;
       Uslov                                         end;                               var
     else if Slijedi('asembler', false)              Str(paradresa, st);                  linija: string;
       then                                          Emit(ImeFunkcije + '@' + st +      begin
       Asembler                                         ':');                             initpp;
     else begin                                      Emit(' PUSH EBP');                   trenlabela := 0;
       IzrazDodjeljivanja(t, dod);                   Emit(' MOV EBP,ESP');                ukupnoident := 0;
       IdiDo(';');                                   Str(lokadresa, st);                  aktnivo := 0;
     end;                                            Emit(' SUB ESP,' + st);              ukupnoslogova := 0;
  end;                                               Blok;                                Assign(ulaz, paramstr(1));
  IdiDo('}');                                        Emit(' MOV ESP,EBP');                Assign(izlaz, paramstr(2));
end;                                                 Emit(' POP EBP');                    brojaclinija := 0;
                                                     Str(paradresa, st);                  linija := '';
procedure DefFunkcija(ftip: TTip);                   Emit(' RET ' + st);                  Reset(ulaz);
var                                                  Emit('PUBLIC ' + ImeFunkcije +       Rewrite(izlaz);
  parametara, paradresa, lokadresa,                     '@' + st);                        Prevedi;
    pfunkc, i, p3: integer;                        end;                                   Close(ulaz);
  ImeFunkcije, imeparametra,                     ';': begin                               Close(izlaz);
    imevarijable, st: string;                        Str(paradresa, st);                  WriteLn('Prevedeno bez greske');
  tip: TTip;                                         Emit('extrn ' + ImeFunkcije +      end;
  imaistogtipa: Boolean;                                '@' + st + ':near');
begin                                                IdiDo(';');                        begin
  if not (((znak >= 'a') and (znak <=              end                                    Glavni
    'z')) or                                  else                                      end.
    ((znak >= 'A') and (znak <= 'Z')))           Greska(DEFFUN);
       then                                   end;
    Greska(IMEFUN);                           aktnivo := 0;
  DeklIdent(ImeFunkcije, 0);                end;
  NoviIdent(ImeFunkcije, 4, 0, 0,
    funkcija, ftip, 0, 0, 0);               procedure Prevedi;
  pfunkc := ukupnoident;                    var
  aktnivo := pfunkc;                          globadresa, p3: Integer;
  IdiDo('(');                                 ImeVarijable, st: string;
  parametara := 0;                            tip: TTip;
  lokadresa := 0;                             imaistogtipa: Boolean;
  paradresa := 0;                           begin
  while znak <> ')' do begin                  Emit('.486');
    if SlijediDekTipa(tip) then begin         Emit('.MODEL FLAT,STDCALL');
       if (tip = slog) or (tip = pslog)       Emit('OPTION CASEMAP:NONE');
         then                                 Emit('EXTRN ExitProcess@4:NEAR');
         p3 := DeklaracijaSloga(pfunkc)       Emit('.CODE');
       else                                   Emit('ULAZ:');
         p3 := 0;                             Emit(' FINIT');
       DeklIdent(ImeParametra, pfunkc);       Emit(' JMP GLAVNI');
       parametara := parametara + 1;          pozicija := 0;
       paradresa := paradresa +               globadresa := 0;
         ((DuzinaTipa(tip) - 1) div 4 +       Novi;
            1) * 4;                           while SlijediDekTipa(tip) do begin
       NoviIdent(ImeParametra,                  if Slijedi('funkcija', false) then
         DuzinaTipa(tip),                          begin
         paradresa, pfunkc, parametar,             Novi;
            tip, pfunkc, parametara, p3);          DefFunkcija(tip);
    end;                                        end
    if znak <> ')' then                         else begin
       IdiDo(',');                                 if (tip=slog) or (tip=pslog) then
  end;                                               p3 := DeklaracijaSloga(0)
  IdiDo(')');                                      else
  for i := ukupnoident downto 0 do                   p3 := 0;
    if (TabIdent[i].nivo = pfunkc) and             repeat
       (TabIdent[i].vrsta = parametar)               DeklIdent(ImeVarijable, 0);
         then                                        NoviIdent(ImeVarijable,
       TabIdent[i].adresa := paradresa +                DuzinaTipa(tip), globadresa,
         8 - TabIdent[i].adresa;                         0, globalna, tip, 0, 0, p3);
  TabIdent[pfunkc].pod1 := parametara;               globadresa := globadresa +
  case znak of                                          DuzinaTipa(tip);
    '{': begin                                       imaistogtipa := true;
         IdiDo('{');                                 if znak = ',' then begin
         while SlijediDekTipa(tip) do                   Novi;
            begin                                       imaistogtipa := false;
            if (tip = slog) or (tip =                end;
              pslog) then                          until imaistogtipa;
              p3 :=                                while (globadresa mod 4) <> 0 do
                 DeklaracijaSloga(pfunkc)            globadresa := globadresa + 1;
            else                                   IdiDo(';');
              p3 := 0;                          end
            repeat                            end;
                                                              92


Prilog 9: Verzija izvornog koda kompajlera br. 8, predprocesor
unit predpr8;                                        if glavnadat then                       Length(linija) - 7);
interface                                              ReadLn(ulaz, linija)               Assign(privulaz, imes);
procedure Novi;                                      else                                 Reset(privulaz);
procedure InitPp;                                      ReadLn(privulaz, linija);          glavnadat := false;
var                                               end;                                    linija := '';
  ulaz, privulaz: text;                         end;                                    end;
  pozicija, brojaclinija: integer;              definicije[deftop].kraj :=           repeat
  znak: char;                                     bafertop;                             mijenjano:=false;
  linija: string;                            end;                                       for i := 1 to deftop do
implementation                               linija := '';                                repeat
uses postpr8;                              end;                                              n := Pos(definicije[i].ime,
const                                                                                          linija);
  MAXCHAR = 200000;                        procedure PpPostoji;                              if (n +
  MAXDEFINICIJE = 50;                      var                                     Length(definicije[i].ime))
type                                         imes: string;                                     <= Length(linija) then
  Tdefinicije = record                       postoji: Boolean;                                 if linija[n +Length(
     ime: string[20];                        i: integer;                                        definicije[i].ime)] in
     pocetak: integer;                     begin                                                  ['a'..'z', 'A'..'Z'] then
     kraj: integer;                          imes := copy(linija, 10,                             n := 0;
  end;                                          Length(linija) - 9);                         if n > 1 then
var                                          postoji := false;                                 if linija[n - 1] in
  bafer: array[1..MAXCHAR] of char;          for i := 1 to deftop do                              ['a'..'z', 'A'..'Z'] then
  definicije: array[1..MAXDEFINICIJE] of        if definicije[i].ime = imes then                  n := 0;
     TDefinicije;                                 postoji := true;                           if n > 0 then begin
  bafertop: integer;                         if not (postoji) then                             glava := copy(linija,1,n-1);
  deftop: integer;                              Obradalinije := false                          rep := copy(linija, n +
  glavnadat: Boolean;                        else                                                 Length(definicije[i].ime),
  ObradaLinije: Boolean;                        ObradaLinije := true;                             Length(linija));
                                             linija := '';                                     linija := glava;
procedure InitPp;                          end;                                                for j := definicije[i].pocetak
begin                                                                                             + 1 to
  bafertop := 0;                           procedure PpNePostoji;                                 definicije[i].kraj do
  deftop := 0;                             var                                                    linija := linija + bafer[j];
  glavnadat := true;                         imes: string;                                     linija := linija + rep;
  ObradaLinije := true;                      postoji: Boolean;                                 mijenjano:=true;
end;                                         i: integer;                                     end;
                                           begin                                        until n <= 0;
procedure PpDefin;                           imes := copy(linija, 12,                until not(mijenjano)
var                                             Length(linija) - 11);              end;
  duz, i, n: integer;                        postoji := false;
  radi: Boolean;                             for i := 1 to deftop do               procedure Novi;
  imes: string;                                 if definicije[i].ime = imes then   begin
                                                  postoji := true;                   repeat
begin                                        if postoji then                            pozicija := pozicija + 1;
  duz := Length(linija);                        Obradalinije := false                   if pozicija > Length(linija) then
  if deftop < MAXDEFINICIJE then             else                                         begin
    deftop := deftop + 1;                       ObradaLinije := true;                     brojaclinija := brojaclinija + 1;
  n := 12;                                   linija := '';                                if glavnadat and not (Eof(ulaz))
  imes := '';                              end;                                              then begin
  radi := true;                                                                              ReadLn(ulaz, linija);
  while (n <= duz) and radi do begin     procedure Predprocesiraj;                           Predprocesiraj;
    if linija[n] in ['a'..'z', 'A'..'Z'] var                                              end
       then                                i, n, j, duz: integer;                         else begin
       imes := imes + linija[n]            imes, glava, rep: string;                         if not (glavnadat) and not
    else                                   mijenjano: Boolean;                                 (Eof(privulaz)) then begin
       radi := false;                    begin                                                 ReadLn(privulaz, linija);
    n := n + 1;                            if linija = '#dalje' then begin                     Predprocesiraj;
  end;                                       obradalinije := true;                           end
  if imes <> '' then begin                   linija := '';                                   else begin
    definicije[deftop].ime := imes;        end;                                                if not (glavnadat) then begin
    definicije[deftop].pocetak :=          if not (obradalinije) then                             glavnadat := true;
       bafertop;                             linija := '';                                        Close(privulaz);
    radi := true;                          duz := Length(linija);                              end;
    while radi do begin                    if duz > 11 then                                  end;
       radi := false;                        if copy(linija, 1, 11) =                     end;
       if Length(linija) > 0 then               '#definiraj ' then                        Emit(';' + copy(linija, 1, 250));
         if linija[Length(linija)] = '\'        PpDefin;                                  pozicija := 1;
            then begin                     if duz > 9 then                              end;
            radi := true;                    if copy(linija, 1, 9) = '#postoji '        if Length(linija) > 0 then
            linija := copy(linija, 1,           then                                      znak := linija[pozicija]
              Length(linija) - 1);              PpPostoji;                              else
         end;                              if duz > 11 then                               znak := ' ';
       for i := n to Length(linija) do       if copy(linija, 1, 11) =                   if (znak = '`') then
         begin                                  '#nepostoji ' then                        pozicija := Length(linija);
         if bafertop < MAXCHAR then             PpNePostoji;                         until ((znak > ' ') and (znak <>
            bafertop := bafertop + 1;                                                   '`')) or Eof(ulaz);
         bafer[bafertop] := linija[i];     if duz > 7 then                         end;
         n := 1;                             if (copy(linija, 1, 7) = '#dodaj ')
       end;                                     and glavnadat then begin           end.
       if radi then begin                       imes := copy(linija, 8,
                                                               93
Prilog 10: Verzija izvornog koda kompajlera br. 8, postprocesor-optimizator
unit postpr8;                               radi: Boolean;                               begin
interface                                 begin                                            if (c1 = 'EAX') then
procedure Emit(st: string);                 pt := 1;                                          breax := true;
var                                         pu := 1;                                       if (c1 = 'EBX') then
  izlaz: text;                              char1 := '';                                      brebx := true;
                                            char2 := '';                                   incsp := 4;
implementation                              radi := true;                                end;
const                                       if Length(tekst) = 0 then
  dubina = 15;                                 radi := false;                            procedure PushSt(var c1, c2: string; var
  da = true;                                if uporedba = tekst then                       incsp: integer; var koreax, korebx:
  ne = false;                                  Uzorak := true                              Boolean);
                                            else begin                                   begin
var                                            while (pu <= Length(uporedba)) and          if Pos('EAX', c1) > 0 then
  bafer: array[1..dubina] of string;             radi do begin                                koreax := true;
  vrhbafera: integer;                            if uporedba[pu] = '$' then begin          if Pos('EBX', c1) > 0 then
  briseeax, koristieax, briseebx,                   pu := pu + 1;                             korebx := true;
    koristiebx, koristifpu: Boolean;                case uporedba[pu] of                   incsp := -4;
  dubinasteka: integer;                               'C': begin                         end;
                                                           pu := pu + 1;
function StrToInt(st: string): integer;                    case uporedba[pu] of          procedure AddSubst(var c1, c2: string;
var                                                          '1': begin                    var incsp: integer; var koreax,
  i, s, rez: integer;                                             KarakterSl(char1,      korebx:
begin                                                                radi, tekst, pt);     Boolean; sub: Boolean);
  rez := 0;                                                     end;                     begin
  if st[1] = '-' then                                        '2': begin                    if c1 = 'ESP' then
     s := 2                                                       KarakterSl(char2,           incsp := StrToInt(c2);
  else                                                               radi, tekst, pt);     if sub then
     s := 1;                                                    end;                          incsp := -incsp;
  for i := s to Length(st) do                              end;                            if (Pos('EAX', c1) > 0) or
     rez := 10 * rez + (ord(st[i]) -                    end;                                  (Pos('EAX', c2) > 0)
       ord('0'));                                     'N': begin                              or (c1 = 'AL') or (c2 = 'AL') then
  if st[1] = '-' then                                      pu := pu + 1;                      koreax := true;
     rez := -rez;                                          case uporedba[pu] of            if (Pos('EBX', c1) > 0) or
  StrToInt := rez;                                           '1': begin                       (Pos('EBX', c2) > 0)
end;                                                              BrojSl(char1, radi,          or (c1 = 'BL') or (c2 = 'BL') then
                                                                     tekst, pt);              korebx := true;
procedure KarakterSl(var char1: string;                         end;                     end;
  var radi: Boolean; tekst: string; var                      '2': begin
     pt: integer);                                                BrojSl(char2, radi,    procedure LogicalSt(var c1, c2: string;
var                                                                  tekst, pt);           var koreax, korebx: Boolean);
  radi2: Boolean;                                               end;                     begin
begin                                                      end;                            if (Pos('EAX', c1) > 0) or
  char1 := '';                                          end;                                  (Pos('EAX', c2) > 0)
  radi2 := true;                                    end                                       or (c1 = 'AL') or (c2 = 'AL') then
  if pt > Length(tekst) then                     end                                          koreax := true;
     radi := false                               else begin                                if (Pos('EBX', c1) > 0) or
  else                                              if uporedba[pu] <> tekst[pt]              (Pos('EBX', c2) > 0) or
     while radi2 do begin                             then                                  (c1 = 'BL') or (c2 = 'BL')
       char1 := char1 + tekst[pt];                    radi := false;                       then
       pt := pt + 1;                                pt := pt + 1;                             korebx := true;
       if pt > Length(tekst) then                end;                                    end;
          radi2 := false                         pu := pu + 1;
       else begin                              end;                                      procedure SkokSt(var breax, brebx,
          if tekst[pt] = ',' then              Uzorak := radi;                             korfp: Boolean);
            radi2 := false                  end;                                         begin
       end;                               end;                                             breax := true;
     end;                                                                                  brebx := true;
end;                                      procedure Status(breax, koreax, brebx,           korfp := true;
                                            korebx: Boolean;                             end;
procedure BrojSl(var char1: string;         dubst: integer; korfpu: Boolean);
  var radi: Boolean; tekst: string; var   begin                                          procedure DivMulSt(var koreax, korebx:
     pt: Integer);                          briseeax := breax;                             Boolean; var c1: string);
var                                         koristieax := koreax;                        begin
  radi2: Boolean;                           briseebx := brebx;                             koreax := true;
begin                                       koristiebx := korebx;                          if (Pos('EBX', c1) > 0) then
  char1 := '';                              koristifpu := korfpu;                             korebx := true;
  radi2 := true;                            dubinasteka := dubinasteka + dubst;          end;
  if pt > Length(tekst) then              end;
     radi := false                                                                       procedure ObradiStanje(tr: string);
  else begin                              procedure LeaMovSt(var c1, c2: string;         var
     if (tekst[pt] < '0') or (tekst[pt] >   var koreax, korebx, breax, brebx:              c1, c2: string;
       '9') then                               Boolean);                                   breax, koreax, brebx, korebx, korfp:
       radi := false;                     begin                                              Boolean;
     while radi2 do begin                   if (c1 = 'EAX') or (c1 = 'AL') then            incsp: integer;
       char1 := char1 + tekst[pt];             breax := true;                              prvoslovo, drugoslovo: char;
       pt := pt + 1;                        if (c1 = 'EBX') or (c1 = 'BL') then          begin
       if pt > Length(tekst) then              brebx := true;                              breax := false;
          radi2 := false                    if ((Pos('EAX', c1) > 0) and (c1 <>            koreax := false;
       else begin                              'EAX'))                                     brebx := false;
          if (tekst[pt] < '0') or              or (Pos('EAX', c2) > 0)                     korebx := false;
            (tekst[pt] > '9') then             or (c2 = 'AL') then                         incsp := 0;
            radi2 := false                     koreax := true;                             korfp := true;
       end;                                 if ((Pos('EBX', c1) > 0) and (c1 <>            if Length(tr) > 3 then begin
     end;                                      'EBX'))                                       prvoslovo := tr[2];
  end                                          or (Pos('EBX', c2) > 0) or                    drugoslovo := tr[3];
end;                                         (Pos('BL', c2) > 0) then                      end
                                               korebx := true;                             else begin
function Uzorak(uporedba, tekst:          end;                                               prvoslovo := ' ';
  string;                                                                                    drugoslovo := ' ';
  var char1, char2: string): Boolean;     procedure PopSt(var c1, c2: string; var          end;
var                                         incsp: integer; var breax, brebx:
  pu, pt: integer;                          Boolean);                                      if prvoslovo < 'K' then
                                                                94
      case prvoslovo of                                  DivMulSt(koreax, korebx, c1)                        else if
        'A': begin                                    end;                                                      Uzorak(' SETNE AL',tr,
            if Uzorak(' ADD $C1,$C2', tr,          'J': begin                                                   c1, c2) then
               c1, c2) then                             if Uzorak(' JMP $C1', tr, c1,                           breax := true
               AddSubst(c1, c2, incsp,                     c2) then                                        end;
                 koreax, korebx, false)                    SkokSt(breax, brebx, korfp)                   'U': begin
            else if                                     else if Uzorak(' JNE $C1',                           if
               Uzorak(' AND $C1,$C2', tr,                  tr, c1, c2) then                                     Uzorak(' SUB $C1,$C2',
               c1, c2) then                                SkokSt(breax, brebx, korfp)                          tr, c1, c2) then
               LogicalSt(c1, c2, koreax,              end;                                                      AddSubst(c1, c2,
                 korebx)                         end;                                                             incsp, koreax,
          end;                                 if prvoslovo >= 'K' then                                           korebx, true)
        'C': begin                               case prvoslovo of                                         end
            if Uzorak(' CALL $C1', tr,                                                                end
               c1, c2) then                        'L': begin                                       end;
               SkokSt(breax, brebx, korfp)             if Uzorak(' LEA $C1,$C2', tr,             'X': begin
            else if Uzorak(' CDQ', tr,                    c1, c2) then                                if Uzorak(' XOR $C1,$C2', tr,
               c1, c2) then                               LeaMovSt(c1, c2, koreax,                       c1, c2) then
               koreax := true                               korebx, breax, brebx)                        LogicalSt(c1, c2, koreax,
            else if Uzorak(' CLD', tr,               end;                                                  korebx)
               c1, c2) then                        'M': begin                                       end;
               c1 := c1                                if Uzorak(' MOV $C1,$C2', tr,           end;
            else if                                       c1, c2) then                      Status(breax, koreax, brebx, korebx,
               Uzorak(' CMP $C1,$C2', tr,                 LeaMovSt(c1, c2, koreax,             incsp, korfp);
               c1, c2) then                                 korebx, breax, brebx)         end;
               LogicalSt(c1, c2, koreax,               else if Uzorak(' MUL $C1',
                 korebx)                                  tr, c1, c2) then                procedure Dump(what: string; j, i:
          end;                                            DivMulSt(koreax, korebx, c1)      integer);
        'F': begin                                   end;                                 var
            case drugoslovo of                     'N': begin                               k: integer;
               'A': begin                              if Uzorak(' NEG $C1', tr, c1,      begin
                   if Uzorak(' FADD ', tr,                c2) then                          WriteLn(what);
                      c1, c2) then                        LogicalSt(c1, c2, koreax,         for k := j to i do
                      korfp := true                         korebx)                            WriteLn(k, bafer[k]);
                 end;                                  else if Uzorak(' NOT $C1',           ReadLn;
               'C': begin                                 tr, c1, c2) then                end;
                   if Uzorak(' FCHS', tr,                 LogicalSt(c1, c2, koreax,
                      c1, c2) then                          korebx)                       procedure Obrisi(n: integer);
                      korfp := true                  end;                                 var
                   else if                         'O': begin                               i: integer;
                      Uzorak(' FCOMPP ', tr,           if Uzorak(' OR $C1,$C2', tr,       begin
                      c1, c2) then                        c1, c2) then                      for i := n + 1 to dubina do
                      korfp := true                       LogicalSt(c1, c2, koreax,            bafer[i - 1] := bafer[i];
                 end;                                       korebx)                         vrhbafera := vrhbafera - 1;
               'D': begin                            end;                                 end;
                   if Uzorak(' FDIVR ',            'P': begin
                      tr, c1, c2) then                 if Uzorak(' POP $C1', tr, c1,      procedure PushEaxOptim(pusheax:
                      korfp := true                       c2) then                          Boolean; var j: integer);
                 end;                                     PopSt(c1, c2, incsp, breax,     var
               'I': begin                                   brebx)                          i: integer;
                   if Uzorak(' FILD $C1',              else if Uzorak(' PUSH $C1',          izlaz, mebx, meax: Boolean;
                      tr, c1, c2) then                    tr, c1, c2) then
                      korfp := true                       PushSt(c1, c2, incsp,           begin
                   else if                                  koreax, korebx)                 dubinasteka := 0;
                      Uzorak(' FINIT', tr,           end;                                   Status(ne, ne, ne, ne, 0, ne);
                      c1, c2) then                 'R': begin                               izlaz := false;
                      korfp := true                    if Uzorak(' REP MOVSB', tr,          meax := false;
                   else if                                c1, c2) then                      mebx := false;
                      Uzorak(' FISTP $C1',                c1 := c1                          i := j;
                      tr, c1, c2) then                 else if Uzorak(' RET $N1',           repeat
                      korfp := true                       tr, c1, c2) then                     i := i + 1;
                 end;                                     incsp := StrToInt(c1) + 4            if i >= vrhbafera then
               'L': begin                            end;                                        izlaz := true;
                   if Uzorak(' FLD $C1',           'S': begin                                  if (dubinasteka = 0) and not (izlaz)
                      tr, c1, c2) then                 case drugoslovo of                        then begin
                      korfp := true                       'A': begin                             if (bafer[i] = ' POP EAX') and
                 end;                                         if Uzorak(' SAHF', tr,                not (meax) then begin
               'M': begin                                        c1, c2) then             //dump('Nepotrebno PUSH/POP EAX',j,i);
                   if Uzorak(' FMUL ', tr,                       koreax := true                     Obrisi(i);
                      c1, c2) then                            else if                               if pusheax then
                      korfp := true                              Uzorak(' SAL EAX,$N1',               Obrisi(j)
                 end;                                            tr, c1, c2) then                   else
               'S': begin                                        koreax := true                       bafer[j] := ' MOV EAX,EBX';
                   if Uzorak(' FSTP $C1',                   end;                                    izlaz := true;
                      tr, c1, c2) then                    'E': begin                             end;
                      korfp := true                           if Uzorak(' SETA AL',              if (bafer[i] = ' POP EBX') and
                   else if                                       tr, c1, c2) then                   not (mebx) then begin
                      Uzorak(' FSTSW AX',                        breax := true            //dump('Nepotrebno PUSH /POP EBX',j,i);
tr,                                                           else if                               Obrisi(i);
                    c1, c2) then                                 Uzorak(' SETB AL', tr,             if pusheax then
                    korfp := true                                c1, c2) then                         bafer[j] := ' MOV EBX,EAX'
                  else if                                        breax := true                      else
                    Uzorak(' FSUBR ', tr,                     else if                                 Obrisi(j);
                    c1, c2) then                                 Uzorak(' SETE AL', tr,             izlaz := true;
                    korfp := true                                c1, c2) then                    end;
                end                                              breax := true                 end;
            end                                               else if                          if not (izlaz) then
          end;                                                   Uzorak(' SETG AL', tr,          ObradiStanje(bafer[i]);
        'I': begin                                               c1, c2) then                  if briseeax and not (meax) then
            if Uzorak(' IDIV $C1', tr,                           breax := true                   meax := true;
               c1, c2) then                                   else if                          if briseebx and not (mebx) then
               DivMulSt(koreax, korebx, c1)                      Uzorak(' SETL AL', tr,          mebx := true;
            else if Uzorak(' IMUL $C1',                          c1, c2) then               until izlaz;
               tr, c1, c2) then                                  breax := true            end;
                                                                 95
                                                zaebx := true                               if (bafer[j] = ' MOV EAX,EAX') or
procedure LeaEbxOptim(var j: integer;         else                                             (bafer[j] = ' MOV EBX,EBX') or
  adresa: string);                              izlaz := true;                                 (bafer[j] = ' ADD EAX,0') or
var                                                                                            (bafer[j] = ' ADD EBX,0') then begin
  i, k, n: integer;                            i := j;                                    // dump('Nepotrebna instrukcija',j,j);
  c1, c2, p: string;                           repeat                                          Obrisi(j);
  izlaz: Boolean;                                 i := i + 1;                               end
                                                  if i >= vrhbafera then                  end;
begin                                               izlaz := true;
  dubinasteka := 0;                               if not (izlaz) then begin               procedure Parovi(var j: integer);
  Status(ne, ne, ne, ne, 0, ne);                    ObradiStanje(bafer[i]);               var
  izlaz := false;                                   if zaeax then begin                     c1, c2, c3, c4, nep, st: string;
  i := j;                                             if koristieax then                  begin
  if i + 1 < vrhbafera then                              izlaz := true;                     nep := 'Nepotreban par';
     if Uzorak(' PUSH EBX', bafer[i +                 if briseeax then begin                if bafer[j][1] = 'M' then begin
       1], c1, c2) then begin                //dump(' Nepotrebno MOV EAX ',j,i);              if Uzorak(' MOV $C1,$C2', bafer[j],
       ObradiStanje(bafer[i + 1]);                       Obrisi(j);                              c1, c2)
       i := i + 2;                                       izlaz := true;                          and Uzorak(' MOV $C1,$C2', bafer[j
       repeat                                         end;                                         + 1], c3, c4) then begin
          if i >= vrhbafera then                    end;                                         if ((c1 = c4) and (c2 = c3)) or
            izlaz := true;                          if zaebx then begin                            ((c1 = c3) and (c2 = c4)) then
          if not (izlaz) then                         if koristiebx then                              begin
            ObradiStanje(bafer[i]);                      izlaz := true;                   // dump(nep,j,j+1);
          if (dubinasteka = 0) and not                if briseebx then begin                       Obrisi(j + 1);
            (izlaz) then                     //dump(' Nepotrebno MOV EBX ',j,i);                 end;
            if Uzorak(' POP EBX',                        Obrisi(j);                           end
               bafer[i], c1, c2) then begin              izlaz := true;                       else if Uzorak(' MOV $C1,$N2',
//dump('Nepotrebno LEA/PUSH/POP',j,i);                end;                                       bafer[j], c1, c2)
               bafer[i] := ' LEA EBX,' +            end;                                         and Uzorak(' ADD $C1,$N2', bafer[j
                 adresa;                                                                           + 1], c3, c4) then begin
               Obrisi(j + 1);                     end                                            if c1 = c3 then begin
               Obrisi(j);                      until izlaz;                               // dump(nep,j,j+1);
               izlaz := true;                end;                                                  Str(StrToInt(c2) +
            end;                                                                                      StrToInt(c4), st);
          i := i + 1;                        procedure FldOptim(var j: integer);                   bafer[j] := ' MOV ' + c1 + ','
       until izlaz;                          var                                                      + st;
     end                                       i: integer;                                         Obrisi(j + 1);
     else begin                                izlaz: Boolean;                                   end;
       i := i + 1;                           begin                                            end
       repeat                                  Status(ne, ne, ne, ne, 0, ne);                 else if Uzorak(' MOV $C1,$N2',
          if i >= vrhbafera then               izlaz := false;                                   bafer[j], c1, c2) and
            izlaz := true;                     i := j;                                           (bafer[j + 1] = ' NEG AX') then
          if not (izlaz) then                  repeat                                              begin
            ObradiStanje(bafer[i]);               i := i + 1;                             // dump(nep,j,j+1);
          if (koristiebx) and not (izlaz)         if i >= vrhbafera then                         bafer[j] := ' MOV ' + c1 + '-' +
            then begin                              izlaz := true;                                 c2;
            if Pos('[EBX]', bafer[i]) < 1         if not (izlaz) then begin                      Obrisi(j + 1);
               then                                 ObradiStanje(bafer[i]);                   end;
               izlaz := true;                       if koristifpu then                      end
          end;                                        izlaz := true;                        else if Uzorak(' ADD $C1,$N2',
          if (briseebx) and not (izlaz)             if bafer[i] = ' FSTP ST(0)' then          bafer[j], c1, c2)
            then begin                                begin                                   and Uzorak(' ADD $C1,$N2', bafer[j
// dump('Nasao nepotrebno LEA',j,i);         //dump(' Nepotrebno FLD/FSTP ',j,i);                + 1], c3, c4) then begin
            for k := j + 1 to i - 1 do                Obrisi(i);                              if c1 = c3 then begin
               begin                                  Obrisi(j);                          // dump(nep,j,j+1);
               n := Pos('[EBX]',                      izlaz := true;                             Str(StrToInt(c2) + StrToInt(c4),
                 bafer[k]);                         end;                                           st);
               if n >= 1 then begin                 if (i < vrhbafera - 1) and not               bafer[j] := ' ADD ' + c1 + ',' +
                 if Pos('EAX', bafer[k]) >            (izlaz) then                                 st;
                    0 then                            if (bafer[i] = ' ADD ESP,-8')              Obrisi(j + 1);
                    p := 'DWORD PTR '                    and                                  end;
                 else                                    (bafer[i + 1] =                    end;
                    p := '';                               ' FSTP QWORD PTR [ESP]')
                 bafer[k] :=                 then                                         end;
                    copy(bafer[k], 1, n - 1)               begin
                    + p + adresa +                       i := i + 2;                      procedure Trojke(var j: integer);
                    copy(bafer[k], n + 5,                dubinasteka := 0;                var
                      Length(bafer[k]) - n -             while (i < vrhbafera - 1) and      c1, c2, c3, c4, c5, c6, nep: string;
                      4);                                  not (izlaz) do begin           begin
               end;                                        ObradiStanje(bafer[i]);          nep := 'Nepotrebna trojka';
            end;                                           if (bafer[i] =                   if Uzorak(' MOV $C1,$C2', bafer[j],
            Obrisi(j);                                        ' FLD QWORD PTR [ESP]')         c1, c2)
            izlaz := true;                                    and (bafer[i + 1] =             and Uzorak(' MOV $C1,$C2', bafer[j
          end;                                                  ' ADD ESP,8') and               + 2], c5, c6)
          i := i + 1;                                         (dubinasteka = 0) then      // Izvrnuto zbog brzine
       until izlaz;                                             begin                       and (
     end;                                    // dump('Nepotr. FP na ESP stek',j,i+1);         (Uzorak(' ADD $C1,$C2', bafer[j +
                                                              bafer[i + 1] := bafer[j];         1], c3, c4)) or
end;                                                          Obrisi(i);                      (Uzorak(' AND $C1,$C2', bafer[j +
                                                              Obrisi(j + 2);                    1], c3, c4)) or
procedure MovViskaOptim(var j: integer;                       Obrisi(j + 1);                  (Uzorak(' SUB $C1,$C2', bafer[j +
  c1: string);                                                Obrisi(j);                        1], c3, c4)) or
var                                                           izlaz := true;                  (Uzorak(' XOR $C1,$C2', bafer[j +
  i: integer;                                              end;                                 1], c3, c4)) or
  izlaz, zaeax, zaebx: Boolean;                            i := i + 1;                        (Uzorak(' MOV $C1,$C2', bafer[j +
                                                         end;                                   1], c3, c4)) or
begin                                                                                         (Uzorak(' OR $C1,$C2', bafer[j +
  Status(ne, ne, ne, ne, 0, ne);                      end;                                      1], c3, c4))) then begin
  izlaz := false;                                 end                                         if (c1 = c4) and (c1 = c5) then
  zaeax := false;                              until izlaz;                                     begin
  zaebx := false;                            end;                                         // dump(nep,j,j+2);
  if (c1 = 'EAX') or (c1 = 'AL') then                                                           if copy(bafer[j + 1], 2, 2) <>
     zaeax := true                           procedure Jednostruke(var j: integer);               'OR' then
  else if c1 = 'EBX' then                    begin                                                bafer[j + 1] := copy(bafer[j +
                                                           96
          1], 1, 5) + c3 + ',' + c2        end;
       else                                bafer[vrhbafera] := st;
          bafer[j + 1] := copy(bafer[j +   if Length(st) >= 3 then
            1], 1, 4) + c3 + ',' + c2;       if copy(st, 1, 3) = 'END' then begin
       Obrisi(j);                               Optimizuj;
     end;                                       for i := 1 to vrhbafera do
  end;                                            WriteLn(izlaz, bafer[i]);
end;                                         end

procedure Cetvorke(var j: integer);       end;
var
  c1, c2, c3, c4, c5, c6, c7, c8, nep:    end.
     string;
begin
nep := 'Nepotrebna cetvorka';
  if Uzorak(' PUSH $C1', bafer[j], c1,
     c2)
     and Uzorak(' POP $C1', bafer[j +
       3], c7, c8) // Izvrnuto zbog
brzine
  and Uzorak(' MOV $C1,$C2', bafer[j +
     1], c3, c4)
     and Uzorak(' MOV $C1,$C2', bafer[j
       + 2], c5, c6)
     and (c1 = c5) and (c3 = c6) and (c6
       = c7) then begin
// dump(nep,j,j+4);
     if (Pos('DWORD', c4) < 1) and (c4 <>
       'EAX') and
       (c4 <> 'EBX') and (c4 <> 'ECX')
         then
       c4 := 'DWORD PTR ' + c4;
     bafer[j] := ' MOV ' + c3 + ',' +
       c1;
     bafer[j + 1] := ' MOV ' + c1 + ','
       + c4;
     Obrisi(j + 3);
     Obrisi(j + 2);
  end;
end;

procedure Optimizuj;
var
  c1, c2: string;
  j: integer;
begin

  j := 1;
  while j <= vrhbafera - 1 do begin
    if (Length(bafer[j]) > 3) and
      (bafer[j][1] = ' ') then begin
      if Uzorak(' PUSH EAX', bafer[j],
        c1, c2) then
        PushEaxOptim(true, j);
      if Uzorak(' PUSH EBX', bafer[j],
        c1, c2) then
        PushEaxOptim(false, j);
      if Uzorak(' MOV $C1,$C2',
        bafer[j], c1, c2) then
        MovViskaOptim(j, c1);
      if Uzorak(' LEA EBX,$C1',
        bafer[j], c1, c2) then
        LeaEbxOptim(j, c1);
      if Uzorak(' FLD $C1', bafer[j],
        c1, c2) then
        FldOptim(j);
      if j < vrhbafera - 3 then
        Cetvorke(j);
      if j < vrhbafera - 2 then
        Trojke(j);
      if j < vrhbafera - 1 then
        Parovi(j);

       Jednostruke(j);
     end;
     j := j + 1;
  end;
end;

procedure Emit(st: string);
var
  i: integer;
begin
  if st = '.486' then begin
    vrhbafera := 0;
    dubinasteka := 0;
  end;
  vrhbafera := vrhbafera + 1;
  if vrhbafera >= dubina then
    Optimizuj;
  if vrhbafera > dubina then begin
    WriteLn(izlaz, bafer[1]);
    Obrisi(1);
    vrhbafera := dubina;
                                              97
Prilog 11: Prikaz finalne verzije jezika FILDZAN-32 u EBNF
Program = { (DeklaracijaVarijabli | DeklaracijaFunkcije) }
   "{" ( {DeklaracijaVarijabli} Blok | "}" ) .
DeklaracijaVarijabli = ImeTipa Identifikator { "," Identifikator } ";"
  { ImeTipa Identifikator { "," Identifikator } ";"} .
ImeTipa = ( "cijeli" ["*"] [DeklaracioniDimenzijskiModifikator] |
  "realni" ["*"] [DeklaracioniDimenzijskiModifikator] |
  "karakter" ["*"] [DeklaracioniDimenzijskiModifikator] |
  "slog" ["*"] DeklaracijaSloga [DeklaracioniDimenzijskiModifikator] ) .
DeklaracijaFunkcije = ImeTipa "funkcija" Identifikator
  "(" [ ImeTipa Identifikator { "," ImeTipa Identifikator } ] ")"
   ( ";" | "{" [DeklaracijaVarijabli] Blok ) .
DeklaracioniDimenzijskiModifikator = "[" NumerickaKonstanta
  { "," NumerickaKonstanta } "]" .
DeklaracijaSloga = "{" ImeTipa Identifikator { "," Identifikator } ";"
  { ImeTipa Identifikator { "," Identifikator } ";" } "}" .
Blok = { ( "dok" Petlja |
  "ako" Uslov |
  IzrazDodjeljivanja ";" |
  "asembler" AsemblerskiModul) } "}" .
Uslov = IzrazDodjeljivanja "{" Blok [ "inace" "{" Blok ] .
Petlja = IzrazDodjeljivanja "{" Blok .
AsemblerskiModul = {BiloKojiZnak} "\" .
IzrazDodjeljivanja = Izraz [ ( ("="| "#" | ">" | "<" ) Izraz |
  ":=" IzrazDodjeljivanja ) ] .
Izraz = Clan { ("-" | "+" | "&" | "|" | "^") Clan } .
Clan = Faktor { ("*" | "/" | "%") Faktor } .
Faktor = ( ("-" | "~" | "&" | "*" | "!") Faktor | NumerickaKonstanta |
  "(" IzrazDodjeljivanja ")" |   Varijabla | '"' StringKonstanta |
  PozivFunkcije | "'" BiloKojiZnakOsimNavodnika "'" )
  [( "." Identifikator | ListaIndeksa ) { ( "." Identifikator | ListaIndeksa ) } ) ].
Varijabla = Identifikator
  [ ( "(" [ IzrazDodjeljivanja { "," IzrazDodjeljivanja } ] ")" .
StringKonstanta = { BiloKojiZnakOsimNavodnika } '"' .
ListaIndeksa = "[" IzrazDodjeljivanja { "," IzrazDodjeljivanja } "]" .
PozivFunkcije = Identifikator "(" [ IzrazDodjeljivanja { "," IzrazDodjeljivanja } ]
")" .
NumerickaKonstanta = Cifra { Cifra } [ "." Cifra { Cifra } ]
  [ "E" [ ( "+" | "-" )] Cifra { Cifra } ] .
Identifikator = Slovo { Slovo | Cifra | "_" } .
Slovo = ("A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" |
   "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" |
   "X" | "Y" | "Z" | "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
   "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" |
   "v" | "w" | "x" | "y" | "z" ) .
Cifra = ("0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ) .
BiloKojiZnakOsimNavodnika = (Slovo | Cifra | "~" | "!" | "@" | "#" | "$" |
   "%" | "^" | "&" | "*" | "(" | ")" | "-" | "_" | "=" | "+" | "[" | "{" |
   "]" | "}" | "|" | "\" | ":" | ";" | "<" | "," | "." | ">" | "/" | "?" |
   "`" | ")" ) .
BiloKojiZnak = (BiloKojiZnakOsimNavodnika | '"' | "'" ) .
                                                             98
13.TEORIJA JEZIKA I PARSIRANJA
         Kompajler razvijen u prethodnim poglavljima razvijen je spiralnom metodom, pri ĉemu je veća paţnja posvećivana
generisanju koda nego sintaksnoj i semantiĉkoj analizi. U sloţenijim kompajlerima sintaksna analiza moţe biti veoma
zahtjevna, i ova slika o razvoju kompajlera neće biti kompletna bez uvoda u teoriju formalnih gramatika i parsiranja.


13.1.    Formalne gramatike
          Formalna gramatika je naĉin opisa formalnog jezika, tj. skupa nizova simbola sastavljenih iz odreĊenog konaĉnog
alfabeta. Ime je dobila formalna gramatika zbog analogije sa konceptom gramatike u ljudskim jezicima.
         Osnovna ideja iza ovih gramatika je da se generišu nizovi znakova koji poĉinju specijalnim startnim simbolom i
primjene pravila koja odreĊuju kako se odreĊena kombinacija simbola moţe zamijeniti drugom kombinacijom simbola. Na
primjer, ako se alfabet sastoji od znakova 'a' i 'b', a startni simbol je 'S', uz sljedeća pravila:
        1. S -> aSb
        2. S -> ba
         tada se moţe napisati "S" kao "aSb" zamjenom simbola 'S' sa "aSb" (pravilo 1), a zatim prepisati "aSb" kao "aaSbb"
primjenom istog pravila. To se ponavlja sve dok rezultat ne sadrţi samo simbole iz alfabeta. U našem primjeru moţe se dalje
prepisati S kao što slijedi: S -> aSb -> aaSbb -> aababb. Jezik ove gramatike se onda sastoji od svih stringova koji se mogu
generisati na ovaj naĉin: ba, abab, aababb, aaababbb, itd.


13.2.    Kontekstno osjetljiva gramatika
        Kontekstno osjetljiva gramatika je formalna gramatika G = (N, T, P, S) ĉija su sva pravila P oblika
        αAβ -> αγβ
         gdje A neterminalni simbol, α i β su nizovi neterminalnih i terminalnih simbola, a γ neprazan niz neterminalnih i
terminalnih simbola , uz dodatno pravilo koje je dopušteno ako se S ne nalazi sa desne strane nijednog pravila:
        S -> ε
        Gdje je ε prazan niz
        Pojam “Kontekstno osjetljiva” potiĉe od ĉinjenice da α i β definišu kontekst u kome se A moţe transformisati sa γ ili
ne. To je razliĉito od kontekstno slobodnih gramatika gdje se kontekst neterminalnih simbola ne uzima u razmatranje.
Formalni jezik opisan kontekstno osjetljivom gramatikom se naziva kontekstno osjetljiv jezik.
        U prirodnim jezicima je ĉest sluĉaj da rijeĉ nije odgovarajuća na odreĊenom mjestu u datom kontekstu.


13.3.    Nesaţimajuća gramatika
         Druga definicija kontekstno osjetljive gramatike definiše je kao formalnu gramatiku koja ima ograniĉenje na pravila
α -> β u skupu P tako da je | α | ≤ | β | gdje je | α | duţina simbola α. Takva gramatika se zove nesaţimajuća gramatika jer
nijedno od pravila ne smanjuje veliĉinu niza simbola koji se razvija.
        Iako razliĉite, kontekstno osjetljiva i nesaţimajuća gramatika su ekvivalentne jer definišu istu klasu jezika osim što
nesaţimajuća gramatika ne moţe generisati jezik koji sadrţi simbol praznog prostora. Ali, ako se jezik L moţe opisati
kontekstno osjetljivom gramatikom, on se (izuzev praznog simbola) moţe predstaviti i nesaţimajućom gramatikom.


13.4.    Kontekstno slobodna gramatika
        Kontekstno slobodna gramatika je formalna gramatika ĉija su sva pravila oblika:
        V -> w
         Gdje je V neterminalni simbol, a w niz koji se sastoji od terminalnih i/ili neterminalnih. Pojam kontekstno slobodna
znaĉi da se varijabla V uvijek moţe zamijeniti sa w, bez obzira u kojem je kontekstu. Formalni jezik je kontekstno slobodan
ako postoji kontekstno slobodna gramatika koja ga generiše.
         Kontekstno slobodnom gramatikom se definišu gotovo svi programski jezici i na bazi nje se prave parseri/sintaksni
analizatori.


13.5.    Regularna gramatika
        Regularna gramatika je formalna gramatika u kojoj sva pravila imaju jedan od sljedećih oblika:
        A -> a gdje je A neterminalni simbol dok je a terminalni simbol
                                                              99
         A -> aB gdje su A i B neterminalni simbol dok je a terminalni simbol
         A -> ε gdje je A neterminalni simbol
         Alternativno, drugo pravilo se moţe pisati kao A -> Ba.
         Primjer: Gramatika G sa N = {S, A}, Σ = {a, b, c}, P pravila su
         S -> aS
         S -> bA
         A -> ε
         A -> cA
         i S kao startni simbol. Ova gramatika opisuje isti jezik kao regularni izraz a*bc*.
         Regularna gramatika opisuje konaĉne automate i regularne jezike. Koristi se u leksiĉkoj analizi.


13.6.     Parsiranje
         PrevoĊenje iz jednog jezika u drugi zahtjeva parsiranje. Parsiranje je proces identifikacije strukture podataka. Ono
odreĊuje da li ulazni podaci imaju odreĊenu strukturu. Da bi se obavilo parsiranje potrebna je gramatika, koja će definisati
skup pravila. Pravila su odreĊeni uzorci podataka koja dalje mogu da imaju reference na druga pravila. Zavisno od skupa
pravila mogu se definisati parseri odozgo prema dolje ili odozdo prema gore.


13.7.     LL Parsiranje
         Prevodilac ne generiše reĉenice u izvornom jeziku, nego ih prepoznaje. To znaĉi da koraci koji vode do konstrukcije
reĉenice moraju biti izvedeni iz gotove reĉenice. Dok je za jezike kao što je Pascal taj zadatak relativno jednostavan, dosta je
sloţen za jezike poput Fortrana ili C++a.
        Razvijajući programski jezik FILDZAN32 bez posebnog navoĊenja korišten je naĉin parsiranja odozgo nadolje,
takozvani rekurzivni silazak. Gramatike jezika Pascal i Modula 2 se definišu tako da se moţe primijeniti ovaj naĉin parsiranja.
          Suština metoda je da se kreće od startnog simbola (npr. “program”) i pokušava dobiti reĉenica primjenom sekvence
pravila. To se ĉini gledajući sljedeći terminalni simbol na ulazu.

Kao ilustracija ove metode neka posluţi sljedeća jednostavna gramatika:
               G   =   { N , T , S , P }
               N   =   { A , B }
               T   =   { x , y , z }
               S   =   A
               P   =
                       A :   xB            (1)
                       B :   z             (2)
                       B :   yB            (3)

Ako treba parsirati reĉenicu xyyz, koja je sastavljena od terminalnih simbola ove gramatike, kreće se od ciljnog simbola i
ulaznog niza

         Reĉeniĉka forma S = A             Ulazni niz   xyyz

Nad reĉeniĉkom formom 1 se primjeni jedino moguće pravilo (1) da se dobije

         Reĉeniĉka forma xB            Ulazni niz xyyz

Za sada je u redu, jer se slaţu poĉetni simboli reĉeniĉke forme i ulaznog niza. Stoga treba iz neterminalnog simbola B izvesti
yyz.

         Reĉeniĉka forma B             Ulazni niz yyz

Moţe se odabrati bilo pravilo (2) ili (3) u obradi neterminalnog simbola B, ali se iz ulaznog stringa vidi da je (3) pravi izbor.
Primjenom tog pravila dobija se:

         Reĉeniĉka forma yB            Ulazni niz yyz

Što znaĉi da se iz neterminalnog simbola B mora izvesti yz.

         Reĉeniĉka forma B             Ulazni niz yz

To nas ponovo vodi do pravila (3) i dobijamo
                                                                                 100
         Reĉeniĉka forma         yB               Ulazni niz yz
          što povlaĉi da se iz neterminalnog simbola B mora izvesti terminalni simbol z direktno, što se postiţe pravilom (2).
          Primjer reĉenica koje se ne mogu prepoznati ovom gramatikom su xxxx ili xyyyy.
         Ova metoda se zove LL(k) parsiranje. Naziv potiĉe od toga što se ulazni string skenira s lijeva na desno (prvo L)
primjenjujući pravila na prvi lijevi neterminalni simbol (drugo L) gledajući maksimalno k terminalnih simbola da se odredi
koje pravilo primijeniti u datom stanju. U našem primjeru, k=1, te LL(1) je najĉešći sluĉaj LL(k) parsiranja.
        Lako je napisati LL(1) parser, ali pisanje gramatike u takvom obliku zna biti sloţen posao, pogotovo što se ne moţe
svaka gramatika transformisati u ovaj oblik. Evo primjera kako se mogu vršiti potrebne transformacije da bi se dobila LL(1)
kompatibilna gramatika:

Neka je u nekoj gramatici REPEAT petlja predstavljena u obliku:
              RepeatStatement           =         "REPEAT" StatementSequence "UNTIL" Condition
                                              |    "REPEAT" StatementSequence "FOREVER" .

Oba oblika poĉinju rezervisanom rijeĉju REPEAT, što zbunjuje parser. Ali, ako se definiše:
              RepeatStatement           =     "REPEAT" StatementSequence TailRepeatStatement .
              TailRepeatStatement       =     "UNTIL" Condition | "FOREVER" .

nema problema s parsiranjem. No, u sljedećem sluĉaju
              Statement                 =     IfStatement | OtherStatement .
              IfStatement               =      "IF" Condition "THEN" Statement
                                              | "IF" Condition "THEN" Statement                    "ELSE"   Statement .

ĉak nakon rastavljanja pravila i dalje postoji neodreĊenost.
              Statement                 =     IfStatement | OtherStatement .                                  (1, 2)
              IfStatement               =     "IF" Condition "THEN" Statement                IfTail .         (3)
              IfTail                    =     "ELSE" Statement | e .                                          (4, 5)

Ova neodreĊenost se obiĉno rješava pravilom da ELSE se odnosi na zadnji THEN. U FILDZAN-32, ovaj problem je izbjegnut,
uvoĊenjem obaveznih vitiĉastih zagrada u naredbi ako.


13.8.         LR Parsiranje
          Drugi popularni naĉin parsiranja je LR(k) parsiranje. Ove oznake predstavljaju da se u ovoj metodi ulazni podaci
ĉitaju sa Lijeva na desno, razvijajući stalno krajnji desni (Right) simbol, gledajući unaprijed najviše k simbola. U praksi je k
najĉešće 1 ili 0.
         Tehnika je bazirana na principu odozdo nagore. Kreće se od ulazne sekvence i praveći redukcije, teţi se da se doĊe do
ciljnog simbola. Redukcija reĉenice se ne postiţe zamjenom desne strane pravila ĉija lijeva strana sadrţi odgovarajući
neterminalni simbol, nego zamjenom lijeve strane pravila koje se slaţe sa desnom stranom.
          Parsiranje odozdo nagore moţe koristiti stek za parsiranje koji sadrţi dio mogućih reĉeniĉnih formi terminalnih i
neterminalnih simbola. Svaki put kada se ĉita terminalni simbol iz ulaznog stringa, on se smješta na stek za parsiranje, zatim se
ispituju elementi na vrhu steka da se vidi da li se moţe obaviti redukcija. Neki terminalni simboli mogu dugo stojati na steku
sve dok se ne oslobode. To je razliĉito od parsera sa rekurzivnim spuštanjem koji oslobaĊa terminalne simbole ĉim ih je
proĉitao i koji smješta neterminalne komponente parcijalne reĉeniĉne forme samo implicitno kao niz nedovršenih poziva
potprograma za obradu neterminalnih simbola.
          Evo primjera za gramatiku koja nije LL(1) tipa definisanu kao
                     Goal           =       Expression "." .                              (1)
                     Expression     =       Expression "-" Term           |   Term .      (2, 3)
                     Term           =       "a"                                           (4)

I treba parsirati ulazni niz "a - a - a ." .

Ovo su akcije koje će se obaviti


        Step       Action        Using production                 Stack

          1         read     a                                    a
          2         reduce                    4                   Term
          3         reduce                    3                   Expression
          4         read     -                                    Expression     -
          5         read     a                                    Expression     - a
          6         reduce                    4                   Expression     - Term
          7         reduce                    2                   Expression
          8         read     -                                    Expression     -
          9         read     a                                    Expression     - a
         10         reduce                    4                   Expression     - Term
         11         reduce                    2                   Expression
         12         read     .                                    Expression     .
         13         reduce                    1                   Goal
                                                                    101
          Cilj je dostignut i reĉenica je ispravna
         Ipak, postavlja se pitanje u ovom primjeru zašto nije korišteno pravilo Goal=Expression kada je reduciran string "a" u
Expression nakon koraka 3? Da bi se primijenila redukcija, naravno da je potrebno da lijeva strana pravila bude na steku za
parsiranje, ali je samo po sebi nedovoljno. Kada postoji više mogućih desnih strana koje se slaţu sa elementima na vrhu steka
za parsiranje, pravi parser treba da primjeni odgovarajuću strategiju, gledajući unaprijed ulazni string da odluĉi koje će pravilo
primijeniti.
         Ovakvi parseri se upravljaju tablicama, gdje odgovarajuća strategija u odgovarajućem trenutku biva odreĊena
gledanjem u pravougaonu matricu, ĉija jedna dimenzija predstavlja stanje parsiranja (tj. poziciju koju je parser dosegao unutar
gramatiĉkih pravila) , a druga predstavlja trenutni simbol (tj. terminalni ili neterminalni simbol gramatike). Elementi tabele
prihvataju ulazni string kao korektan, odbacuju kao nekorektan, prelaze u druga stanja ili vrše redukciju primjenom
odgovarajućeg pravila. Umjesto smještanja na stek samih simbola kako je bilo navedeno u prethodnom primjeru, algoritam za
parsiranje smješta ili skida elemente koji predstavljaju stanje parsiranja - shift operacije koje smještaju novodosegnuto stanje
na stek i reduce operacije koje skidaju onoliko elemenata sa steka koliko je simbola na desnoj strani pravila koje se
primjenjuje. Algoritam se moţe opisati kao:


  BEGIN
    GetSYM(InputSymbol); (* first Sym in sentence *)
    State := 1; Push(State); Parsing := TRUE;
    REPEAT
      Entry := Table[State, InputSymbol];
      CASE Entry.Action OF
        shift:
           State := Entry.NextState; Push(State);
           IF IsTerminal(InputSymbol) THEN
             GetSYM(InputSymbol) (* accept *)
           END
        reduce:
           FOR I := 1 TO Length(Rule[Entry].RightSide) DO Pop END;
           State := Top(Stack);
           InputSymbol := Rule[Entry].LeftSide;
        reject:
           Report(Failure); Parsing := FALSE
        accept:
           Report(Success); Parsing := FALSE
      END
    UNTIL NOT Parsing
  END
          Algoritam je jednostavan, ali je pravljenje tabele za parsiranje dosta teško. Ovdje neće biti navedeno kako se to radi,
ali za gornji primjer tabela za parsiranje moţe izgledati ovako (bez elemenata za odbacivanje)


                                                      Symbol

           Goal         Expression         Term       "a"         "-"          "."
 State

    1     Accept         Shift 2          Shift 3    Shift 4
    2                                                            Shift 5     Reduce 1
    3                                                            Reduce 3    Reduce 3
    4                                                            Reduce 4    Reduce 4
    5                                     Shift 6    Shift 4
    6                                                            Reduce 2    Reduce 2
          Parsiranje stringa "a - a - a ." će teći na sljedeći naĉin:.


  State        Symbol      Stack           Action

    1             a         1               Shift to state 4, accept a
    4             -         1   4           Reduce by (4) Term = a
    1           Term        1               Shift to state 3
    3             -         1   3           Reduce by (3) Expression = Term
    1      Expression       1               Shift to state 2
    2             -         1   2           Shift to state 5, accept -
    5             a         1   2   5       Shift to state 4, accept a
    4             -         1   2   5 4     Reduce by (4) Term = a
    5           Term        1   2   5       Shift to state 6
    6             -         1   2   5 6     Reduce by (2) Expression = Expression - Term
    1      Expression       1               Shift to state 2
    2             -         1   2           Shift to state 5, accept -
    5             a         1   2   5       Shift to state 4, accept a
    4             .         1   2   5 4     Reduce by (4) Term = a
    5           Term        1   2   5       Shift to state 6
    6             .         1   2   5 6     Reduce by (2) Expression = Expression - Term
    1      Expression       1               Shift to state 2
    2             .         1   2           Reduce by (1) Goal = Expression
    1           Goal        1               Accept as completed
                                                                102
         Tablice mogu biti dosta velike pa se u memoriji ĉesto smještaju pomoću metoda za rijetke matrice. Kao u sluĉaju
LL(1) parsera potrebno je osigurati da se izbjegnu neodreĊenosti izmeĊu pravila koje se nazivaju "Shift/reduce" konflikti.
Pravljenje tablica i provjera konflikta se ostavlja generatorima parsera.
         LR(k) parsiranje je mnogo moćnije od LL(k) parsiranja, i intuitivno konstruisane gramatike zahtijevaju daleko manje
transformacija da se napravi gramatika iz koje se moţe generisati LR(k) parser. Na primjer, LR(k) parsiranje podrţava lijevu
rekurziju, dok LL(k) ne podrţava. TakoĊer, tablice predstavljaju brţi naĉin parsiranja od velikog broja uslova. LR parseri
imaju prednost u lakšem dodavanju oporavka od grešaka. Nedostaci LR parsera u odnosu na LL parsere su u veliĉini tablica
koje LR parseri oni moraju imati, teţem dodavanju semantike i generisanog koda i ĉesto ĉudnim porukama o greškama.


13.9.     Generatori parsera
        Pravljenje parsera je toliko standardiziran posao da postoje i programi koji ih generišu iz opisa gramatike jezika.
Mogu se podijeliti na generatore leksiĉkih analizatora, generatore LR parsera i generatore LL parsera.
         Najpoznatiji generator leksiĉkih analizatora je LEX, i njegova besplatna varijanta FLEX. Leksiĉki analizator
generisan ovakvim programom je, na primjer, sposoban da kljuĉnu rijeĉ BEGIN prizna kao jedan simbol, dok rijeĉ BEGI
predstavlja ĉetiri simbola. Slijedi dio ulazne datoteke koja se koristi za generisanje leksiĉkog analizatora (skanera) koji
prepoznaje programski jezik Pascal, a koju prihvata YACC.


[a-zA-Z]([a-zA-Z0-9])*    if (is_keyword(yytext, kw)) {return(kw);}
                          else {return(IDENTIFIER);}
":="                      return(ASSIGNMENT);
'({NQUOTE}|'')+' return(CHARACTER_STRING);
":"                       return(COLON);
","                       return(COMMA);
[0-9]+                    return(DIGSEQ);
"."                       return(DOT);
".."                      return(DOTDOT);
"="                       return(EQUAL);
">="                      return(GE);
">"                       return(GT);
"["                       return(LBRAC);
"<="                      return(LE);



         LEX saraĊuje sa generatorom LR parsera YACC (Yet Another Compiler Compiler) ĉija se besplatna varijanta zove
Bison. Iz definicije gramatike kakva je data na kraju klasiĉne knjige Kernighan-Ritchie, "Programski jezik C" moţe se
generisati parser, obiĉno napisan u jeziku C, zajedno sa tabelama. Na slici je dat dio ulazne datoteke koja se koristi za
generisanje parsera koji prepoznaje programski jezik Pascal, a koju prihvata YACC.
program : program_heading semicolon block DOT
    ;

program_heading : _PROGRAM identifier
    | _PROGRAM identifier LPAREN identifier_list RPAREN
    ;

identifier_list : identifier_list comma identifier
    | identifier
    ;

block : label_declaration_part
    constant_definition_part
    type_definition_part
    variable_declaration_part
    procedure_and_function_declaration_part
    statement_part
    ;

module : constant_definition_part
    type_definition_part
    variable_declaration_part
    procedure_and_function_declaration_part
    ;



         Parseri LEX i YACC su izraĊeni i u verzijama koje generišu izvorni kod parsera u drugim programskim jezicima
pored jezika C. Tako na primjer program TPLY - TP Lex and Yacc generiše izvorni kod za Turbo Pascal.
         Eikhound je generator generalizovanih LR parsera koji moţe prevesti svaku kontekstno slobodnu gramatiku,
ukljuĉujući i one koje generišu shift/reduce konflikte.


         Jedan od generatora LL(1) parsera zove se COCO/R i napravljen je u razliĉitim verzijama za razne jezike izvornog
koda koji se generiše. Prednost ovog generatora je u vrlo preglednom ulaznom formatu (standardni BNF) i ĉitljivom izlaznom
kodu. Ovaj generator iz iste ulazne datoteke pravi i leksiĉke analizatore. . Na slici je dat dio ulazne datoteke koja se koristi za
generisanje leksiĉkog analizatora (skanera) koji prepoznaje programski jezik Pascal, a koju prihvata COCO/R.
                                                             103

TOKENS
  identifier   =  letter { letter | digit } .
  integer      =  digit { digit } | digit { digit } CONTEXT ("..") .
  real         =  digit { digit } "." digit { digit }
                  [ "E" ["+" | "-"] digit { digit } ]
                  | digit { digit } "E" ["+" | "-"] digit { digit } .
  string       = "'" { noQuote1 | "''" } "'" .

PRODUCTIONS

  Pascal             = "program" NewIdent [ ExternalFiles ] ";"
                       Block "." .
  ExternalFiles      = "(" NewIdentList ")" .
  Block              = DeclarationPart StatementPart .
  DeclarationPart    = LabelDeclarations ConstDefinitions
                       TypeDefinitions VarDeclarations
                       { ProcDeclarations } .

/* ---------------------------------------------------------------- */

  LabelDeclarations = [ "label" Labels ";" ] .
  Labels            = Label { "," Label } .
  Label             = UnsignedInt .

/* -------------------------------------------------------------------- */

  ConstDefinitions   = [ "const" ConstDef { ConstDef } ] .

  ConstDef           = NewIdent "=" Constant ";" .


        O naĉinu pripreme ulaznih datoteka za spomente generatore parsera potrebno je proĉitati njihovu dokumentaciju.
Generatori parsera se inaĉe zovu i kompajler-kompajleri.


13.10. Rezime poglavlja
          Detaljnije znanje o pravljenju kompajlera moţe se steći upoznavanjem teorije formalne lingvistike i parsiranja.
Gramatika programskog jezika je definisana skupom neterminalnih simbola, skupom terminalnih simbola, jeziĉkim pravilima i
poĉetnim ili ciljnim simbolom. Gramatike se dijele na formalne, kontekstno neovisne, kontekstno osjetljive i regularne. Za
kontekstno neovisne gramatike se prave parseri koji obavljaju sintaksnu analizu. LL parsiranje je metoda koja radi od vrha ka
dnu razvijajući stalno ulazni string i zavisno od sljedećeg terminalnog simbola poziva odgovarajući potprogram. LR parsiranje
koristi stek i tablice kako bi se prepoznao odgovarajući jeziĉki pojam i ova metoda ide odozdo nagore. LR parseri pokrivaju
širu klasu gramatika od LL parsera. Parseri se mogu praviti generatorima parsera kakvi su Yacc i COCO/R.
                                                             104
14. OSNOVNI WIN32 API PROGRAM
         Nakon što je napisan kompajler, slijedi pisanje sistemskih funkcija. Sretna je okolnost što operativni sistem Windows
već ima ogroman broj sistemskih funkcija tako da je samo potrebno pozivati ih. Radi razumijevanja rada testnih aplikacija, kao
i razumijevanja koncepta sistemskih poziva pod operativnim sistemom Windows, slijedi nekoliko lekcija koje govore o naĉinu
korištenja Windows sistemskih funkcija.


14.1.     Hello World
          Najprimitivniji FILDZAN32 Windows program izgleda kao na slici Sl. 14.1.1.
Cijeli funkcija MessageBoxA(cijeli a,karakter * b, karakter * c, cijeli d);
{
    MessageBoxA(0,"Zdravo", "Fildzanski pozdrav", 0);
    0;
}
                                           Sl. 14.1.1.       Primitivni Win32 program

14.2.     Prosti Prozor
Programi koji prikazuju prozor na ekranu imaju standardizovani izgled kao na slici Sl. 14.2.1:
cijeli funkcija RegisterClassExA(cijeli * wndclass);                    ako (msg=16){ DestroyWindow(hwnd); obrada:=1;}` WM_CLOSE
cijeli funkcija ShowWindow ( cijeli a,cijeli b) ;                       ako (msg=2) {PostQuitMessage(0); obrada:=1;} `WM_DESTROY
cijeli funkcija UpdateWindow(cijeli hWnd) ;                             ako (obrada#1) {
cijeli funkcija GetMessageA (cijeli a, cijeli b, cijeli                   DefWindowProcA(lParam,wParam,msg,hwnd); }
c,cijeli * d);                                                          inace {0;}
cijeli funkcija TranslateMessage (cijeli * d) ;
cijeli funkcija DispatchMessageA (cijeli * d) ;                 }
cijeli funkcija CreateWindowExA(cijeli a,cijeli b,cijeli c,
cijeli d,cijeli e,cijeli f,
cijeli g,cijeli h,cijeli i,                                     ` Glavni program
 karakter * j,karakter * k,cijeli l);                           {
cijeli funkcija LoadCursorA ( cijeli a,cijeli b) ;
cijeli funkcija LoadIconA ( cijeli a,cijeli b) ;                ` Korak 1: Registracija prozorske klase
cijeli funkcija DestroyWindow ( cijeli a) ;                         hInstance:=GetModuleHandleA(0);
cijeli funkcija PostQuitMessage ( cijeli a) ;                       wc.cbSize        := 48;
cijeli funkcija DefWindowProcA (cijeli a, cijeli b, cijeli          wc.style         := 0;
c,cijeli d);                                                        wc.lpfnWndProc   := WndProc;
cijeli funkcija MessageBoxA (cijeli a, karakter * b,                wc.cbClsExtra    := 0;
karakter * c,cijeli d);                                             wc.cbWndExtra    := 0;
cijeli funkcija WinExec (karakter * b, karakter * c);               wc.hInstance     := hInstance;
cijeli funkcija GetModuleHandleA ( cijeli a) ;                      wc.hIcon         := LoadIconA(32512,0); `IDI_APPLICATION
cijeli hInstance;                                                   wc.hCursor       := LoadCursorA(32512,0); ` IDC_ARROW
karakter * klasa;                                                   wc.hbrBackground := 6; `COLOR_WINDOW_FRAME
slog {                                                              wc.lpszMenuName := 0;
       cijeli cbSize;                                               wc.lpszClassName := "FILDZANKLASA";
       cijeli   style;                                              wc.hIconSm       := LoadIconA(32512,0); `IDI_APPLICATION
       cijeli * lpfnWndProc;
       cijeli   cbClsExtra;                                             ako (!RegisterClassExA(&wc))
       cijeli   cbWndExtra;                                             {
       cijeli   hInstance;                                                  MessageBoxA(0, "Greska","Neuspjela registracija!",0);
       cijeli   hIcon;                                                  }
       cijeli   hCursor;                                                inace
       cijeli   hbrBackground;                                          {
       karakter * lpszMenuName;                                 `         Korak 2: Kreiranje prozora
       karakter * lpszClassName;                                          hwnd:=CreateWindowExA(0,hInstance,0,0,120,140,
       cijeli hIconSm;                                                      100,200, 13565952, ` ,WS_OVERLAPPEDWINDOW
    } wc; ` Klasa prozora                                                   "Windows aplikacija","FILDZANKLASA",512);
    cijeli hwnd;                                                          ako (hwnd = 0)
    slog                                                                  {
    {                                                                         MessageBoxA(0, "Greska","Neuspjelo kreiranje!",0);
       cijeli hwnd;                                                       }
       cijeli message;                                                    inace
       cijeli wParam;                                                     {
       cijeli lParam;
       cijeli time;                                                           ShowWindow(10,hwnd); `SW_SHOW
       slog                                                                   UpdateWindow(hwnd);
       {                                                                      ` Korak 3: Petlja poruka
            cijeli x;                                                         dok (GetMessageA(0,0,0,&Msg) > 0)
            cijeli y;                                                         {
         } pt;                                                                   TranslateMessage(&Msg);
       } Msg; ` Poruka                                                           DispatchMessageA(&Msg);
                                                                              }
                                                                             Msg.wParam;
` Korak 4: Prozorska procedura                                           }
cijeli funkcija WndProc(cijeli lParam, cijeli wParam, cijeli        }
msg, cijeli hwnd)                                            }
{   cijeli obrada;
    obrada:=0;
                                                 Sl. 14.2.1.      Osnovni prozor
          Ovo je jedan od najkraćih primjera koji generiše osnovni prozor pod Windowsom. Slijedi objašnjenje rada u ĉetiri
koraka.
                                                                105
14.3.      Korak 1: Registracija prozorske klase
          Prozorska klasa ĉuva informacije o tipu prozora ukljuĉujući njegovu prozorsku proceduru koja ga kontroliše, male i
velike ikone prozora i pozadinske boje, Na ovaj naĉin moguće je registrovati klasu jednom i kreirati prozora koliko se ţeli bez
specificiranja svih tih atributa svaki put, mada se oni mogu po ţelji mijenjati za pojedinaĉne prozore. Prozorske klase nemaju
veze sa C++ klasama.
 ` Korak 1: Registracija prozorske klase
    hInstance:=GetModuleHandleA(0);
    wc.cbSize        := 48;
    wc.style         := 0;
    wc.lpfnWndProc   := WndProc;
    wc.cbClsExtra    := 0;
    wc.cbWndExtra    := 0;
    wc.hInstance     := hInstance;
    wc.hIcon         := LoadIconA(32512,0); `IDI_APPLICATION
    wc.hCursor       := LoadCursorA(32512,0); ` IDC_ARROW
    wc.hbrBackground := 6; `COLOR_WINDOW_FRAME
    wc.lpszMenuName := 0;
    wc.lpszClassName := "FILDZANKLASA";
    wc.hIconSm       := LoadIconA(32512,0); `IDI_APPLICATION

     ako (!RegisterClassExA(&wc))
     {
        MessageBoxA(0, "Greska","Neuspjela registracija!",0);
     }
     inace
     {
     Ovaj se kod koristi u glavnom programu za registraciju prozorske klase. Sada će se popuniti struktura
WNDCLASSEX i poziva funkcija RegisterClassEx()
          Ĉlanovi strukture utiĉu na klasu prozora kako slijedi:
          cbSize : Veliĉina strukture.
          style : Stil klase, CS_xxxxx, on se obiĉno postavlja na 0..
          lpfnWndProc :Pokazivaĉ na proceduru koja obraðuje poruke za ovu klasu prozora.
          cbClsExtra : Koliĉina dodatnih podataka alociranih za ovu klasu u memoriji. Obiĉno 0.
          cbWndExtra: Koliĉina dodatnih podataka u memoriji alociranih po prozoru. Obiĉno 0...
          hInstance : Handle koji pokazuje na instancu aplikacije (dobiven funkcijom GetModuleHandle)
          hIcon : Velika (32x32) ikona koja se prikazuje prilikom AltTab.
          hCursor : Kurzor koji se prikazuje preko prozora ove klase.
          hbrBackground: Oznaka ĉetke za pozadinu za postavljanje boje ovog prozora
          lpszMenuName: Ime menija u resursnom dijelu datoteke za prozore ove klase
          lpszClassName: Ime kojim se klasa identificira
          hIconSm : Mala (16x16) ikona koja se pojavljuje u taskbaru i u gornjem lijevom uglu prozora.
         U praksi se ova struktura ne pamti, nego se najĉešæe kopira, niti ima potrebe pamtiti je. Neophodno je imati help
datoteke kada se ţeli modifikovati neki od parametara..
         Nakon što je ova struktura popunjena, poziva se RegisterClassEx i provjeravaju greške. U sluĉaju greške prikaţe se
poruka i prekida program izlaskom iz glavnog programa.


14.4.      Korak 2: Kreiranje prozora
          Nakon što je klasa registrovana, slijedi kreiranje prozora pomoću nje. To se radi pomoću funkcije CreateWindowEx,
ĉiji će parametri sada biti objašnjeni..
 `        Korak 2: Kreiranje prozora
        hwnd:=CreateWindowExA(0,hInstance,0,0,120,140,
          100,200, 13565952, ` ,WS_OVERLAPPEDWINDOW
          "Windows aplikacija","FILDZANKLASA",512);
        ako (hwnd = 0)
        {
            MessageBoxA(0, "Greska","Neuspjelo kreiranje!",0);
        }
        inace
        {
         Zadnji parametar, 512 je prošireni windows stil koji daje drugaĉiji izgled ivice. Moţe se eksperimentirati i sa drugim
vrijednostima..
                                                                106
         Ime klase "FILDZANKLASA" kaţe sistemu kakvu vrstu prozora da kreira. U datom primjeru, treba kreirati prozor od
klase koja je upravo registrovana, pa će se njeno ime i koristiti. Nakon toga se navodi ime prozora ili naslov koji se prikazuje u
naslovnom dijelu prozora..
         Parametar koji u datom primjeru ima vrijednost 13565952 (WS_OVERLAPPEDWINDOW) je parametar stila
prozora. Ima više razliĉitih stilova i korisno je eksperimentisati sa njima da se vidi šta koji radi..
         Sljedeća ĉetiri parametra (120,140,100,200) su visina prozora, širina prozora, y koordinata i x koordinata x i y
koordinate gornjeg lijevog ugla i širina i visina prozora. Jedinice su u pikselima, ishodište koordinatnog sistema je gornji lijevi
ugao, tako da y osa raste prema dolje, a x osa prema desno.
          Sljedeća ĉetiri parametra (0,hinstance,0,0) su pokazivaĉ na dodatne podatke o kreiranju prozora, te hendlovi na
instancu aplikacije, meni i roditeljski prozor. Ekranska unosna polja ili dugmad predstavljaju podprozore i za njih je potrebno
postaviti vrijednost Parent. U ovom primjeru, ovo je glavni prozor i on nema roditeljskog prozora..
        Ĉest uzrok grešaka u programima je što se ne provjerava rezultat funkcija. CreateWindow() ĉesto pada i kod iskusnih
programera, stoga je potrebno uvijek provjeravati njen rezultat!
     ako (hwnd = 0)
      {
         MessageBoxA(0, "Greska","Neuspjelo kreiranje!",0);
      }
        Nakon što je prozor kreiran i provjerena ispravnost njegovog hendla, sada je potrebno prikazati i aţurirati prozor.
Konstanta 10 (SW_SHOW) znaĉi da se prozor treba prikazati.
   ShowWindow(10,hwnd); `SW_SHOW
        UpdateWindow(hwnd);




14.5.      Korak 3: Petlja poruka
          Ovo je srce cijelog programa, praktiĉno sve što program radio prolazi kroz ovu taĉku.
             ` Korak 3: Petlja poruka
          dok (GetMessageA(0,0,0,&Msg) > 0)
          {
             TranslateMessage(&Msg);
             DispatchMessageA(&Msg);
          }
         Msg.wParam;
     }



         GetMessage() preuzima poruku iz reda ĉekanja korisniĉke aplikacije. Svaki put kada korisnik pomjeri miša, otkuca
nešto na tastaturi, klikne na meni prozora ili uradi mnogo drugih stvari, poruke se generišu od strane sistema i smjeste u red
ĉekanja korisniĉkog programa. Pozivom GetMessage() zahtijeva se da se sljedeća poruka izbaci iz reda ĉekanja i preda
programu za procesiranje. Ako nema poruke GetMessage prelazi u ĉekanje do nailaska nove. Ukoliko to predstavlja problem,
neki programi koriste poruku PeekMessage() koja radi isto kao GetMessage, samo što nastavlja rad ako u redu ĉekanja nema
novih poruka..
         TranslateMessage() dodatno procesira poruke tastature kao što je generisanje poruka WM_CHAR da se šalju zajedno
sa WM_KEYDOWN porukom. Poruka DispatchMessage šalje poruku prozoru kome je poruka namijenjena. To moţe biti
glavni prozor aplikacije, ali i bilo koji drugi prozor, korisniĉka kontrola ili neki prozor kreiran od strane sistema ili druge
aplikacije. O tome ne treba brinuti jer se je jedini zadatak programa da preuzme i pošalje poruku, a sistem rješava kako će opna
doći do odgovarajućeg prozora..


14.6.      Korak 4: Prozorska procedura
         Ako je petlja poruka srce programa, prozorska procedura je njegov mozak. Na ovom mjestu se obraðuju sve poruke
poslane prozoru..
` Korak 4: Prozorska procedura
cijeli funkcija WndProc(cijeli lParam, cijeli wParam, cijeli msg, cijeli hwnd)
{   cijeli obrada;
    obrada:=0;
    ako (msg=16){ DestroyWindow(hwnd); obrada:=1;} ` Poruka WM_CLOSE
    ako (msg=2) {PostQuitMessage(0); obrada:=1;} ` Poruka WM_DESTROY

    ako (obrada#1) { DefWindowProcA(lParam,wParam,msg,hwnd); }
    inace {0;}
         }

         Prozorska procedura se poziva za svaku poruku. HWND parametar je hendl prozora, tj. onaj na koga se poruka
odnosi. To je bitan podatak jer svi prozori iste klase dijele istu prozorsku proceduru, pa se oni meðusobno razlikuju po HWND
parametru.
                                                           107
          WM_CLOSE se šalje kada korisnik pritisne taster Close ili Alt+F4. To će izazvati uništavanje prozora i inaĉe, ali je
ovdje obrada izdvojena kako bi se mogao dodati eventualni kod koji posprema ostale podatke prije uništenja prozora, kao što
je upit korisnika za snimanje datoteka..
         Poziv funkcije DestroyWindow() šalje poruku WM_DESTROY prozoru koji treba biti uništen, uništavajući potom
sve njegove podprozore. Na prijem ove poruke poziva se funkcija PostQuitMessage. Ova funkcija šalje WM_QUIT petlji za
prozore. Ova se poruka nikada ne dobija, jer ona izaziva da GetMessage() vrati netaĉnu vrijednost ĉime se prekida obrada
poruka.


14.7.      Obrada poruka
          Sada prozor postoji mada moţe da radi jedino
ono     što    mu    omogućava      DefWindowProc(),
proširivanja, maksimiziranja, ali nikakav drugi kod.
Dodatne funkcionalnosti se mogu dodavati obradom
pojedinaĉnih poruka. Obrada poruke predstavlja širenje
prozorske procedure dodavanjem aktivnosti u sluĉaju
prijema poruke.


         U proceduru WndProc() dodaće se kod koji
prikazuje ime programa kada se klikne mišem unutar
prozora. Trenutno u WndProc postoji sljedeće:
` Korak 4: Prozorska procedura
cijeli funkcija WndProc(cijeli lParam, cijeli wParam, cijeli msg, cijeli hwnd)
{   cijeli obrada;
    obrada:=0;
    ako (msg=16){ DestroyWindow(hwnd); obrada:=1;} ` Poruka WM_CLOSE
    ako (msg=2) {PostQuitMessage(0); obrada:=1;} ` Poruka WM_DESTROY

    ako (obrada#1) { DefWindowProcA(lParam,wParam,msg,hwnd); }
    inace {0;}

}
         Da se obradi klik na lijevi taster miša, dodaje se obrada poruke WM_LBUTTONDOWN. Obrada poruke znaĉi njeno
dodavanje u WndProc kao na sljedećoj slici:
` Korak 4: Prozorska procedura
cijeli funkcija WndProc(cijeli lParam, cijeli wParam, cijeli msg, cijeli hwnd)
{   cijeli obrada;
    obrada:=0;
    ako (msg=16){ DestroyWindow(hwnd); obrada:=1;} ` Poruka WM_CLOSE
    ako (msg=2) {PostQuitMessage(0); obrada:=1;} ` Poruka WM_DESTROY
    ako (msg=513) {                       ` DODANO
obrada:=1;} ` Poruka WM_LBUTTONDOWN   ` DODANO

    ako (obrada#1) { DefWindowProcA(lParam,wParam,msg,hwnd); }
    inace {0;}
}

Sada treba napisati šta će se dogoditi kada se uĊe u taj dio programa. Kod koji se ţeli dodati je prikaz imena datoteke
korisniĉkog programima. U kasnijim primjerima će se samo prikazivati kod koji se ţeli integrisati u program, u cilju smanjenja
kucanja..
        GetModuleFileNameA (MAXPATH, szFileName, hInstance);
        MessageBoxA(0, "This program is:",szFileName, hwnd);

          Gore prikazani kod će se izvršiti kada se klikne mišem na formu programa i dodaje se u osnovnu Windows aplikaciju:


` Korak 4: Prozorska procedura
cijeli funkcija WndProc(cijeli lParam, cijeli wParam, cijeli msg, cijeli hwnd)
{   cijeli obrada;
    obrada:=0;
    ako (msg=16){ DestroyWindow(hwnd); obrada:=1;} ` Poruka WM_CLOSE
    ako (msg=2) {PostQuitMessage(0); obrada:=1;} ` Poruka WM_DESTROY
    ako (msg=513) {                       `
      GetModuleFileNameA (MAXPATH, szFileName, hInstance);
      MessageBoxA(0, "This program is:",szFileName, hwnd);
    obrada:=1;} ` Poruka WM_LBUTTONDOWN   `

    ako (obrada#1) { DefWindowProcA(lParam,wParam,msg,hwnd); }
    inace {0;}
}
         Nakon modifikacije ovog koda treba ga kompajlirati. Klik na prozor izaziva poruku sa imenom EXE programa.
Dodane su varijable hInstance i szFileName. Prvi parametar funkcije GetModuleFIleName je HINSTANCE koji se odnosi na
izvršni program (dakle EXE datoteka). Ta se vrijednost dobija funkcijom GetModuleHandle, koja za parametar NULL vraća
                                                              108
oznaku datoteke u kojoj se nalazi proces koji ju je pozvao. Drugi parametar funkcije je pokazivaĉ na mjesto gdje će se primiti
ime datoteke i staza do navedenog modula i taj parametar je tima LPTSTR, odnosno pokazivaĉ niz karaktera.:
#definiraj MAXPATH 260
cijeli funkcija GetModuleFileNameA (cijeli a,karakter * b,cijeli c);
karakter [MAXPATH] szFileName;
        MAX_PATH definiše maksimalnu veliĉinu imena datoteke.
        Nakon poziva GetModuleFileName, bafer szFileName će se napuniti stringom koji sadrţi ime naše EXE datoteke. Taj
parametar se prosljeðuje funkciji MessageBox, ĉime se prikaţe na ekranu..
        Ukoliko dodavanje koda nije rezultovalo ispravnim kompajliranjem, slijedi kompletan kod.
cijeli funkcija RegisterClassExA(cijeli * wndclass);                   ako (msg=16){ DestroyWindow(hwnd); obrada:=1;} `WM_CLOSE
cijeli funkcija ShowWindow ( cijeli a,cijeli b) ;                      ako (msg=2) {PostQuitMessage(0); obrada:=1;} `WM_DESTROY
cijeli funkcija UpdateWindow(cijeli hWnd) ;                            ako (msg=513) {                       `
cijeli funkcija GetMessageA (cijeli a, cijeli b, cijeli                  GetModuleFileNameA (MAXPATH, szFileName, hInstance);
c,cijeli * d);                                                           MessageBoxA(0, "This program is:",szFileName, hwnd);
cijeli funkcija TranslateMessage (cijeli * d) ;                        obrada:=1;} ` Poruka WM_LBUTTONDOWN   `
cijeli funkcija DispatchMessageA (cijeli * d) ;
cijeli funkcija CreateWindowExA(cijeli a,cijeli b,cijeli c,            ako (obrada#1) { DefWindowProcA(lParam,wParam,msg,hwnd);
cijeli d,cijeli e,cijeli f,                                    }
cijeli g,cijeli h,cijeli i,                                            inace    {0;}
 karakter * j,karakter * k,cijeli l);
cijeli funkcija LoadCursorA ( cijeli a,cijeli b) ;             }
cijeli funkcija LoadIconA ( cijeli a,cijeli b) ;
cijeli funkcija DestroyWindow ( cijeli a) ;
cijeli funkcija PostQuitMessage ( cijeli a) ;                  ` Glavni program
cijeli funkcija DefWindowProcA (cijeli a, cijeli b, cijeli     {
c,cijeli d);
cijeli funkcija MessageBoxA (cijeli a, karakter * b,           ` Korak 1: Registracija prozorske klase
karakter * c,cijeli d);                                            hInstance:=GetModuleHandleA(0);
cijeli funkcija WinExec (karakter * b, karakter * c);              wc.cbSize        := 48;
cijeli funkcija GetModuleHandleA ( cijeli a) ;                     wc.style         := 0;
#definiraj MAXPATH 260                                             wc.lpfnWndProc   := WndProc;
cijeli funkcija GetModuleFileNameA (cijeli a,karakter *            wc.cbClsExtra    := 0;
b,cijeli c);                                                       wc.cbWndExtra    := 0;
karakter [MAXPATH] szFileName;                                     wc.hInstance     := hInstance;
cijeli hInstance;                                                  wc.hIcon         := LoadIconA(32512,0); `IDI_APPLICATION
karakter * klasa;                                                  wc.hCursor       := LoadCursorA(32512,0); ` IDC_ARROW
slog {                                                             wc.hbrBackground := 6; `COLOR_WINDOW_FRAME
       cijeli cbSize;                                              wc.lpszMenuName := 0;
       cijeli   style;                                             wc.lpszClassName := "FILDZANKLASA";
       cijeli * lpfnWndProc;                                       wc.hIconSm       := LoadIconA(32512,0); `IDI_APPLICATION
       cijeli   cbClsExtra;
       cijeli   cbWndExtra;                                            ako (!RegisterClassExA(&wc))
       cijeli   hInstance;                                             {
       cijeli   hIcon;                                                     MessageBoxA(0, "Greska","Neuspjela registracija!",0);
       cijeli   hCursor;                                               }
       cijeli   hbrBackground;                                         inace
       karakter * lpszMenuName;                                        {
       karakter * lpszClassName;                               `         Korak 2: Kreiranje prozora
       cijeli hIconSm;                                                   hwnd:=CreateWindowExA(0,hInstance,0,0,120,140,
    } wc; ` Klasa prozora                                                  100,200, 13565952, ` ,WS_OVERLAPPEDWINDOW
    cijeli hwnd;                                                           "Windows aplikacija","FILDZANKLASA",512);
    slog                                                                 ako (hwnd = 0)
    {                                                                    {
       cijeli hwnd;                                                          MessageBoxA(0, "Greska","Neuspjelo kreiranje!",0);
       cijeli message;                                                   }
       cijeli wParam;                                                    inace
       cijeli lParam;                                                    {
       cijeli time;
       slog                                                                  ShowWindow(10,hwnd); `SW_SHOW
       {                                                                     UpdateWindow(hwnd);
            cijeli x;                                                        ` Korak 3: Petlja poruka
            cijeli y;                                                        dok (GetMessageA(0,0,0,&Msg) > 0)
         } pt;                                                               {
       } Msg; ` Poruka                                                          TranslateMessage(&Msg);
                                                                                DispatchMessageA(&Msg);
                                                                             }
` Korak 4: Prozorska procedura                                              Msg.wParam;
cijeli funkcija WndProc(cijeli lParam, cijeli wParam, cijeli            }
msg, cijeli hwnd)                                                  }
{   cijeli obrada;                                           }
    obrada:=0;




14.8.    Šta je to poruka?
         Razumijevanje petlje poruka i cijele strukture u kojoj se šalju poruke windows programa je od suštinskog znaĉaja za
pisanje svega osim najtrivijalnijih poruka. Sada će se malo više paţnje posvetiti cijelom procesu radi izbjegavanja kasnijih
konfuzija. Pogled na datoteke zaglavlja u kompajlerima za C pokazuje sljedeće definicije:


#define WM_INITDIALOG                    0x0110
#define WM_COMMAND                       0x0111

#define WM_LBUTTONDOWN                   0x0201
                                                              109
          Poruke se koriste za komunikaciju izmeĊu mnogih podsistema. Ukoliko se ţeli da neki prozor ili kontrola (koja je
samo specijalizovani prozor) obavi neku akciju, šalje joj se poruka. Drugi prozor moţe takoĊe da zahtjeve za aktivnosti našeg
prozora pozove porukom. Ako se dogodi kucanje na tastaturi ili pomicanje miša sistem šalje poruku prozoru na koji poruka
utiĉe. Zadatak prozorske procedure je da odgovori na navedene poruke.
         Svaka poruka Windowsa moţe da ima do dva parametra, wParam i lParam. Unatoĉ imenu, pod Win32 oba parametra
su 32 bitna. Ove parametre ne koristi svaka poruka, a i one koje ih koriste mogu ih interpretirati na razliĉite naĉine. Tako na
primjer, poruka WM_CLOSE ne koristi ni jedan parametar, a poruka WM_COMMAND koristi oba. U Parametru wParam
kod poruke WM_COMMAND se u višoj rijeĉi nalaz notifikacijska poruka, a u niţoj identifikator kontrole koja je poslala
poruku. U parametru lParam se nalazi handle prozora ili kontrole koji je poslao poruku.
        Slanje poruke se vrši funkcijama PostMessage() ili SendMessage(). PostMessage() samo smjesti poruku u red ĉekanja
i odmah se vrati, tako da poruka moţe ali i ne mora biti obraĊena. SendMessage() šalje poruku direktno prozoru i ne vraća se
dok prozor ne završi procesiranje poruke. Na ovaj naĉin moguće je, na primjer, zatvoriti prozor slanjem poruke WM_CLOSE
tom prozoru koristeći funkciju PostMessage(0,0,WM_CLOSE,hwnd);


14.9.     Komunikacija sa dijaloškim prozorima
         Dijaloškim prozorima se šalju poruke u svrhu komunikacije sa njim Poruka pojedinoj kontroli na dijalogu se moţe
poslati korištenjem funkcije GetDlgItem() koja na bazi identifikatora vraća hendl kontrole i zatim upotrebom funkcije
SendMessage () ili upotrebom SendDlgItemMessage() koja kombinuje oba koraka.


14.10. Šta je red čekanja poruka?
         Ukoliko u trenutku obrade poruke WM_PAINT korisnik otkuca nešto na tastaturi, šta se treba dogoditi? Prekinuti
iscrtavanje da bi se obradili tasteri ili ih ignorisati. Nijedno rješenje nije dobro, nego postoji red ĉekanja u koji se smještaju
poruke kada se pošalju i nakon obrade ovih poruka one se uklanjaju. To omogućuje da se poruke ne gube dok se obraĊuju
druge poruke.


14.11. Šta je petlja poruka
        dok (GetMessageA(0,0,0,&Msg) > 0)
        {
           TranslateMessage(&Msg);
           DispatchMessageA(&Msg);
        }
         Petlja poruka poziva GetMessage() koja pregleda red ĉekanja. Ako je red ĉekanja prazan, program se zaustavlja i ĉeka
da se poruka pojavi.
         Kada se desi dogaĊaj koji ubacuje poruku u red ĉekanja (npr. pritisak na taster miša), GetMessage() vraća pozitivnu
vrijednost indicirajući da postoji poruka koja se treba obraditi i da je ona napunjena ĉlanovima MSG strukture koja joj je
dodijeljena. Ova funkcija vraća vrijednost 0 ako primi poruku WM_QUIT i negativnu vrijednost ako se dogodila greška.
         Preuzimanje poruke u Msg varijablu i njeno prosljeĊivanje funkciji TranslateMessage() je opcionalni korak koji
prevodi virtualni taster u karakterske poruke. Nakon što je to uraĊeno, poruka se prosljeĊuje funkciji DispatchMessage(). Ova
funkcija provjeri kojem je prozoru namijenjena i traţi prozorsku proceduru koja obraĊuje taj prozor. Nakon toga poziva tu
proceduru šaljući kao parametar hendl prozora, poruku, wParam i lParam.
        U prozorskoj proceduri se provjeri poruka i njeni parametri i obraĊuje po ţelji. Ukoliko se poruka posebno ne
obraĊuje, poziva se DefWindowProc() koja obavlja podrazumijevane akcije, što ĉesto znaĉi da se ništa ne radi.
         Po završetku prozorske procedure, DispatchMessage() se vrati i petlja se ponovo izvršava. Prozorska procedura se ne
poziva magiĉno iz sistema, nju zapravo poziva korisniĉki program funkcijom DispatchMessage. Ukoliko se to ţeli, isti efekat
se moţe postići korištenjem GetWindowLong() funkcije koja za navedeni hendl nalazi prozorsku proceduru i direktno je zvati
indirektnim pozivom funkcije. Ipak to neće raditi u sloţenijim aplikacijama, pošto su neki efekti koje implicitno radi
DispatchMessage zanemareni.
         Aplikacija provodi većinu vremena u petlji za poruke. Kada se ţeli izaći iz te petlje, GetMessage() treba da vrati
vrijednost 0 da se doĊe do kraja WinMain funkcije. To obavlja PostQuitMessage(). Ona u red ĉekanja dodaje poruku
WM_QUIT i umjesto vraćanja pozitivne vrijednosti GetMessage() puni Msg strukturu i vraća vrijednost 0. Polje wParam
strukture Msg sadrţi vrijednost koja je proslijeĊena funkciji PostQuitMessage i ona se moţe ili ignorisati ili iskoristiti kao
izlazni kod pri završetku procesa.


14.12. Rezime poglavlja
         Aplikacije koje nemaju prozore se mogu pisati na klasiĉni naĉin. Windows aplikacije sa prozorima su bazirane na
petljama i porukama. Svaka windows aplikacija, koja treba da prikaţe standardni prozor ima ĉetiri faze: pripremu i registraciju
prozorske klase, kreiranje prozora, petlju poruka i obradu poruka u prozorskoj proceduri. Slanje poruke u glavnoj petlji
automatski pokreće proceduru za obradu prozora, a ova procedura je definisana u prozorskoj klasi.
                                                              110
15.KORISNIČKI INTERFEJS I GRAFIČKE PRIMITIVE

          Jedan od najvaţnijih zadataka aplikacija napisanih u bilo kom programskom jeziku je komunikacija sa korisnikom. U
ovom poglavlju će biti rijeĉi o tome kako se mogu primati ulazni podaci od korisnika pod operativnim sistemom Windows,
prilagoĊeno za FILDZAN-32.Prema naĉinu interakcije sa korisnikom, postoje tri vrste aplikacija, servisi koji nemaju nikakvu
interakciju osim kroz konfiguracione datoteke ili Registry, konzolne aplikacije, koje komuniciraju preko tastature i tekstualnog
izlaza i GUI aplikacije, koje imaju kompletan skup korisniĉkih kontrola.


15.1.    Servisne aplikacije
         Ovo su obiĉno sistemski procesi koji se startaju automatski po startu operativnog sistema. Ove aplikacije direktno ne
komuniciraju sa korisnikom, nego primaju poruke od sistema. Tako na primjer, aplikacije koje predstavljaju Web server ne
prikazuju ništa na ekranu, niti oĉitavaju išta sa tastature, nego obavljaju prijemom i slanjem podataka kroz socket funkcije.
Servisne aplikacije u uţem smislu se mogu startati i kada korisnik nije uopšte prijavljen na raĉunar.



15.2.    Konzolne aplikacije

          Već su prvi primjeri u FILDZAN-32 koji su se uspjeli kompajlirati predstavljali ovakve aplikacije. Konzola je
interfejs koji omogućava ulaz/izlaz aplikacijama koje rade u znakovnom reţimu. Konzola se sastoji od ulaznog bafera i jednog
ili više ekranskih bafera. Ulazni bafer sadrţi red ulaznih slogova od kojih svaki ukljuĉuje informacije u ulaznom dogaĊaju.
Ekranski bafer je dvodimenzionalni niz znakova i informacija o boji za izlaz na prozoru konzole.
        Win32 dopušta funkcije visokog i niskog nivoa za pristup konzoli. Funkcije visokog nivoa su orijentisane prema
znakovima i omogućavaju redirekciju podataka. Funkcije niskog nivoa prate ulaze sa tastature kao što su pojedinaĉni tasteri,
dogaĊaje miša i omogućuju bolju kontrolu izlaza na ekran.
        Konzolne aplikacije se ne pišu ni na kakav poseban naĉin. Treba jedino znati da jezik FILDZAN32 koji se razvija
sam po sebi nema naredbe kao što su writeln ili scanf, pa treba napisati program koristeći Win32 API.
         Najvaţnije funkcije visokog nivoa su GetStdHandle , ReadConsoleA i WriteConsoleA, koje su objašnjene u testnim
primjerima šestog i sedmog poglavlja.
         Od funkcija niskog nivoa treba spomenuti funkciju PeekConsoleInput kojom se mogu oĉitavati tasteri bez ĉekanja.


15.3.    Grafičke kontrole
       Grafiĉke aplikacije imaju drugaĉiji pristup ulaznim podacima od tekstualnih. Na ekranu se nalaze razliĉite kontrole
(dugmad, editna polja, kombinovane liste i sliĉno)
         Sve Windows kontrole su zapravo prozori. To je bitno za znati, jer se tako mnoge funkcije namijenjene prozorima
mogu koristiti i za kontrole. Tako na primjer, postavljanje naslova prozora ili upis podrazumijevane vrijednosti u editno polje
obavljaju iste funkcije.
          Dva su pristupa pravljenju Windows kontrola. Jedan je preko resursnih dijaloga i zahtijeva upotrebu resursnog editora
ili jezika za resursne skripte. Resursi se odvojeno kompajliraju i povezuju sa glavnim programom. To su binarni podaci koji
opisuju izgled kontrola. Prednost pristupa je u mogućnosti ekstrakcije ekranskih formi iz izvršnog programa u cilju njihove
popravke ili prevoĊenja na druge jezike. Druga prednost je što je osnovni program kraći. Treća prednost je što resursni editori
mogu biti grafiĉke, vizuelne aplikacije, pa je njihova priprema razmjerno jednostavna. Nedostaci pristupa su potreba za
posebnim kompajlerom resursa i veća rasparĉanost koda jer se on nalazi i u datoteci sa programom i u datoteci sa resursom.
        Windows kontrole se mogu dobiti i direktnim pozivom CreateWindowExA funkcije za svaku kontrolu. Kako resursni
kompajler za FILDZAN32 još nije napisan, koristiće se drugi metod.
         Dio parametara iz CreateWindowExA koji su korišteni za kreiranje osnovne Windows aplikacije se mogu primijeniti i
ovdje, dok se drugi dio mijenja. Tako na primjer, za Windows kontrole nema potrebe registrovati klasu prozora, jer već postoji
nekoliko standardnih:
         BUTTON - dugmad, checkbox-ovi i radio tasteri
         LISTBOX – liste podataka
         COMBOBOX - kombinovane liste podataka
         EDIT - unosna polja
         SCROLLBAR - klizna traka
                                                                111
         STATIC - statiĉni tekst
         SysAnimate32- kontrola koja prikazuje AVI datoteku
         msctls_hotkey32- kontrola koja predefiniše taster za brţi pristup nekoj opciji
         msctls_progress32- mjeraĉ realizacije nekog posla
         msctls_statusbar32 - statusna traka
         ToolbarWindow32 - alatna traka
         tooltips_class32 - informacioni prozorĉić
         msctls_trackbar32 - potenciometarska kontrola
         msctls_updown32 - kontrola za unos podatka uz mogućnost uvećanja i umanjenja njegove vrijednosti tasterima
         SysHeader32 - zaglavlje pogleda na podatke u formi liste
         SysListView32 - Pogled na podatke u formi liste, koji omogućuje i pojedine ikone
         SysTabControl32 - Tab kontrola, omogućuje prikaz podataka u formi odvojenih kartica
         SysTreeView32 - Pogled stabla, hijerarhijski prikaz podataka
         RichEdit - Omogućuje unos tekstova koji mogu biti u boji i sadrţati dodatne podatke


        Sa kontrolama se komunicira slanjem poruka kontroli funkcijom SendMessage ili odgovarajućim funkcijama za
obradu prozora.
        Kontrole vraćaju prozoru poruku WM_COMMAND, WM_NOTIFY, WM_HSCROLL ili WM_VSCROLL, zavisno
od same kontrole. U okviru wParam i lParam parametara nalaze se dodatne informacije koje govore o poruci.


15.4.     Funkcije grafičkih kontrola kroz primjer
        Na slici Sl. 15.4.1 data je ekranska forma aplikacije za unos podataka o zainteresovanim licima za uvoĊenje
kablovske televizije. Na ovoj formi se nalaze sve standardne Windows kontrole, koje se nalaze u USER32.DLL biblioteci.




                                                    Sl. 15.4.1.        Forma aplikacije
        Na ovoj formi se uoĉava da postoje kontrole tipa edit polja, listbox, combobox, checkbox, memo polja, menu,
dugmad, scroll bar, statiĉki tekst, iscrtani logo firme, ispisani tekst i menu. Sada će se pogledati cijeli listing programa, a zatim
vidjeti kako se definiše pojedina vrsta kontrola i                           kako se oĉitavaju podaci koje ona šalje.
                                                          112
                                                               cijeli hEdit1,hEdit2,hGroup1,hRadio1,hRadio2,hCheck1,
                                                                 hMemo1,hListBox1,hCombo1,hScroll1,hButton1,hStatic1,
                                                               hStatic2,hStatic3,hStatic4,hStatic5,hStatic6,hdc,hMenu,
cijeli funkcija RegisterClassExA(cijeli * wndclass);           hSubMenu;
cijeli funkcija ShowWindow ( cijeli a,cijeli b) ;
cijeli funkcija UpdateWindow(cijeli hWnd) ;                    cijeli funkcija KreirajKontrole()
cijeli funkcija GetMessageA (cijeli a, cijeli b, cijeli        {
c,cijeli * d);                                                   hEdit1:=CreateWindowExA(0,hInstance,0,hwnd,21,161,16,64,
cijeli funkcija TranslateMessage (cijeli * d) ;                    1350565888, ` ws_child or ws_visible or ws_border
cijeli funkcija DispatchMessageA (cijeli * d) ;                  "","EDIT",512);
cijeli funkcija CreateWindowExA(cijeli a,cijeli b,cijeli c,
cijeli d,cijeli e,cijeli f,                                      hEdit2:=CreateWindowExA(0,hInstance,0,hwnd,21,161,48,64,
cijeli g,cijeli h,cijeli i,                                        1350565888, ` ws_child or ws_visible or ws_border
 karakter * j,karakter * k,cijeli l);                            "","EDIT",512);
cijeli funkcija LoadCursorA ( cijeli a,cijeli b) ;
cijeli funkcija LoadIconA ( cijeli a,cijeli b) ;                 hGroup1:=CreateWindowExA(0,hInstance,0,hwnd,57,217,80,16,
cijeli funkcija DestroyWindow ( cijeli a) ;                         1342177287, ` ws_child or ws_visible or bs_groupbox
cijeli funkcija PostQuitMessage ( cijeli a) ;                    "Spol","BUTTON",0);
cijeli funkcija DefWindowProcA (cijeli a, cijeli b, cijeli
c,cijeli d);
cijeli funkcija MessageBoxA (cijeli a, karakter * b,           hRadio1:=CreateWindowExA(0,hInstance,105,hGroup1,17,113,16,2
karakter * c,cijeli d);                                        4,
cijeli funkcija WinExec (karakter * b, karakter * c);               1342177289, ` ws_child or ws_visible or
cijeli funkcija GetModuleHandleA ( cijeli a) ;                 bs_autoradiobutton
cijeli funkcija SendMessageA (karakter * a,cijeli b, cijeli       "Muški","BUTTON",0);
c, cijeli d);
cijeli funkcija GetWindowTextA (cijeli a,karakter * b,
cijeli c);                                                     hRadio2:=CreateWindowExA(0,hInstance,106,hGroup1,17,113,32,2
cijeli funkcija IsDlgButtonChecked(cijeli a, cijeli b);        4,
cijeli funkcija SetScrollRange(cijeli a,cijeli b, cijeli c,         1342177289, ` ws_child or ws_visible or
cijeli d, cijeli e);                                           bs_autoradiobutton
cijeli funkcija SetScrollPos(cijeli a,cijeli b, cijeli c,         "Ženski","BUTTON",0);
cijeli d);
cijeli funkcija GetScrollPos(cijeli a,cijeli b);
cijeli funkcija BeginPaint(cijeli * a,cijeli b);               hCheck1:=CreateWindowExA(0,hInstance,107,hwnd,17,209,152,16,
cijeli funkcija EndPaint(cijeli * a,cijeli b);                     1342177283, ` ws_child or ws_visible or bs_autocheckbox
cijeli funkcija Ellipse(cijeli a, cijeli b, cijeli c,cijeli      "Uplatio uvođenje","BUTTON",512);
d, cijeli e);
cijeli funkcija MoveToEx(cijeli * a, cijeli b, cijeli            hMemo1:=CreateWindowExA(0,hInstance,0,hwnd,89,185,216,16,
c,cijeli d);                                                       1350565892, ` ws_child or ws_visible or ws_border or
cijeli funkcija LineTo(cijeli a, cijeli b, cijeli c);          es_multiline
cijeli funkcija TextOutA(cijeli a,cijeli * b,cijeli c,cijeli     "Memo","EDIT",512);
d,cijeli e);
cijeli funkcija CreateMenu();
cijeli funkcija CreatePopupMenu();                             hListBox1:=CreateWindowExA(0,hInstance,0,hwnd,97,200,24,272,
cijeli funkcija AppendMenuA(karakter * a,cijeli b, cijeli c,       1352663043, ` ws_child or ws_visible or ws_border or
cijeli d);                                                     lbs_standard
cijeli funkcija SetMenu(cijeli a,cijeli b);                      "List1","LISTBOX",512);

                                                                 SendMessageA("1.Samo   TV program",0,384,hListBox1);
cijeli hInstance;                                              ` 384 LB_ADDSTRING
karakter * klasa;                                                SendMessageA("2.TV i   Internet",0,384,hListBox1);
slog {                                                         ` 384 LB_ADDSTRING
       cijeli cbSize;                                            SendMessageA("3.Samo   Internet",0,384,hListBox1);
       cijeli   style;                                         ` 384 LB_ADDSTRING
       cijeli * lpfnWndProc;                                     SendMessageA("4.TV s   kodiranimkanalima",0,384,hListBox1);
       cijeli   cbClsExtra;                                    ` 384 LB_ADDSTRING
       cijeli   cbWndExtra;                                      SendMessageA("5.Puni   paket",0,384,hListBox1);
       cijeli   hInstance;                                     ` 384 LB_ADDSTRING
       cijeli   hIcon;
       cijeli   hCursor;
       cijeli   hbrBackground;                                 hCombo1:=CreateWindowExA(0,hInstance,0,hwnd,100,145,144,272,
       karakter * lpszMenuName;                                    1350566402, ` ws_child or ws_visible or ws_border or
       karakter * lpszClassName;                               cbs_dropdown or cbs_hasstrings
       cijeli hIconSm;                                           "COmbobox1","COMBOBOX",0);
    } wc; ` Klasa prozora                                        SendMessageA("Maršala Tita",0,323,hCombo1);
    cijeli hwnd;                                               ` 323 CB_ADDSTRING
    slog                                                         SendMessageA("Alipašina",0,323,hCombo1);
    {                                                          ` 323 CB_ADDSTRING
       cijeli hwnd;
       cijeli message;
       cijeli wParam;                                          hScroll1:=CreateWindowExA(0,hInstance,0,hwnd,21,185,192,272,
       cijeli lParam;                                              1342177280, ` ws_child or ws_visible or sbs_horz
       cijeli time;                                              "","SCROLLBAR",0);
       slog                                                      SetScrollRange(1,100,1,2,hScroll1);
       {
            cijeli x;                                           hButton1:=CreateWindowExA(0,hInstance,0,hwnd,25,75,256,288,
            cijeli y;                                              1342177280, ` ws_child or ws_visible or bs_pushbutton
         } pt;                                                   "Unesi","BUTTON",0);
       } Msg; ` Poruka
                                                                 hStatic1:=CreateWindowExA(0,hInstance,0,hwnd,14,57,16,8,
slog                                                                1342177291, `ws_child or ws_visible   or ss_simple
 {                                                               "Prezime","STATIC",0);
   cijeli hdc;
   cijeli fErase;                                                hStatic2:=CreateWindowExA(0,hInstance,0,hwnd,14,37,50,8,
   slog                                                             1342177291, `ws_child or ws_visible   or ss_simple
     { cijeli left,top,right,bottom; } rcPaint;                  "Ime","STATIC",0);
   cijeli fRestore;
   cijeli fIncUpdate;                                            hStatic3:=CreateWindowExA(0,hInstance,0,hwnd,14,72,200,16,
   cijeli [32] rgbReserved;                                         1342177291, `ws_child or ws_visible   or ss_simple
} pstruct;                                                       "Napomena","STATIC",0);

                                                                 hStatic4:=CreateWindowExA(0,hInstance,0,hwnd,14,103,8,272,
                                                               113
       1342177291, `ws_child or ws_visible      or ss_simple
    "Vrsta usluge","STATIC",0);

                                                             ` Korak 4: Prozorska procedura
hStatic5:=CreateWindowExA(0,hInstance,0,hwnd,14,78,128,280,  cijeli funkcija WndProc(cijeli lParam, cijeli wParam, cijeli
     1342177291, `ws_child or ws_visible   or ss_simple      msg, cijeli hwnd)
  "Adresa","STATIC",0);                                      {    cijeli obrada;
                                                                  obrada:=0;
                                                                  ako (msg=16){ DestroyWindow(hwnd); obrada:=1;}` WM_CLOSE
                                                                  ako (msg=15){ OnWMPaint(hwnd); obrada:=1;}` WM_PAINT
hStatic6:=CreateWindowExA(0,hInstance,0,hwnd,13,190,176,280,      ako (msg=2) {PostQuitMessage(0); obrada:=1;}` WM_DESTROY
     1342177291, `ws_child or ws_visible   or ss_simple           ako (msg=273) {OnWMCommand(wParam,lParam); obrada:=1;}
  "Stepen realizacije","STATIC",0);                            ` Poruka WM_COMMAND
                                                                  ako (msg=276) {OnWMHScroll(wParam,lParam); obrada:=1;}
  hMenu:=CreateMenu();                                       ` Poruka WM_HSCROLL
  hSubMenu := CreatePopupMenu();
  AppendMenuA( "O& programu",200,0,hSubMenu);                     ako (obrada#1) { DefWindowProcA(lParam,wParam,msg,hwnd);
  AppendMenuA( "I&zlaz",201,0,hSubMenu);                     }
  AppendMenuA("&Meni",hSubMenu,16,hMenu);                         inace {0;}
  SetMenu(hMenu,hwnd);
                                                             }
}

cijeli funkcija OnWMHScroll(cijeli wParam,cijeli lParam)        ` Glavni program
{ cijeli nPos;                                                  {

                                                                ` Korak 1: Registracija prozorske klase
    ako (lParam=hScroll1)& (wParam & 65535 =5) `SB_THUMBTRACK       hInstance:=GetModuleHandleA(0);
      {                                                             wc.cbSize        := 48;
         nPos:=wParam / 65536;                                      wc.style         := 0;
         SetScrollPos(1,nPos,2,hScroll1);                           wc.lpfnWndProc   := WndProc;
      }                                                             wc.cbClsExtra    := 0;
}                                                                   wc.cbWndExtra    := 0;
                                                                    wc.hInstance     := hInstance;
cijeli funkcija OnWMCommand(cijeli wParam,cijeli lParam)            wc.hIcon         := LoadIconA(32512,0); `IDI_APPLICATION
{ karakter [200] rezultat;                                          wc.hCursor       := LoadCursorA(32512,0); ` IDC_ARROW
  cijeli nItem;                                                     wc.hbrBackground := 5; `SIVA
                                                                    wc.lpszMenuName := 0;
    ako (lParam=0)                                                  wc.lpszClassName := "FILDZANKLASA";
    {                                                               wc.hIconSm       := LoadIconA(32512,0); `IDI_APPLICATION
      ako (wParam & 65535 = 201) {
        PostQuitMessage(0);                                              ako (!RegisterClassExA(&wc))
      }                                                                  {
      ako (wParam & 65535 = 200) {                                             MessageBoxA(0, "Greska","Neuspjela registracija!",0);
         MessageBoxA(0,"O programu",                                     }
      "Ovo je aplikacija koja demonstrira kontrole i GDI",0);            inace
      }                                                                  {
                                                                `            Korak 2: Kreiranje prozora
    }                                                                        hwnd:=CreateWindowExA(0,hInstance,0,0,383,535,
    ako (lParam=hButton1)                                                      177,108, 13565952, ` WS_OVERLAPPEDWINDOW
    {                                                                          "Forma za unos","FILDZANKLASA",512);
        GetWindowTextA(200,rezultat,hEdit1);                                 ako (hwnd = 0)
        MessageBoxA(0,"Prezime",rezultat,hwnd);                              {
        GetWindowTextA(200,rezultat,hEdit2);                                      MessageBoxA(0, "Greska","Neuspjelo kreiranje!",0);
        MessageBoxA(0,"Ime",rezultat,hwnd);                                  }
        GetWindowTextA(200,rezultat,hCombo1);                                inace
        MessageBoxA(0,"Adresa",rezultat,hwnd);                               {
        GetWindowTextA(200,rezultat,hMemo1);                                    KreirajKontrole();
        MessageBoxA(0,"Napomena",rezultat,hwnd);                                ShowWindow(10,hwnd); `SW_SHOW
        ako IsDlgButtonChecked(105,hGroup1)=1 {                                 UpdateWindow(hwnd);
           MessageBoxA(0,"Spol","Muski",hwnd);                                  ` Korak 3: Petlja poruka
        }                                                                       dok (GetMessageA(0,0,0,&Msg) > 0)
        ako IsDlgButtonChecked(106,hGroup1)=1 {                                 {
           MessageBoxA(0,"Spol","Zenski",hwnd);                                     TranslateMessage(&Msg);
        }                                                                           DispatchMessageA(&Msg);
                                                                                }
        ako     IsDlgButtonChecked(107,hwnd)=1 {                               Msg.wParam;
              MessageBoxA(0,"Status","Platio",hwnd);                       }
      }                                                              }
      nItem := SendMessageA(0,0,392,hListBox1);                 }
` LB_GETCURSEL
      ako nItem=2
        {
        }
            MessageBoxA(0,"TV","Ne koristi TV",hwnd);
                                                                              Sl. 15.4.2.       Aplikacija sa podprozorima -
      ako (GetScrollPos(2,hScroll1)>50) {                                                          kontrolama
        MessageBoxA(0,"Realizovanost","Preko 50",0);
      }
  }

}

cijeli funkcija OnWMPaint(cijeli hwnd)
{
   hdc:=BeginPaint(&pstruct,hwnd);
   MoveToEx(0,250,400,hdc);
   LineTo(250,480,hdc);
   LineTo(310,480,hdc);
   LineTo(310,400,hdc);
   LineTo(250,400,hdc);
   TextOutA(5,"CBLTV",253,403,hdc);
   Ellipse(294,470,264,410, hdc);
   EndPaint(&pstruct,hwnd);
}
                                                              114
        Na listingu Sl. 15.4.2 se vidi da se registracija prozorske klase uopšte nije promijenila, izuzev boje pozadine. Dijelu
koda za kreiranje prozora je dodan poziv funkcije KreirajKontrole nakon što je kreiran glavni program, dok je glavna petlja
poruka identiĉna osnovnoj verziji. Prozorska procedura obraĊuje pet poruka.
` Korak 4: Prozorska procedura
cijeli funkcija WndProc(cijeli lParam, cijeli wParam, cijeli msg, cijeli hwnd)
{   cijeli obrada;
    obrada:=0;
    ako (msg=16){ DestroyWindow(hwnd); obrada:=1;}` WM_CLOSE
    ako (msg=15){ OnWMPaint(hwnd); obrada:=1;}` WM_PAINT
    ako (msg=2) {PostQuitMessage(0); obrada:=1;}` WM_DESTROY
    ako (msg=273) {OnWMCommand(wParam,lParam); obrada:=1;} ` Poruka WM_COMMAND
    ako (msg=276) {OnWMHScroll(wParam,lParam); obrada:=1;}` Poruka WM_HSCROLL
        ako (obrada#1) { DefWindowProcA(lParam,wParam,msg,hwnd); }
    inace {0;}
}



          Poruka WM_COMMAND (broj 273) se šalje glavnom prozoru svaki put kada se izabere neka opcija na meniju ili
pritisne neki ekranski taster, radio taster ili checkbox. Ova poruka uz parametre wparam i lparam šalje dodatne vrijednosti koji
odreĊuju kontrolu.
           Poruka WM_PAINT (broj 15) se šalje glavnom prozoru svaki put kada se treba iscrtati dio prozora.
           Horizontalne klizne trake (scrollbar) šalju poruke WM_HSCROLL (broj 276).


15.5.      Meniji
         Kreiranje menija se vrši funkcijom CreateMenu(), a podmenija funkcijom CreatePopupMenu(). Ove funkcije interno
kreiraju menije, i dodijele mu identifikator, handle. To se vidi na dijelu koda koji se nalazi na kraju funkcije KreirajKontrole()
  hMenu:=CreateMenu();
  hSubMenu := CreatePopupMenu();
  AppendMenuA( "O& programu",200,0,hSubMenu);
  AppendMenuA( "I&zlaz",201,0,hSubMenu);
  AppendMenuA("&Meni",hSubMenu,16,hMenu);
  SetMenu(hMenu,hwnd);



          Za dodavanje opcija menija koristi se funkcija AppendMenuA, ĉiji prvi parametar predstavlja tekst opcije, drugi
parametar predstavlja broj koji će meni proslijediti uz poruku WM_COMMAND ili handle podmenija. Treći parametar
predstavlja status menija i ima vrijednost 0 ako je rijeĉ o opciji, a 16 ako je rijeĉ o podmeniju. Moguće je još mnogo razliĉitih
statusa. Posljednji parametar predstavlja handle menija ili podmenija kome se pridruţuje ova opcija.
           Meni se dodjeljuje prozoru primjenom opcije SetMenu, ĉiji je prvi parametar handle menija, a drugi je handle
prozora.
        Izbor opcije u meniju šalje glavnom prozoru poruku WM_COMMAND. Odgovor na opcije se vidi u sljedećem dijelu
koda unutar funkcije OnWMCommand


ako (lParam=0)
  {
    ako (wParam & 65535 = 201) {
      PostQuitMessage(0);
    }
    ako (wParam & 65535 = 200) {
       MessageBoxA(0,"O programu",
    "Ovo je aplikacija koja demonstrira kontrole i GDI",0);
    }
  }



       Poruka WM_COMMAND koja je stigla od menija u parametru lParam ima vrijednost 0, a niţih 16 bita parametra
wParam predstavlja konstantu koja je data uz drugi parametar funkcije AppendMenuA.


15.6.      Dugme - Button
           Kontrola oblika dugmeta se kreira kao i svaki prozor, CreateWindowExA funkcijom. U našem primjeru, to je naredba
hButton1:=CreateWindowExA(0,hInstance,0,hwnd,25,75,256,288,
    1342177280, ` ws_child or ws_visible or bs_pushbutton
  "Unesi","BUTTON",0);

         Kao što se vidi, klasa prozora je BUTTON, a stil je kombinacija ws_child , ws_visible i bs_pushbutton. Treći
parametar je hwnd, što znaĉi da je rijeĉ o kontroli koja ima roditelja, tj. prozor kome će se slati poruke. Posljednji parametar je
0 što znaĉi da nema specijalnog okvira.
                                                             115
        Prepoznavanje da je taster pritisnut moţe se vršiti u obradi poruke WM_COMMAND, što se vidi iz sljedećeg dijela
koda unutar funkcije OnWMCommand:
 ako (lParam=hButton1)
  {
    ...
  }


          Parametar lParam poruke WM_COMMAND sadrţi handle tastera koji je pritisnut, hButton1. U okviru obrade ovog
tastera se nalazi kod koji oĉitava vrijednosti svih kontrola i prikazuje ih na ekranu koristeći MessageBoxA.


15.7.     Editna i memo polja
        Najvaţnija kontrola za unos podataka su polja za unos teksta ili editna polja. Ove kontrole imaju klasu EDIT kao u
sljedećem dijelu koda
hEdit1:=CreateWindowExA(0,hInstance,0,hwnd,21,161,16,64,
    1350565888, ` ws_child or ws_visible or ws_border
  "","EDIT",512);

  hEdit2:=CreateWindowExA(0,hInstance,0,hwnd,21,161,48,64,
    1350565888, ` ws_child or ws_visible or ws_border
  "","EDIT",512);
         Memo polja se razlikuju od obiĉnih editnih polja po tome što imaju dodatni stil es_multiline
hMemo1:=CreateWindowExA(0,hInstance,0,hwnd,89,185,216,16,
    1350565892, ` ws_child or ws_visible or ws_border or es_multiline
  "Memo","EDIT",512);
         Oĉitavanje vrijednosti kontrole se svodi na ĉitanje naslova prozora funkcijom GetWindowTextA unutar obrade
pritiska na dugme. Prvi argument ove funkcije je broj bajtova koliki tekst treba da bude, drugi je adresa na koju se tekst
smješta a treći je hendl kontrole. U sljedećem dijelu koda se primljeni podaci prikazuju u poruci (prava aplikacija bi ih upisala
u bazu podataka)
GetWindowTextA(200,rezultat,hEdit1);
      MessageBoxA(0,"Prezime",rezultat,hwnd);
      GetWindowTextA(200,rezultat,hEdit2);
      MessageBoxA(0,"Ime",rezultat,hwnd);
      GetWindowTextA(200,rezultat,hCombo1);
      MessageBoxA(0,"Adresa",rezultat,hwnd);
      GetWindowTextA(200,rezultat,hMemo1);
      MessageBoxA(0,"Napomena",rezultat,hwnd);
        U sloţenijim sluĉajevima editno polje treba dodatno kontrolisati, recimo zabranjujući da se nenumeriĉke vrijednosti
uopšte mogu otkucati. To se radi obradom poruka koje editno polje direktno šalje glavnom prozoru.


15.8.     Grupe kontrola i radio tasteri
         Radio tasteri su okruglog oblika i omogućavaju izbor jedne od više opcija. Svaki radio taster predstavlja poseban
prozor klase BUTTON. Da bi se znalo izmeĊu kojih radio tastera se odabira opcija, formira se grupa tastera (group box) koja je
takoĊe prozor klase BUTTON, ali sa kombinacijom stilova ws_child, ws_visible i bs_groupbox, kao što se vidi iz dijela koda:


hGroup1:=CreateWindowExA(0,hInstance,0,hwnd,57,217,80,16,
     1342177287, ` ws_child or ws_visible or bs_groupbox
  "Spol","BUTTON",0);

         Radio tasteri imaju kombinaciju stilova ws_child, ws_visible i bs_autoradiobutton. Ono što je bitno primijetiti da se
za roditeljski prozor ne navodi handle od glavnog prozora, nego od grupe tastera hGroup1, te da su koordinate relativne u
odnosu grupu kontrola. Pored toga, svaki radio taster treba da ima svoju specijalnu numeriĉku oznaku koja je treći parametar i
koja u narednim linijama ima vrijednosti 105, odnosno 106.
  hRadio1:=CreateWindowExA(0,hInstance,105,hGroup1,17,113,16,24,
    1342177289, ` ws_child or ws_visible or bs_autoradiobutton
  "Muški","BUTTON",0);

  hRadio2:=CreateWindowExA(0,hInstance,106,hGroup1,17,113,32,24,
    1342177289, ` ws_child or ws_visible or bs_autoradiobutton
  "Ženski","BUTTON",0);

          Oĉitavanje vrijednosti radio tastera se vrši funkcijom IsDlgButtonChecked, ĉiji prvi argument ima vrijednost ranije
navedene numeriĉke oznake, a drugi je handle na grupu tastera. Ako je taster izabran, ova će funkcija vratiti taĉnu vrijednost,
što se vidi na sljedećem dijelu koda.
ako   IsDlgButtonChecked(105,hGroup1)=1 {
          MessageBoxA(0,"Spol","Muski",hwnd);
       }
       ako IsDlgButtonChecked(106,hGroup1)=1 {
          MessageBoxA(0,"Spol","Zenski",hwnd);
       }
                                                               116



15.9.         Kontrolne kućice (checkbox)
        Kontrolnom kućicom (checkbox) se omogućuje unos podataka koji imaju vrijednosti tipa taĉno/netaĉno. Ova
komponenta se kreira kao i obiĉni tasteri (prozor klase BUTTON) uz stil koji je kombinacija stilova ws_child, ws_visible i
bs_autocheckbox. I kod ove komponente je potrebno navesti internu oznaku (koja u sljedećem dijelu koda ima vrijednost 107)
hCheck1:=CreateWindowExA(0,hInstance,107,hwnd,17,209,152,16,
    1342177283, ` ws_child or ws_visible or bs_autocheckbox
  "Uplatio uvođenje","BUTTON",512);
             Oĉitavanje vrijednosti ove komponente se takoĊe vrši funkcijom IsDlgButtonChecked, kao u sljedećem dijelu koda:

        ako     IsDlgButtonChecked(107,hwnd)=1 {
              MessageBoxA(0,"Status","Platio",hwnd);
         }


15.10. Liste podataka (listbox)
          Liste podataka (listbox) sluţe za izbor podataka poredanih jedan iznad drugog. I ova kontrola se kreira kao prozor, ali
koji je klase LISTBOX. Stil je kombinacija ws_child , ws_visible , ws_border i lbs_standard. Kreiranom listboxu, treba poslati
vrijednosti koristeći funkciju SendMessageA. Prvi argument ove funkcije (lParam) je pointer na niz karaktera koji se dodaje u
listbox, drugi je 0 (wParam), treći je 384 ( poruka LB_ADDSTRING) a ĉetvrti je handle na listbox.
hListBox1:=CreateWindowExA(0,hInstance,0,hwnd,97,200,24,272,
    1352663043, ` ws_child or ws_visible or ws_border or lbs_standard
  "List1","LISTBOX",512);

  SendMessageA("1.Samo     TV program",0,384,hListBox1); ` 384 LB_ADDSTRING
  SendMessageA("2.TV i     Internet",0,384,hListBox1); ` 384 LB_ADDSTRING
  SendMessageA("3.Samo     Internet",0,384,hListBox1); ` 384 LB_ADDSTRING
  SendMessageA("4.TV s     kodiranimkanalima",0,384,hListBox1); ` 384 LB_ADDSTRING
  SendMessageA("5.Puni     paket",0,384,hListBox1); ` 384 LB_ADDSTRING
       Da bi se saznalo koja je opcija listbox-a odabrana, pošalje se poruka LB_GETCURSEL (392) listboxu uz lparam i
wparam parametre jednake 0.
        nItem := SendMessageA(0,0,392,hListBox1); ` LB_GETCURSEL
        ako nItem=2
          {   MessageBoxA(0,"TV","Ne koristi TV",hwnd);
          }




15.11. Kombinovane liste (combo box)
         Kombinovanjem listboxa i editnog polja dobija se combo box. On je prozor klase COMBOBOX, i kreira se i puni
sliĉno LISTBOXu, s tim što je stil prozora kombinacija ws_child, ws_visible, ws_border, cbs_dropdown i cbs_hasstrings a
kod poruke za punjenje 323 (cb_addstring). Nazivi ulica su stavljeni u combobox koji je tipa dropdown, što znaĉi da je moguće
dokucavati uneseni tekst. Druga dva tipa su simple koji je fiksnog izgleda i dropdownlist koji je promjenjive veliĉine, ali je
tekst moguće samo izabrati, ne i dokucavati.


hCombo1:=CreateWindowExA(0,hInstance,0,hwnd,100,145,144,272,
    1350566402, ` ws_child or ws_visible or ws_border or cbs_dropdown or cbs_hasstrings
  "COmbobox1","COMBOBOX",0);
  SendMessageA("Maršala Tita",0,323,hCombo1); ` 323 CB_ADDSTRING
  SendMessageA("Alipašina",0,323,hCombo1); ` 323 CB_ADDSTRING

             Oĉitavanje stringa koji je izabran u ComboBoxu se moţe obaviti oĉitavanjem naslova prozora.
        MessageBoxA(0,"Adresa",rezultat,hwnd);
        GetWindowTextA(200,rezultat,hMemo1);




15.12. Statički tekst
         Pored odgovora na WM_PAINT poruku, statiĉki tekst se takoĊe moţe realizovati u formi podprozora klase static. O
iscrtavanju ovakvih tekstova na formama brine kasnije sam Windows.
hStatic1:=CreateWindowExA(0,hInstance,0,hwnd,14,57,16,8,
     1342177291, `ws_child or ws_visible   or ss_simple
  "Prezime","STATIC",0);

  hStatic2:=CreateWindowExA(0,hInstance,0,hwnd,14,37,50,8,
     1342177291, `ws_child or ws_visible   or ss_simple
  "Ime","STATIC",0);

  hStatic3:=CreateWindowExA(0,hInstance,0,hwnd,14,72,200,16,
     1342177291, `ws_child or ws_visible   or ss_simple
                                                               117
    "Napomena","STATIC",0);

    hStatic4:=CreateWindowExA(0,hInstance,0,hwnd,14,103,8,272,
       1342177291, `ws_child or ws_visible   or ss_simple
    "Vrsta usluge","STATIC",0);

    hStatic5:=CreateWindowExA(0,hInstance,0,hwnd,14,78,128,280,
       1342177291, `ws_child or ws_visible   or ss_simple
    "Adresa","STATIC",0);


    hStatic6:=CreateWindowExA(0,hInstance,0,hwnd,13,190,176,280,
       1342177291, `ws_child or ws_visible   or ss_simple
    "Stepen realizacije","STATIC",0);




15.13. Klizna traka (scrollbar)
         Iako se daleko ĉešće koristi za pregled velikih slika ili skupova korisniĉkih kontrola koje ne mogu stati na ekran,
horizontalna klizna traka se moţe koristiti i za unos podataka ĉija vrijednost nije egzaktna nego pribliţna. Pomicanje klizne
trake izaziva poruku WM_HSCROLL (broj 276). U programu je ova poruka obraĊena u funkciji OnWMHScroll
cijeli funkcija OnWMHScroll(cijeli wParam,cijeli lParam)
{ cijeli nPos;


    ako (lParam=hScroll1)& (wParam & 65535 =5) `SB_THUMBTRACK
      {
         nPos:=wParam / 65536;
         SetScrollPos(1,nPos,2,hScroll1);
      }
}
          Postoji više naĉina pomicanja klizne trake, povlaĉenjem kvadratića na njoj, klikom na strelice ili klikom u prazna
polja. Ovdje je obraĊeno samo povlaĉenje kvadratića (u niţoj rijeĉi wParama vrijednost 5, poruka SB_THUMBTRACK).
Prilikom povlaĉenja kvadratića na kliznoj traci(ali samo u tom sluĉaju), viša rijeĉ parametra wparam će sadrţati novu poziciju.
Ta pozicija neće biti zadrţana ako se ne pozove funkcija SetScrollPos, ĉiji prvi parametar znaĉi da li će se klizna traka ponovo
iscrtati, drugi parametar definiše njenu novu poziciju. Treći parametar govori da li je rijeĉ o horizontalnoj kliznoj traci,
vertikalnoj kliznoj traci samog prozora ili odvojenoj kontroli (vrijednost 2). Ĉetvrti parametar je handle na kliznu traku.
         Trenutna pozicija klizne trake se dobija funkcijom GetScrollPos, ĉiji prvi parametar predstavlja vrstu klizne trake (u
našem sluĉaju 2, odvojena kontrola), a drugi je hendl na kliznu traku. U ovom dijelu koda se provjerava da li klizna traka ima
vrijednost preko 50.
ako (GetScrollPos(2,hScroll1)>50) {
        MessageBoxA(0,"Realizovanost","Preko 50",0);
      }




15.14. Iscrtane slike i WM_PAINT poruka
         Za iscrtavanje grafike postoji jedan poseban podsistem koji se zove GDI, graphic device interface. On omogućava
širok izbor grafiĉkih elemenata kao što su linije, krugovi, elipse, ispunjeni likovi, bitmape, tekstualne poruke, i sliĉno
         Većina ovih funkcija koristi jedan specijalni identifikator dijela prozora po kome se crta, koji se zove hdc (handle to
device context - kontekst ureĊaja). On se dobija pozivom odgovarajućih funkcija iz hendla na prozor, hwnd. Razlog zbog ĉega
API funkcije za crtanje razdvajaju prozor od njegovog konteksta ureĊaja je u ĉinjenici da prozor ima okvir i korisnu površinu i
da crtanje po korisnoj površini ne mijenja sadrţaj okvira i obrnuto.
          Nije, meĊutim dobro iscrtavati sliku bilo kada. Iscrtavanje drugih prozora u sistemu lako prekriva iscrtanu sliku, pa se
ono što je iscrtano izgubi. Stoga je iscrtavanje potrebno obaviti svaki put kada je primljena poruka WM_PAINT (poruka broj
15). Ovu poruku šalje sistem kada je prozor doţivio takvu promjenu da ga je potrebno ponovo crtati (recimo, otkriven nakon
što je bio prekriven ili su mu promijenjene dimenzije.
          Unutar funkcije OnWMPaint iscrtava se predviĊeni lik. Funkcijom BeginPaint, koja ima dva parametra: struktura za
crtanje i handle na prozor, daje se informacija Windowsu da se poĉinje sa iscrtavanjem. Struktura za crtanje je slog koji sadrţi
informacije o pravougaoniku koji se iscrtava. Rezultat funkcije BeginPaint je handle na kontekst ureĊaja (device context).
Crtanje se završava funkcijom EndPaint koja ima iste argumente.
cijeli funkcija OnWMPaint(cijeli hwnd)
{
   hdc:=BeginPaint(&pstruct,hwnd);
   MoveToEx(0,250,400,hdc);
   LineTo(250,480,hdc);
   LineTo(310,480,hdc);
   LineTo(310,400,hdc);
   LineTo(250,400,hdc);
   TextOutA(5,"CBLTV",253,403,hdc);
   Ellipse(294,470,264,410, hdc);
   EndPaint(&pstruct,hwnd);
}
                                                             118
          IzmeĊu funkcija BeginPaint i EndPaint mogu se vidjeti funkcije za crtanje. Prvi parametar funkcije MoveToEx, koja
sluţi za postavljanje poĉetne taĉke je pointer na slog koji bi vratio prethodne koordinate ili vrijednost 0 ukoliko prethodne
koordinate nije potrebno oĉitavati. Drugi parametar predstavlja y koordinatu taĉke, treći parametar predstavlja x koordinatu, a
ĉetvrti hendl na kontekst ureĊaja. Taĉka postavljena funkcijom MoveToEx je poĉetna taĉka za iscrtavanje linija. Linije se dalje
iscrtava do taĉke ĉije su y i x koordinate navedene kao prvi i drugi parametar funkcije LineTo. Krajnja taĉka tako iscrtane
linije postaje poĉetna taĉka za novu liniju.
          Ispis teksta se obavlja funkcijom TextOutA. Prvi argument ove funkcije je broj bajtova koliko je velik string koji se
ispisuje, drugi je sam string, treći i ĉetvrti su same koordinate stringa a posljednji je handle na kontekst ureĊaja.
         Moguće je iscrtavati i elipse. Funkcija Ellipse za argumente ima redom: y koordinatu donjeg desnog ugla kvadrata
koji je opisuje, x koordinatu donjeg desnog ugla kvadrata koji je opisuje, y koordinatu gornjeg lijevog ugla kvadrata koji je
opisuje, x koordinatu donjeg lijevog ugla kvadrata koji je opisuje i handle na kontekst ureĊaja.


15.15. Rezime poglavlja
         Pod windowsom kontrole su takoĊe prozori. Svaka kontrola se kreira funkcijom CreateWindowExA i ima nekoliko
predefinisanih klasa. Sve kontrole osim radio tastera trebaju da za roditelja imaju glavni prozor. Radio tasteri se smještaju u
grupe. Podaci koje kontrole šalju se oĉitavaju na razliĉite naĉine. Dodatno iscrtani grafiĉki elementi se trebaju crtati kao
odgovor na poruku WM_PAINT. Sve funkcije za crtanje dio su podsistema koji se zove GDI i kao argument imaju handle na
kontekst ureĊaja koji se prosljeĊuje kao zadnji argument funkcija za crtanje.




        -.
                                                           119
16.SPISAK WIN32API FUNKCIJA
        U prethodnim poglavljima upoznato je sa osnovama Windows API-ja. Sada slijedi spisak svih API funkcija koje
savremene verzije Windowsa pruţaju.

16.1.    Najvaţniji podsistemi Windows API-ja
        Windows API je kompilacija razliĉitih skupova funkcija namijenjenih programerima. Najvaţniji njegovi dijelovi su:
        - Windows Kernel
        - Korisniĉki interfejs
        - Grafiĉki podsistem GDI
        - Funkcije za slanje poruka MAPI
        - Funkcije za rad sa interfejsom za telefon TAPI
        - COM, objektni model za kooperaciju odvojenih aplikacija
        - OLE/Active X, nadgradnja COMa za pravljenje aplikacija ĉije su komponente druge aplikacije
        - ODBC, funkcije za pristup bazama podataka
        - Kontrole unaprijeĊenog korisniĉkog interfejsa
        - DirectX, nadgradnja COMa za direktni pristup grafiĉkom hardveru i zvuku
        - RASAPI za pristup preko modema
        - Winsock za pravljenje Internet aplikacija
        -MCI, za pristup multimedijalnim ureĊajima.
        -OPENGL za trodimenzionalnu grafiku
        - Standardni dijalozi
         Api funkcija ima mnogo i jedini naĉin da se one nauĉe je analizom gotovih programa. Stoga većina Windows API
aplikacija ima standardan izgled. Tako na primjer, ODBC aplikacije izgledaju kao na slici Sl. 16.1.1:




                                            Sl. 16.1.1.     Osnovna ODBC aplikacija
                                                           120


16.2.    DLL datoteke u kojima se nalaze funkcije
        Standardnim API funkcijama windowsa smatraju se one koje se nalaze u sljedećim DLL datotekama:

ACLUI.DLL    Korisnički interfejs za kontrolu prava
pristupaACTIVEDS.DLL Active Directory Services                   MSVFW32.DLL Video for Windows
ADVAPI32.DLL Razni sistemski pozivi uključujući                  MSWSOCK.DLL Microsoftove nestandardne Winsock funkcije
sigurnost i registry                                             NAL.DLL   Sloj abstrakcije mreže
bdnapi.DLL     Web TV biblioteka                                 netapi32.dll Za pristup Microsoftovim mrežama
bignums.dll    Račun sa velikim brojevima                        NTDLL.DLL Za pristup internim funkcijama Windowsa NT
CAP.DLL      Dijagnostika                                        NTMSAPI.DLL Removable Storage API (proširenje diskova
COMCTL32.DLL Savremene kontrole korisničkog interfejsa           trakama)
COMDLG32.DLL Standardni dijalozi
CRTDLL.DLL Standardna C biblioteka, printf, sin itd              ODBC32.DLL Pristup bazama podataka
CRYPT32.DLL Kriptografske funkcije                               ODBCCP32.dll Podešavanje ODBC
ctl3d32.dll Trodimenzionalni izgled kontrola                     ole32.dll Osnovne OLE funkcije
d3dim.DLL     Proširenje arhitekture Direct3D                    OLEAUT32.DLL Ole automatizacija
D3DRM.DLL     Direct3D vektorske funkcije                        oledlg.DLL OLE dijalozi (Insert Object)
d3dxof.DLL    Direct3D aplikacijska biblioteka                   OLEPRO32.DLL Microsoftove vlastite OLE funkcije
dapi.DLL      Za pristup direktoriju MS Exchangea                opengl.dll Silicon Graphics OpenGL biblioteka
ddraw.dll     Direct Draw, glavna datoteka                       opengl32.dll Microsoft OpenGL Biblioteka
dflayout.dll Definisanje rasporeda podataka u složeniim          pdh.dll Performance Data Helper
dokumentima                                                      penwin32.dll Za Windows koji se upravlja olovkom
DINPUT.DLL    DirectInput (za DirectX pristup joysticku,         pkdp32.dll Za Windows koji se upravlja olovkom
tastaturi, mišu)                                                 PSAPI.DLL Spisak procesa koji se izvršavaju
dlcapi.dll Pristupanje DLC protokolu za HP mrežne                RASAPI32.DLL RAS Pristup sistemu preko modema
štampače                                                         rasdlg.dll Dijalozi koji se koriste u RAS
DPLAY.DLL     DirectPlay, za igranje preko mreže                 rassapi.dll RAS administracijske funkcije
DPLAYX.DLL    DirectPlay, proširenje                             RESUTILS.DLL Pristup Windows resursima
DSETUP.DLL    Za instalaciju DirectX                             RICHED20.DLL RichEdit kontrola
DSOUND.DLL    DirectSound, zvuk u DirectX                        rpcns4.dll Name Service u pozivu udaljene procedure
dynloader.dll Analiza OBJ datoteka                               (RPC)
edbbcli.DLL Alatke za MS Exchange server                         RPCRT4.DLL API za poziv udaljene procedure
gc.dll Garbage collector                                         RTM.DLL Upravljač tabelom rutiranja
GDI32.DLL     Grafičke biblioteke za prikaz linija i             Secur32.DLL Windows sigurnosne funkcije
bitmapa                                                          SETUPAPI.DLL Instalacija Windowsa
glide2x.dll 3D biblioteka za 3DFX 3D grafičke                    SHELL32.DLL Veza između aplikacije i FileManagera,
akceleratore                                                     Explorera
glu32.dll Pomoćne funkcije koje OpenGL aplikacije                SHFOLDER.DLL Pristup specijalnim folderima (My
koriste za prikaz 3D grafike                                     Documents)
GLUT32.DLL Varijanta OpenGL sa izmjenjenim imenima               SHLWAPI.DLL Pomoćne funkcije za pristup stazama,
funkcija                                                         urlovima, registriju i bojama
HLINK.DLL Rad sa hiperlinkovima                                  snmpapi.dll Pristup SNMP funkcijama za praćenje mreže i
ICMP.DLL    Za komandu PING                                      servera
ICMUI.DLL Korisnički interfejs za Microsoft Color                svrapi.dll   Kontrola dijeljenih (share) resursa na
Matching System                                                  Microsoft mreži
imagehlp.dll Za analiziranje EXE datoteka                        tapi32.dll   Telefonski API
IMM32.DLL Unošenje azijskih UNICODE znakova                      TOOLHELP.DLL Funkcije za debagiranje i praćenje sistema
iphlpapi.DLL Informacije o mrežnoj konfiguraciji i               URL.DLL      Pokretanje Web browsera preko URL adrese
statistici                                                       URLMON.DLL   Proširenje OLE32
IPROP.DLL Implementacija OlePropertySet                          USER32.DLL   Najbitnije funkcije za rad sa prozorima i
KERNEL32.DLL Upravljanje memorijom i I/O operacijama             kontrolama
loadperf.dll Upravljanje perfomance monitorom                    USERENV.DLL Pristup korisničkim profajlovima
LSAPI32.DLL Informacije o licenciranju                           version.dll Informacije o broju verzije izvršnog
lz32.dll Kompresija podataka                                     programa
mapi32.dll Slanje i obrada EMAIL poruka                          webpost.dll Slanje Web stranica na internet
mgmtapi.DLL Biblioteka za upravljanje resursima preko            win32spl.dll Pristup printer spooleru
SNMP                                                             WINFAX.DLL   Rad sa telefaxom
MPR.DLL     Punjenje Network Neighboorhooda spiskom              WININET.DLL Microsoft Internet funkcije
mašina                                                           winmm.dll    Windows multimedia API
MPRAPI.DLL Pristup funkcijama za rutiranje                       wintrust.dll Autentifikacija tajnim i javnim ključem
MSACM32.DLL Upravljanje audio kompresijom                        WOW32.dll    Podrška 16 bitnim aplikacijama
mscms.DLL    Color Matching biblioteka (prilikom štampe)         WS2_32.DLL   Winsock 2.0
MSI.DLL     Windows Installer                                    wsock32.dll Winsock API
MSLSP32.DLL Informacije o licenciranju                           wst.dll      Working Set Tuner (optimalan broj stranica
MSVCRT.DLL Microsoft C runtime biblioteka                        u RAMu)
MSVCRTD.DLL Microsoft C runtime biblioteka, debug
verzija




16.3.    Spisak API funkcija
          Sada su navedene sve dokumentovane funkcije koje se nalaze u pojedinim bibliotekama, a koje je moguće pozvati iz
FILDZAN-32 ili drugih programskih jezika. Puna sintaksa svake od njih, namjena i naĉin korištenja mogu se naći na Internetu
ili na CD-ovima Microsoft Developers Network. Ovdje su navedeni ime funkcije, biblioteka, oznaka NM/AW, broj parametara
i kratki opis funkcije. Ako je navedena oznaka AW, tada se pri deklaraciji i pozivu funkcije njenom imenu dodaje slovo A za
Ascii stringove ili W za Unicode stringove (npr CreateWindowEx se u Fildzan32 piše CreateWindowExA). Pri oznaci NM
ovog sufiksa nema.
                                                                                               121
AbortDoc,GDI32.DLL,NM,1, stops the current print job and erases everything drawn since the AddPrinterDriver,WINMM.DLL,AW,3, installs a local or remote printer driver and links the
last call to the StartDoc function.                                                               configuration, data, and driver files.
AbortPath,GDI32.DLL,NM,1, closes and discards any paths in the specified device context.          AddPrintProcessor,WINMM.DLL,AW,5 installs a print processor on thespecified server and
AbortPrinter,WINMM.DLL,NM,1, deletes a printer?s spool file if the printer is configured for      adds the print-processor name to an internallist of supported print processors.
spooling.                                                                                         AddPrintProvidor,WINMM.DLL,AW,3, installs a local printer provider and links the configuration,
AbortSystemShutdown,ADVAPI32.DLL,AW,1, stops a system shutdown started by using the               data, and provider files.
InitiateSystemShutdown function.                                                                  AdjustTokenGroups,ADVAPI32.DLL,NM,6, adjusts groups in the specified access token.
accept,WS2_32.DLL,NM,3, extracts the first connection on the queue of pending connections AdjustTokenPrivileges,ADVAPI32.DLL,NM,6 enables or disables privileges in the specified
on socket s.                                                                                      access token.
accept,WSOCK32.DLL,NM,3, extracts the first connection on the queue of pending connections AdjustWindowRect,USER32.DLL,NM,3 calculates the required size of the window rectangle,
on socket s.                                                                                      based on the desired client-rectangle size.
AcceptEx,MSWSOCK.DLL,NM,8, combines several socket functions into a single API/kernel             AdjustWindowRectEx,USER32.DLL,NM,4 calculates the required size of thewindow rectangle,
transition.                                                                                       based on the desired size of the clientrectangle.
AcceptEx,WSOCK32.DLL,NM,8, combines several socket functions into a single API/kernel             ADsBuildEnumerator,ACTIVEDS.DLL,NM,2 Builds an enumerator object for the specified
transition.                                                                                       Active Directory container object.
AcceptSecurityContext,SECUR32.DLL,NM,9,This function enables the server part of a                 ADsBuildVarArrayInt,ACTIVEDS.DLL,NM,3 Builds a VARIANT array from an array of
transport application to establish a security context between the server and a remote client.     DWORDS.
AccessCheck,ADVAPI32.DLL,NM,8 is used by a server application to check aclient?s access to ADsBuildVarArrayStr,ACTIVEDS.DLL,NM,3 Builds a VARIANT array from an array of Unicode
an object against the access control associatedwith the object.                                   strings.
AccessCheckAndAuditAlarm,ADVAPI32.DLL,AW,11, performs an access validation and                    ADsEnumerateNext,ACTIVEDS.DLL,NM,4 Populates a VARIANT arrray with elements fetched
generates corresponding audit messages.                                                           from the indicated enumerator object.
AccessNtmsLibraryDoor,NTMSAPI.DLL,NM,3, unlocks the door of the specified library. If the         ADsFreeEnumerator,ACTIVEDS.DLL,NM,1 Frees an enumerator object previously created
library is busy, RSM queues the request and returns successfully.                                 through ADsBuildEnumerator
acmDriverAdd,MSACM32.DLL,AW,5, adds a driver to the list of available ACM drivers.                ADsGetLastError,ACTIVEDS.DLL,NM,5 Retrieves the calling thread?s last-error code value.
acmDriverClose,MSACM32.DLL,NM,2, closes a previously opened ACM driver instance.                  ADsGetObject,ACTIVEDS.DLL,NM,3 In Active Directory, bind to an object given its path and
acmDriverDetails,MSACM32.DLL,AW,3, queries a specified ACM driver to determine its                primaryinterface identifier (IID).
capabilities.                                                                                     ADsOpenObject,ACTIVEDS.DLL,NM,6 In Active Directory, bind to an object using username
acmDriverEnum,MSACM32.DLL,NM,3 enumerates the available ACM drivers,continuing until and passwordcredentials.
there are no more drivers or the callback functionreturns FALSE.                                  ADsSetLastError,ACTIVEDS.DLL,NM,3 Sets the calling thread?s last-error code value.
acmDriverID,MSACM32.DLL,NM,3 returns the handle of an ACM driveridentifier associated             AdvancedDocumentProperties,WINMM.DLL,AW,5 displays a printerconfiguration dialog box for
with an open ACM driver instance or streamhandle.                                                 the specified printer, allowing theuser to configure that printer.
acmDriverMessage,MSACM32.DLL,NM,4 sends a user-defined message to a given ACM driver AllocateAndInitializeSid,ADVAPI32.DLL,NM,11, allocates and initializes a security identifier
instance.                                                                                         (SID) with up to eight subauthorities.
acmDriverOpen,MSACM32.DLL,NM,3 opens the specified ACM driver andreturns a driver                 AllocateLocallyUniqueId,ADVAPI32.DLL,NM,1, allocates a locally unique identifier (LUID).
instance handle that can be used to communicatewith the driver.                                   AllocateNtmsMedia,NTMSAPI.DLL,NM,6, allocates a piece of available media.
acmDriverPriority,MSACM32.DLL,NM,3, modifies the priority and state of an ACM driver.             AllocConsole,KERNEL32.DLL,NM,0, allocates a new console for the calling process.
acmDriverRemove,MSACM32.DLL,NM,2, removes an ACM driver from the list of available                AngleArc,GDI32.DLL,NM,6, moves the current position to the ending point of the arc.
ACM drivers.                                                                                      AnimatePalette,GDI32.DLL,NM,4 replaces entries in the specified logical palette.
acmFilterChoose,MSACM32.DLL,AW,1, creates an ACM-defined dialog box that enables the              AnimateWindow,USER32.DLL,NM,3, enables you to produce special effects when showing or
user to select a waveform-audio filter.                                                           hiding windows.
acmFilterDetails,MSACM32.DLL,AW,3 queries the ACM for details about a filter with a specific AnyPopup,USER32.DLL,NM,0, indicates whether an owned, visible, top- level pop-up, or
waveform-audio filter tag.                                                                        overlapped window exists on the screen.
acmFilterEnum,MSACM32.DLL,AW,5, enumerates waveform-audio filters available for a given AppendMenu,USER32.DLL,AW,4, appends a new item to the end of the specified menu bar,
filter tag from an ACM driver.                                                                    drop-down menu, submenu, or shortcut menu.
acmFilterTagDetails,MSACM32.DLL,AW,3, queries the ACM for details about a specific                ApplyControlToken,SECUR32.DLL,NM,2,Provides a way to apply a control token to a security
waveform-audio filter tag.                                                                        context.
acmFilterTagEnum,MSACM32.DLL,AW,5, will return MMSYSERR_NOERROR (zero) if no filter Arc,GDI32.DLL,NM,9, draws an elliptical arc.
tags are to be enumerated.                                                                        ArcTo,GDI32.DLL,NM,9, draws an elliptical arc.
acmFormatChoose,MSACM32.DLL,AW,1 function creates an ACM-defined dialog box that                  AreAllAccessesGranted,ADVAPI32.DLL,NM,2, checks whether a set of requested access rights
enables the user to select a waveform-audio format.                                               has been granted.
acmFormatDetails,MSACM32.DLL,AW,3, queries the ACM for format details for a specific              AreAnyAccessesGranted,ADVAPI32.DLL,NM,2, tests whether any of a set of requested access
waveform-audio format tag.                                                                        rights has been granted.
acmFormatEnum,MSACM32.DLL,AW,5, enumerates waveform-audio formats available for a                 AreFileApisANSI,KERNEL32.DLL,NM,0, determines whether a set of Win32 file functions is
given format tag from an ACM driver.                                                              using the ANSI or OEM character set code page.
acmFormatSuggest,MSACM32.DLL,NM,5 queries the ACM or a specified ACMdriver to                     ArrangeIconicWindows,USER32.DLL,NM,1, arranges all the minimized (iconic) child windows
suggest a destination format for the supplied sourceformat.                                       of the specified parent window.
acmFormatTagDetails,MSACM32.DLL,AW,3, queries the ACM for details on a specific                   AssociateColorProfileWithDevice,MSCMS.DLL,AW,3, associates a specified color profile with a
waveform-audio format tag.                                                                        specified device.
acmFormatTagEnum,MSACM32.DLL,AW,5, enumerates waveform-audio format tags available AttachThreadInput,USER32.DLL,NM,3, fails if either of the specified threads does not have a
from an ACM driver.                                                                               message queue.
acmGetVersion,MSACM32.DLL,NM,0, returns the version number of the ACM.                            auxGetDevCaps,WINMM.DLL,AW,3, retrieves the capabilities of a given auxiliary output
acmMetrics,MSACM32.DLL,NM,3, returns various metrics for the ACM or related ACM objects. device.
acmStreamClose,MSACM32.DLL,NM,2 closes an ACM conversion stream. If the function is               auxGetNumDevs,WINMM.DLL,NM,0, retrieves the number of auxiliary output devices present
successful, the handle is invalidated.                                                            in the system.
acmStreamConvert,MSACM32.DLL,NM,3, requests the ACM to perform a conversion on the                auxGetVolume,WINMM.DLL,NM,2, retrieves the current volume setting of the specified
specified conversion stream.                                                                      auxiliary output device.
acmStreamMessage,MSACM32.DLL,NM,4, sends a driver-specific message to an ACM driver. auxOutMessage,WINMM.DLL,NM,4, sends a message to the given auxiliary output device.
acmStreamOpen,MSACM32.DLL,NM,8, opens an ACM conversion stream.                                   auxSetVolume,WINMM.DLL,NM,2, sets the volume of the specified auxiliary output device.
acmStreamPrepareHeader,MSACM32.DLL,NM,3, prepares an ACMSTREAMHEADER                              BackupEventLog,ADVAPI32.DLL,AW,2, saves the specified event log to a backup file.
structure for an ACM stream conversion.                                                           BackupFree,EDBBCLI.DLL,NM,1, frees a backup memory buffer.
acmStreamReset,MSACM32.DLL,NM,2 stops conversions for a given ACM stream. All pending BackupRead,KERNEL32.DLL,NM,7, reads data associated with a specified file or directory into
buffers are marked as done and returned to the application.                                       a buffer.
acmStreamSize,MSACM32.DLL,NM,4, returns a recommended size for a source or destination BackupSeek,KERNEL32.DLL,NM,6, seeks forward in a data stream initially accessed by using
buffer on an ACM stream.                                                                          the BackupRead or BackupWrite function.
acmStreamUnprepareHeader,MSACM32.DLL,NM,3 cleans up the preparation performed by                  BackupWrite,KERNEL32.DLL,NM,7, writes a stream of data from a buffer to a specified file or
the acmStreamPrepareHeader </native/sdk/win32/vfw/src/mmfu5dwy.htm> function for an ACM directory.
stream.                                                                                           BatchExport,DAPI.DLL,AW,1, exports objects from the Microsoft Exchange Server directory.
AcquireCredentialsHandle,SECUR32.DLL,AW,9,Acquires a handle to preexisting credentials of BatchImport,DAPI.DLL,AW,1, imports directory service objects from a text file in a single
a security principal.                                                                             function call.
AcsLan,DLCAPI.DLL,NM,2 communicates with IBM mainframes or networkperipheral devices, Beep,KERNEL32.DLL,NM,2, generates simple tones on the speaker.
such as printers connected directly to thenetwork, by using the data link control (DLC) protocol. BeginDeferWindowPos,USER32.DLL,NM,1 allocates memory for a multiple-window - position
ActivateKeyboardLayout,USER32.DLL,NM,2 The ActivateKeyboardLayout function activates a structure and returns the handle to thestructure.
different keyboard layout and sets the active keyboard layout for the entire system rather than BeginPaint,USER32.DLL,NM,2 prepares the specified window for paintingand fills a
the calling thread.                                                                               PAINTSTRUCT structure with information about thepainting.
AddAccessAllowedAce,ADVAPI32.DLL,NM,4, adds an access-allowed ACE to an ACL.                      BeginPath,GDI32.DLL,NM,1, opens a path bracket in the specified device context.
AddAccessDeniedAce,ADVAPI32.DLL,NM,4, adds an access-denied ACE to an ACL.                        BeginUpdateResource,KERNEL32.DLL,AW,2 returns a handle that can be usedby the
AddAce,ADVAPI32.DLL,NM,5, adds one or more ACEs to a specified ACL.                               UpdateResource function to add, delete, or replace resourcesin an executable file.
AddAtom,KERNEL32.DLL,AW,1, adds a character string to the local atom table and returns a bind,WS2_32.DLL,NM,3, is used on an unconnected socket before subsequent calls to the
unique value (an atom) identifying the string.                                                    connect or listen functions.
AddAuditAccessAce,ADVAPI32.DLL,NM,6, adds a system-audit ACE to a system ACL.                     bind,WSOCK32.DLL,NM,3, is used on an unconnected socket before subsequent calls to the
AddFontResource,GDI32.DLL,AW,1, adds the font resource from the specified file to the             connect or listen functions.
Windows font table.                                                                               BindImage,IMAGEHLP.DLL,NM,3, computes the virtual address of each imported function.
AddForm,WINMM.DLL,AW,3, adds a form to the list of available forms that can be selected for BindImageEx,IMAGEHLP.DLL,NM,5, computes the virtual address of each function that is
the specified printer.                                                                            imported.
AddJob,WINMM.DLL,AW,5 obtains a path string that specifies a file that you can use to store a BindMoniker,OLE32.DLL,NM,4,This function locates an object by means of its moniker,
spooled print job.                                                                                activates the object if it is inactive, and retrieves a pointer to the specified interface on that
AddMonitor,WINMM.DLL,AW,3 installs a local printer monitor and links the configuration, data, object.
and monitor files.                                                                                BitBlt,GDI32.DLL,NM,9 performs a bit-block transfer of the color datacorresponding to a
AddNtmsMediaType,NTMSAPI.DLL,NM,3, adds the specified media type to the specified library rectangle of pixels from the specified sourcedevice context into a destination device context.
if there is not currently a relation in the library object. The function then creates the system  BringWindowToTop,USER32.DLL,NM,1, brings the specified window to the top of the Z order.
media pools if they do not exist.                                                                 BroadcastSystemMessage,USER32.DLL,AW,5, sends a message to the specified recipients.
AddPort,WINMM.DLL,AW,3, adds the name of a port to the list of supported ports.                   BstrFromVector,OLEAUT32.DLL,NM,2,Returns a BSTR, assigning each element of the vector
AddPrinter,WINMM.DLL,AW,3 adds a printer to the list of supported printers for a specified        to a character in the BSTR.
server.                                                                                           BuildCommDCB,KERNEL32.DLL,AW,2, fills a specified DCB structure with values specified in
AddPrinterConnection,WINMM.DLL,AW,1, adds a connection to the specified printer for the           a device-control string.
current user.                                                                                     BuildCommDCBAndTimeouts,KERNEL32.DLL,AW,3 translates a device-definitionstring into
                                                                                                  appropriate device-control block codes and then placesthese codes into a device control block.
                                                                                               122
BuildDisplayTable,MAPI32.DLL,NM,10, creates a display table from the property page data              CertFindExtension,CRYPT32.DLL,NM,3, finds the first extension in the CERT_EXTENSION
contained in one or more DTPAGE structures.                                                          array, as identified by its object identifier (OID).
BuildExplicitAccessWithName,ADVAPI32.DLL,AW,5, initializes an EXPLICIT_ACCESS                        CertFindRDNAttr,CRYPT32.DLL,NM,2, finds the first RDN attribute identified by its object
structure with data specified by the caller.                                                         identifier (OID) in a list of the Relative Distinguished Names (RDN).
BuildImpersonateExplicitAccessWithName,ADVAPI32.DLL,AW,6, is provided for future use.                CertFindSubjectInCTL,CRYPT32.DLL,NM,5, attempts to find the specified subject in a
BuildImpersonateTrustee,ADVAPI32.DLL,AW,2, is provided for future use.                               certificate trust list (CTL).
BuildSecurityDescriptor,ADVAPI32.DLL,AW,9, allocates and initializes a new security                  CertFreeCertificateContext,CRYPT32.DLL,NM,1,Frees a certificate context by decrementing its
descriptor.                                                                                          reference count. When the reference count goes to zero, CertFreeCertificateContext frees the
BuildTrusteeWithName,ADVAPI32.DLL,AW,2, initializes a TRUSTEE structure.                             memory occupied by a certificate context.
BuildTrusteeWithSid,ADVAPI32.DLL,AW,2, initializes a TRUSTEE structure.                              CertFreeCRLContext,CRYPT32.DLL,NM,1, frees a certificate revocation list (CRL) context by
CallMsgFilter,USER32.DLL,AW,2 passes the specified message and hookcode to the hook                  decrementing its reference count. When the reference count goes to zero, CertFreeCRLContext
procedures associated with the WH_SYSMSGFILTER andWH_MSGFILTER hooks.                                frees the memory occupied by a CRL context.
CallNamedPipe,KERNEL32.DLL,AW,7 connects to a message-type pipe (and waits if an                     CertFreeCTLContext,CRYPT32.DLL,NM,1, frees a certificate trust list (CTL) context by
instance of the pipe is not available), writes to and reads from the pipe, and then closes the       decrementing its reference count. When the reference count goes to zero, CertFreeCTLContext
pipe.                                                                                                frees the memory occupied by a CTL context.
CallNextHookEx,USER32.DLL,NM,4, passes the hook information to the next hook procedure               CertGetCertificateContextProperty,CRYPT32.DLL,NM,4, retrieves the information contained in
in the current hook chain.                                                                           an extended property of a certificate context.
CallWindowProc,USER32.DLL,AW,5, passes message information to the specified window                   CertGetCRLContextProperty,CRYPT32.DLL,NM,4, gets an extended property for the specified
procedure.                                                                                           certificate revocation list (CRL) context.
CancelDC,GDI32.DLL,NM,1, cancels any pending operation on the specified device context               CertGetCRLFromStore,CRYPT32.DLL,NM,4,Gets the first or next certificate revocation list
(DC).                                                                                                (CRL) context from the certificate store for the specified issuer.
CancelIo,KERNEL32.DLL,NM,1 cancels all pending input and output (I/O)operations that were            CertGetCTLContextProperty,CRYPT32.DLL,NM,4, retrieves an extended property of a
issued by the calling thread for the specifiedfile handle.                                           certificate trust list (CTL) context.
CancelNtmsLibraryRequest,NTMSAPI.DLL,NM,2, cancels outstanding RSM requests, such as                 CertGetEnhancedKeyUsage,CRYPT32.DLL,NM,4, returns information from the enhanced key
calls to the CleanNtmsDrive function. If the library is busy, RSM queues the cancellation and        usage (EKU) extension or the EKU extended property of a certificate. EKUs indicate valid uses
returns success.                                                                                     of the certificate.
CancelNtmsOperatorRequest,NTMSAPI.DLL,NM,2, cancels the specified RSM operator                       CertGetIntendedKeyUsage,CRYPT32.DLL,NM,4, acquires the intended key usage bytes from a
request.                                                                                             certificate. The intended key usage can be in either the szOID_KEY_USAGE (
CancelWaitableTimer,KERNEL32.DLL,NM,1, sets the specified ?waitable? timer to the inactive           CertGetIssuerCertificateFromStore,CRYPT32.DLL,NM,4,Retrieves the certificate context from
state.                                                                                               the certificate store for the first or next issuer of the specified subject certificate. The new
CascadeWindows,USER32.DLL,NM,5, cascades the specified windows or the child windows of               Certificate Chain Verification Functions are recommended instead of the use of this function.
the specified parent window.                                                                         CertGetSubjectCertificateFromStore,CRYPT32.DLL,NM,3,Returns from a certificate store a
CertAddCertificateContextToStore,CRYPT32.DLL,NM,4, adds a certificate context to the                 subject certificate context uniquely identified by its issuer and serial number.
certificate store.                                                                                   CertIsRDNAttrsInCertificateName,CRYPT32.DLL,NM,4, compares the attributes in the
CertAddCRLContextToStore,CRYPT32.DLL,NM,4, adds a certificate revocation list (CRL)                  certificate name with the specified CERT_RDN to determine whether all attributes are included
context to the certificate store.                                                                    there.
CertAddCTLContextToStore,CRYPT32.DLL,NM,4, adds a certificate trust list (CTL) context to a          CertNameToStr,CRYPT32.DLL,AW,5,Converts an encoded name in a CERT_NAME_BLOB
certificate store.                                                                                   structure to a null-terminated character string.
CertAddEncodedCertificateToStore,CRYPT32.DLL,NM,6, creates a certificate context from an             CertOIDToAlgId,CRYPT32.DLL,NM,1, converts the Abstract Syntax Notation One (ASN.1)
encoded certificate and adds it to the certificate store.                                            object identifier (OID) string to the CryptoAPI algorithm identifier (ALG_ID).
CertAddEncodedCRLToStore,CRYPT32.DLL,NM,6, creates a certificate revocation list (CRL)               CertOpenStore,CRYPT32.DLL,NM,5,Opens a certificate store using a specified store provider
context from an encoded CRL and adds it to the certificate store. The function makes a copy of       type.
the CRL context before adding it to the store.                                                       CertOpenSystemStore,CRYPT32.DLL,AW,2, is a simplified function used to open the most
CertAddEncodedCTLToStore,CRYPT32.DLL,NM,6, creates a certificate trust list (CTL) context            common system certificate store. To open certificate stores with more complex requirements,
from an encoded CTL and adds it to the certificate store. The function makes a copy of the CTL       such as file-based or memory-based stores, use CertOpenStore.
context before adding it to the store.                                                               CertRDNValueToStr,CRYPT32.DLL,AW,4, converts a name in a CERT_RDN_VALUE_BLOB
CertAddEnhancedKeyUsageIdentifier,CRYPT32.DLL,NM,2, adds a usage identifier object                   to a null-terminated character string.
identifier (OID) to the enhanced key usage (EKU) extended property of the certificate.               CertRemoveEnhancedKeyUsageIdentifier,CRYPT32.DLL,NM,2, removes a usage identifier
CertAddSerializedElementToStore,CRYPT32.DLL,NM,8,Adds a serialized certificate, certificate          object identifier (OID) from the enhanced key usage (EKU) extended property of the certificate.
revocation list (CRL), or certificate trust list (CTL) element to the store.                         CertSaveStore,CRYPT32.DLL,NM,6,Saves the certificate store to a file or to a memory BLOB.
CertAlgIdToOID,CRYPT32.DLL,NM,1,Converts a CryptoAPI algorithm identifier (ALG_ID) to an             CertSerializeCertificateStoreElement,CRYPT32.DLL,NM,4, serializes a certificate context's
Abstract Syntax Notation One (ASN.1) object identifier (OID) string.                                 encoded certificate and its encoded properties. The result can be persisted to storage so that
CertCloseStore,CRYPT32.DLL,NM,2, closes a certificate store handle and reduces the                   the certificate and properties can be retrieved at a later time.
reference count on the store. There needs to be a corresponding call to CertCloseStore for           CertSerializeCRLStoreElement,CRYPT32.DLL,NM,4, serializes an encoded certificate
each successful call to the CertOpenStore or CertDuplicateStore functions.                           revocation list (CRL) context and the encoded representation of its properties.
CertCompareCertificate,CRYPT32.DLL,NM,3, compares two certificates to determine whether              CertSerializeCTLStoreElement,CRYPT32.DLL,NM,4, serializes an encoded certificate trust list
they are identical.                                                                                  (CTL) context and the encoded representation of its properties. The result can be persisted to
CertCompareCertificateName,CRYPT32.DLL,NM,3, compares two certificate                                storage so that the CTL and properties can be retrieved later.
CERT_NAME_BLOB structures to determine whether they are identical. The                               CertSetCertificateContextProperty,CRYPT32.DLL,NM,4, sets an extended property for a
CERT_NAME_BLOB structures are used for the subject and the issuer of certificates.                   specified certificate context.
CertCompareIntegerBlob,CRYPT32.DLL,NM,2, compares two integer BLOBs to determine                     CertSetCRLContextProperty,CRYPT32.DLL,NM,4, sets an extended property for the specified
whether they represent equal numeric values.                                                         certificate revocation list (CRL) context.
CertComparePublicKeyInfo,CRYPT32.DLL,NM,3, compares two encoded public keys to                       CertSetCTLContextProperty,CRYPT32.DLL,NM,4, sets an extended property for the specified
determine whether they are identical.                                                                certificate trust list (CTL) context.
CertCreateCertificateContext,CRYPT32.DLL,NM,3, creates a certificate context from an                 CertSetEnhancedKeyUsage,CRYPT32.DLL,NM,2, sets the enhanced key usage (EKU)
encoded certificate. The created context is not persisted to a certificate store. The function       property for the certificate.
makes a copy of the encoded certificate within the created context.                                  CertStrToName,CRYPT32.DLL,AW,7,Converts a null-terminated X.500 string to an encoded
CertCreateCRLContext,CRYPT32.DLL,NM,3, creates a certificate revocation list (CRL) context           certificate name.
from an encoded CRL. The created context is not persisted to a certificate store. It makes a         CertVerifyCRLRevocation,CRYPT32.DLL,NM,4, check a CRL to determine whether a subject's
copy of the encoded CRL within the created context.                                                  certificate has or has not been revoked. The new Certificate Chain Verification Functions are
CertCreateCTLContext,CRYPT32.DLL,NM,3, creates a certificate trust list (CTL) context from           recommended instead of the use of this function.
an encoded CTL. The created context is not persisted to a certificate store. The function makes      CertVerifyCRLTimeValidity,CRYPT32.DLL,NM,2, verifies the time validity of a CRL.
a copy of the encoded CTL within the created context.                                                CertVerifyCTLUsage,CRYPT32.DLL,NM,7, verifies that a subject is trusted for a specified
CertDeleteCertificateFromStore,CRYPT32.DLL,NM,1, deletes the specified certificate context           usage by finding a signed and time-valid CTL with the usage identifiers that contain the subject.
from the certificate store.                                                                          CertVerifyRevocation,CRYPT32.DLL,NM,7,Checks the revocation status of the certificates
CertDeleteCRLFromStore,CRYPT32.DLL,NM,1, deletes the specified certificate revocation list           contained in the rgpvContext array. If a certificate in the list is found to be revoked, no further
(CRL) context from the certificate store.                                                            checking is done.
CertDeleteCTLFromStore,CRYPT32.DLL,NM,1, deletes the specified certificate trust list (CTL)          CertVerifySubjectCertificateContext,CRYPT32.DLL,NM,3, performs the enabled verification
context from a certificate store.                                                                    checks on a certificate by checking the validity of the certificate's issuer. The new Certificate
CertDuplicateCertificateContext,CRYPT32.DLL,NM,1,Duplicates a certificate context by                 Chain Verification Functions are recommended instead this function.
incrementing its reference count.                                                                    CertVerifyTimeValidity,CRYPT32.DLL,NM,2, verifies the time validity of a certificate.
CertDuplicateCRLContext,CRYPT32.DLL,NM,1, duplicates a certificate revocation list (CRL)             CertVerifyValidityNesting,CRYPT32.DLL,NM,2, verifies that a subject certificate's time validity
context by incrementing its reference count.                                                         nests correctly within its issuer's time validity.
CertDuplicateCTLContext,CRYPT32.DLL,NM,1, duplicates a certificate trust list (CTL) context          ChangeClipboardChain,USER32.DLL,NM,2, removes a specified window from the chain of
by incrementing its reference count.                                                                 clipboard viewers.
CertDuplicateStore,CRYPT32.DLL,NM,1,Duplicates a store handle by incrementing the store's            ChangeDisplaySettings,USER32.DLL,AW,2, changes the display settings to the specified
reference count.                                                                                     graphics mode.
CertEnumCertificateContextProperties,CRYPT32.DLL,NM,2, retrieves the first or next extended          ChangeIdleRoutine,MAPI32.DLL,NM,7, changes some or all of the characteristics of a FNIDLE
property associated with a certificate context.                                                      - based idle routine.
CertEnumCertificatesInStore,CRYPT32.DLL,NM,2,Retrieves the first or next certificate in a            ChangeNtmsMediaType,NTMSAPI.DLL,NM,3, moves the specified PMID to the specified target
certificate store. Used in a loop, this function can retrieve in sequence all certificates in a      media pool and sets the PMID's media type identifier to the media type of the target media pool.
certificate store.                                                                                   ChangeServiceConfig,ADVAPI32.DLL,AW,11, changes the configuration parameters of a
CertEnumCRLContextProperties,CRYPT32.DLL,NM,2, retrieves the first or next extended                  service.
property associated with a certificate revocation list (CRL) context.                                CharLower,USER32.DLL,AW,1, converts a character string or a single character to lowercase.
CertEnumCTLContextProperties,CRYPT32.DLL,NM,2, retrieves the first or next extended                  CharLowerBuff,USER32.DLL,AW,2, converts uppercase characters in a buffer to lowercase
property associated with a certificate trust list (CTL) context. Used in a loop, this function can   characters.
retrieve in sequence all extended properties associated with a CTL context.                          CharNext,USER32.DLL,AW,1 returns a pointer to the next character in a string.
CertEnumCTLsInStore,CRYPT32.DLL,NM,2, retrieves the first or next certificate trust list (CTL)       CharNextEx,USER32.DLL,AW,3 The CharNextExA function retrieves the pointer to the next
context in a certificate store. Used in a loop, this function can retrieve in sequence all CTL       character in a string.
contexts in a certificate store.                                                                     CharPrev,USER32.DLL,AW,2, returns a pointer to the preceding character in a string.
CertFindAttribute,CRYPT32.DLL,NM,3, finds the first attribute in the CRYPT_ATTRIBUTE                 CharPrevEx,USER32.DLL,AW,4 retrieves the pointer to the preceding character in a string.
array, as identified by its object identifier (OID).                                                 CharToOem,USER32.DLL,AW,2, translates a string into the OEM-defined character set.
CertFindCertificateInStore,CRYPT32.DLL,NM,6,Finds the first or next certificate context in a         CharToOemBuff,USER32.DLL,AW,3, translates a specified number of characters in a string
certificate store that matches a search criteria established by the dwFindType and its               into the OEM-defined character set.
associated pvFindPara.                                                                               CharUpper,USER32.DLL,AW,1, converts a character string or a single character to uppercase.
CertFindCTLInStore,CRYPT32.DLL,NM,6, finds the first or next certificate trust list (CTL)            CharUpperBuff,USER32.DLL,AW,2, converts lowercase characters in a buffer to uppercase
context that matches search criteria established by the dwFindType and its associated                characters.
pvFindPara.
                                                                                           123
CheckBitmapBits,MSCMS.DLL,NM,9, checks whether the pixels in a specified bitmap lie within       CoGetInterfaceAndReleaseStream,OLE32.DLL,NM,3,This function unmarshals a buffer
the output gamut of a specified transform.                                                       containing an interface pointer and releases the stream when an interface pointer has been
CheckColors,MSCMS.DLL,NM,5, determines whether the colors in an array lie within the output      marshaled from another thread to the calling thread.
gamut of a specified transform.                                                                  CoGetMalloc,OLE32.DLL,NM,2,4.2 CoGetMalloc This function retrieves a pointer to the
CheckDlgButton,USER32.DLL,NM,3, changes the check state of a button control.                     default OLE task memory allocator (which supports the system implementation of the IMalloc
CheckMenuItem,USER32.DLL,NM,3, sets the state of the specified menu item's check mark            CoGetMarshalSizeMax,OLE32.DLL,NM,6,4.2 CoGetMarshalSizeMax This function returns
attribute to either checked or unchecked.                                                        an upper bound on the number of bytes needed to marshal the specified interface pointer to the
CheckMenuRadioItem,USER32.DLL,NM,5, checks a specified menu item and makes it a radio            CoGetObject,OLE32.DLL,NM,4, Converts a display name into a moniker that identifies the
item.                                                                                            object named, and then binds to the object identified by the moniker.
CheckRadioButton,USER32.DLL,NM,4 adds a check mark to (checks) aspecified radio button           CoGetPSClsid,OLE32.DLL,NM,2,This function returns the CLSID of the DLL that implements
in a group and removes a check mark from(clears) all other radio buttons in the group.           the proxy and stub for the specified interface.
CheckSumMappedFile,IMAGEHLP.DLL,NM,5, computes the checksum of the specified image               CoGetStandardMarshal,OLE32.DLL,NM,6,4.2 CoGetStandardMarshal This function creates
file.                                                                                            a default, or standard, marshaling object in either the client process or the server process,
ChildWindowFromPoint,USER32.DLL,NM,3, determines which, if any, of the child windows             CoGetState,OLE32.DLL,NM,1, This function is not yet supported.
belonging to a parent window contains the specified point.                                       CoGetTIDFromIPID,OLE32.DLL,NM,1, This function is not yet supported.
ChildWindowFromPointEx,USER32.DLL,NM,4 determines which, if any, of the child windows            CoGetTreatAsClass,OLE32.DLL,NM,2,4.2 CoGetTreatAsClass This function returns the
belonging to the specified parent window contains the specified point.                           CLSID of an object that can emulate the specified object. HRESULT CoGetTreatAsClass(
ChooseColor,COMDLG32.DLL,AW,1, creates a Color common dialog box that enables the user           REFCLSID
to select a color.                                                                               CoImpersonateClient,OLE32.DLL,NM,0,Allows the server to impersonate the client of the
ChooseFont,COMDLG32.DLL,AW,1, creates a Font common dialog box that enables the user             current call for the duration of the call.
to choose attributes for a logical font.                                                         CoInitialize,OLE32.DLL,NM,1 Initializes the COM library on the current thread and identifies the
ChoosePixelFormat,GDI32.DLL,NM,2 compares the generic pixel formats supported by                 concurrency model as single-thread apartment
Windows NT and any device pixel formats supported by special hardware accelerators with the      CoInitializeEx,OLE32.DLL,NM,2,Initializes the COM library for use by the calling thread, sets
pixel format you described, and returns the best match.                                          the thread's concurrency model, and creates a new apartment for the thread if one is required.
Chord,GDI32.DLL,NM,9, draws a chord (a region bounded by the intersection of an ellipse and      CoInitializeSecurity,OLE32.DLL,NM,9,Registers security and sets the default security values for
a line segment, called a ?secant?).                                                              the process. This function is called exactly once per process, either explicitly or implicitly. It can
CleanNtmsDrive,NTMSAPI.DLL,NM,2, queues a cleaning request for the specified drive for           be called by the client, server, or both.
cleaning.                                                                                        CoIsHandlerConnected,OLE32.DLL,NM,1, This function determines whether a remote object is
ClearCommBreak,KERNEL32.DLL,NM,1 restores character transmission for aspecified                  connected to the corresponding in-process object.
communications device and places the transmission line ina nonbreak state.                       CoIsOle1Class,OLE32.DLL,NM,1,This function determines if a given CLSID represents an OLE
ClearCommError,KERNEL32.DLL,NM,3 retrieves information about acommunications error and           1 object.
reports the current status of acommunications device.                                            CoLoadLibrary,OLE32.DLL,NM,2,Loads a specific DLL into the caller's process. CoLoadLibrary
ClearEventLog,ADVAPI32.DLL,AW,2, clears the specified event log, and optionally saves the        is equivalent to LoadLibraryEx. CoLoadLibrary does not do anything about the lifetime of the
current copy of the logfile to a backup file.                                                    library.
ClientToScreen,USER32.DLL,NM,2, replaces the client coordinates in the POINT structure with      CoLockObjectExternal,OLE32.DLL,NM,3,4.2 CoLockObjectExternal This function is called
the screen coordinates.                                                                          either to lock an object to ensure that it stays in memory, or to release such a lock. Call
ClipCursor,USER32.DLL,NM,1, confines the cursor to a rectangular area on the screen.             CoMarshalHresult,OLE32.DLL,NM,2,This function marshals an HRESULT to the specified
CloseClipboard,USER32.DLL,NM,0, closes the clipboard.                                            stream, from which it can be unmarshaled using the CoUnmarshalHresult function.
CloseColorProfile,MSCMS.DLL,NM,1,This CloseColorProfile closes an open profile handle.           CoMarshalInterface,OLE32.DLL,NM,6, This function writes into a stream the data required to
CloseDesktop,USER32.DLL,NM,1, closes an open handle to a desktop object.                         initialize a proxy object in some client process. The COM library in the client process calls the
CloseEnhMetaFile,GDI32.DLL,NM,1 closes an enhanced-metafile devicecontext and returns a          CoUnmarshalInterface function to extract the data and initialize the proxy.
handle that identifies an enhanced-formatmetafile.                                               CoMarshalInterThreadInterfaceInStream,OLE32.DLL,NM,3,Marshals an interface pointer from
CloseEventLog,ADVAPI32.DLL,NM,1, closes the specified event log.                                 one thread to another thread in the same process.
CloseFigure,GDI32.DLL,NM,1, closes an open figure in a path.                                     CombineRgn,GDI32.DLL,NM,4 combines two regions and stores the result in a third region.
CloseHandle,KERNEL32.DLL,NM,1, closes an open object handle.                                     CombineTransform,GDI32.DLL,NM,3, concatenates two world-space to page- space
CloseIMsgSession,MAPI32.DLL,NM,1, closes a message session and all the messages                  transformations.
created within that session.                                                                     CommConfigDialog,KERNEL32.DLL,AW,3, displays a driver-supplied configuration dialog box.
CloseMetaFile,GDI32.DLL,NM,1, closes a metafile device context and returns a handle that         CommDlgExtendedError,COMDLG32.DLL,NM,0, can return general error codes for any of the
identifies a Windows-format metafile.                                                            common dialog box functions.
CloseNtmsNotification,NTMSAPI.DLL,NM,1, closes the specified open notification channel.          CommitUrlCacheEntry,WININET.DLL,AW,11,Stores data in the specified file in the Internet
CloseNtmsSession,NTMSAPI.DLL,NM,1, closes the specified RSM session.                             cache and associates it with the specified URL.
ClosePrinter,WINMM.DLL,NM,1, closes the specified printer object.                                CompareFileTime,KERNEL32.DLL,NM,2, compares two 64-bit file times.
CloseServiceHandle,ADVAPI32.DLL,NM,1 closes the handles created with OpenSCManager,              CompareString,KERNEL32.DLL,AW,6 compares two character strings, usingthe locale
OpenService or CreateService                                                                     specified by the given identifier as the basis for thecomparison.
closesocket,WS2_32.DLL,NM,1, closes a socket.                                                    CompleteAuthToken,SECUR32.DLL,NM,2, completes an authentication token.
closesocket,WSOCK32.DLL,NM,1, closes a socket.                                                   ConfigurePort,WINMM.DLL,AW,3, displays the port-configuration dialog box for a port on the
CloseWindow,USER32.DLL,NM,1, minimizes (but does not destroy) the specified window.              specified server.
CloseWindowStation,USER32.DLL,NM,1, closes an open window station handle.                        connect,WS2_32.DLL,NM,3, establishes a connection to a specifed socket.
CLSIDFromProgID,OLE32.DLL,NM,2,Looks up a CLSID in the registry, given a ProgID.                 connect,WSOCK32.DLL,NM,3, is used to create a connection to the to the specified
CLSIDFromString,OLE32.DLL,NM,2,Converts a string generated by the StringFromCLSID                destination.
function back into the original CLSID.                                                           ConnectNamedPipe,KERNEL32.DLL,NM,2 enables a named pipe server process to wait for a
ClusWorkerCheckTerminate,RESUTILS.DLL,NM,1,The ClusWorkerCheckTerminate utility                  client process to connect to an instance of a named pipe.
function determines whether a worker thread should exit as soon as possible.                     ConnectToPrinterDlg,WINMM.DLL,NM,2, displays a dialog box that lets users browse and
ClusWorkerCreate,RESUTILS.DLL,NM,3,The ClusWorkerCreate utility function creates a               connect to printers on a network.
worker thread.                                                                                   ContinueDebugEvent,KERNEL32.DLL,NM,3 enables a debugger to continue a thread that
ClusWorkerTerminate,RESUTILS.DLL,NM,1,The ClusWorkerTerminate utility function                   previously reported a debugging event.
terminates a worker thread.                                                                      ControlService,ADVAPI32.DLL,NM,3, sends a control code to a Win32-based service.
CoAddRefServerProcess,OLE32.DLL,NM,0,Increments a global per-process reference count.            ConvertDefaultLocale,KERNEL32.DLL,NM,1, converts a special default locale value to an
CoBuildVersion,OLE32.DLL,NM,0,4.2 CoBuildVersion This function is obsolete.                      actual locale identifier.
Requirements OS Versions: Windows CE 3.0 and later. Header: Objbase.h. Link Library:             ConvertThreadToFiber,KERNEL32.DLL,NM,1 converts the current thread into a fiber.
Ole32.lib.                                                                                       CopyAcceleratorTable,USER32.DLL,AW,3, copies the specified accelerator table.
CoCopyProxy,OLE32.DLL,NM,2,This function makes a private copy of the specified proxy.            CopyEnhMetaFile,GDI32.DLL,AW,2, copies the contents of an enhanced- format metafile to a
CoCreateFreeThreadedMarshaler,OLE32.DLL,NM,2,Creates an aggregatable object capable of           specified file.
context-dependent marshaling.                                                                    CopyFile,KERNEL32.DLL,AW,3 copies an existing file to a new file.
CoCreateGuid,OLE32.DLL,NM,1,Creates a GUID, a unique 128-bit integer used for CLSIDs             CopyFileEx,KERNEL32.DLL,AW,6, copies an existing file to a new file.
and interface identifiers.                                                                       CopyIcon,USER32.DLL,NM,1, copies the specified icon from another module to the current
CoCreateInstance,OLE32.DLL,NM,5,ExCreates an instance of a specific class on a specific          module.
machine.                                                                                         CopyImage,USER32.DLL,NM,5 creates a new image (icon, cursor, orbitmap) and copies the
CoCreateInstanceEx,OLE32.DLL,NM,6,Creates an instance of a specific class on a specific          attributes of the specified image to the newone.
machine.                                                                                         CopyLZFile,LZ32.DLL,NM,2, is obsolete.
CoDisconnectObject,OLE32.DLL,NM,2,This function disconnects all remote process                   CopyMetaFile,GDI32.DLL,AW,2, copies the content of a Windows-format metafile to the
connections being maintained on behalf of all the interface pointers that point to a specified   specified file.
object. Only the process that actually manages the object should call CoDisconnectObject.        CopyRect,USER32.DLL,NM,2, copies the coordinates of one rectangle to another.
CoDosDateTimeToFileTime,OLE32.DLL,NM,3,Converts the MS-DOS representation of the                 CopySid,ADVAPI32.DLL,NM,3, copies a security identifier (SID) to a buffer.
time and date to a FILETIME structure, which Win32 uses to determine the date and time.          CoQueryAuthenticationServices,OLE32.DLL,NM,2,4.2 CoQueryAuthenticationServices This
CoFileTimeNow,OLE32.DLL,NM,1, Pointer to return the FILETIME structure.                          function retrieves a list of the authentication services registered when the process called .
CoFileTimeToDosDateTime,OLE32.DLL,NM,3,Converts a FILETIME into MS-DOS date and                  HRESULT
time values.                                                                                     CoQueryClientBlanket,OLE32.DLL,NM,7, This function is called by the server to find out about
CoFreeAllLibraries,OLE32.DLL,NM,0, This function frees all the DLLs that have been loaded        the client that invoked the method executing on the current thread.
with the CoLoadLibrary function (called internally by CoGetClassObject), regardless of whether   CoQueryProxyBlanket,OLE32.DLL,NM,8,4.2 CoQueryProxyBlanket This function retrieves
they are currently in use.                                                                       the authentication information the client uses to make calls on the specified proxy. HRESULT
CoFreeLibrary,OLE32.DLL,NM,1,This function frees a library that, when loaded, was specified      CoQueryReleaseObject,OLE32.DLL,NM,1, This function is not yet supported.
to be freed explicitly.                                                                          CoRegisterChannelHook,OLE32.DLL,NM,2, This function is not yet supported.
CoFreeUnusedLibraries,OLE32.DLL,NM,0,Unloads any DLLs that are no longer in use and              CoRegisterClassObject,OLE32.DLL,NM,5,Registers an EXE class object with OLE so other
that, when loaded, were specified to be freed automatically.                                     applications can connect to it. EXE object applications should call CoRegisterClassObject on
CoGetCallContext,OLE32.DLL,NM,2, Interface identifier (IID) of the call context that is being    startup.
requested.                                                                                       CoRegisterMallocSpy,OLE32.DLL,NM,1, This function registers an implementation of the
CoGetCallerTID,OLE32.DLL,NM,1,Returns a GUID identifying the callers thread.                     IMallocSpy interface in OLE, thereafter requiring OLE to call its wrapper methods around every
CoGetClassObject,OLE32.DLL,NM,5,FromURL Returns a factory object for a given CLSID.              call to the corresponding IMalloc method.
CoGetClassObjectFromURL,URLMON.DLL,NM,10, Returns a factory object for a given CLSID.            CoRegisterMessageFilter,OLE32.DLL,NM,2,Registers with OLE the instance of an
CoGetCurrentLogicalThreadId,OLE32.DLL,NM,1, This function is not yet supported.                  IMessageFilter interface, which is to be used for handling concurrency issues on the current
CoGetCurrentProcess,OLE32.DLL,NM,0, This function returns a value that is unique to the          thread. Only one message filter can be registered for each thread.
current thread. CoGetCurrentProcess can be used to avoid thread ID reuse problems.               CoRegisterPSClsid,OLE32.DLL,NM,2,This function enables a downloaded DLL to register its
DWORD CoGetCurrentProcess(void); Return Value Unique DWORD value identifying the                 custom interfaces within its running process so that the marshaling code will be able to marshal
current thread.                                                                                  those interfaces.
CoGetInstanceFromFile,OLE32.DLL,NM,8,This function creates a new object and initializes it       CoReleaseMarshalData,OLE32.DLL,NM,1,This function destroys a previously marshaled data
from a file using IPersistFile::Load.                                                            packet.
                                                                                           124
CoReleaseServerProcess,OLE32.DLL,NM,0,Decrements the global per-process reference                CreateFontIndirect,GDI32.DLL,AW,1, creates a logical font that has the characteristics
count.                                                                                           specified in the specified structure.
CoResumeClassObjects,OLE32.DLL,NM,0,4.2 CoResumeClassObjects This function is                    CreateFormatEnumerator,URLMON.DLL,NM,3, Creates an object that implements
called by a server that can register multiple class objects to inform the OLE SCM about all      IEnumFORMATETC over a static array of FORMATETC structures.
registered                                                                                       CreateGenericComposite,OLE32.DLL,NM,3,4.2 CreateGenericComposite This function
CoRevertToSelf,OLE32.DLL,NM,0,This function restores the authentication information on a         performs a generic composition of two monikers and supplies a pointer to the resulting
thread of execution.                                                                             composite moniker.
CoRevokeClassObject,OLE32.DLL,NM,1, This function informs OLE that a class object,               CreateHalftonePalette,GDI32.DLL,NM,1 creates a halftone palette for the specified device
previously registered with the CoRegisterClassObject function, is no longer available for use.   context.
CoRevokeMallocSpy,OLE32.DLL,NM,0,This function revokes a registered IMallocSpy object.           CreateHatchBrush,GDI32.DLL,NM,2, creates a logical brush that has the specified hatch
CoSetProxyBlanket,OLE32.DLL,NM,8,Sets the authentication information that will be used to        pattern and color.
make calls on the specified proxy. This is a helper function for IClientSecurity::SetBlanket.    CreateIC,GDI32.DLL,AW,4 creates an information context for the specified device.
CoSetState,OLE32.DLL,NM,1, This function is not yet supported.                                   CreateIcon,USER32.DLL,NM,7, creates an icon that has the specified size, colors, and bit
CoSuspendClassObjects,OLE32.DLL,NM,0,4.2 CoSuspendClassObjects This function                     patterns.
prevents any new activation requests from the SCM on all class objects registered within the     CreateIconFromResource,USER32.DLL,NM,4, creates an icon or cursor from resource bits
process.                                                                                         describing the icon.
CoSwitchCallContext,OLE32.DLL,NM,2, This function switches the call context object used by       CreateIconFromResourceEx,USER32.DLL,NM,7, creates an icon or cursor from resource bits
CoGetCallContext.                                                                                describing the icon.
CoTaskMemAlloc,OLE32.DLL,NM,1,Allocates a block of task memory in the same way that              CreateIconIndirect,USER32.DLL,NM,1, creates an icon or cursor from an ICONINFO structure.
IMalloc::Alloc does.                                                                             CreateILockBytesOnHGlobal,OLE32.DLL,NM,3,Creates a byte array object, using global
CoTaskMemFree,OLE32.DLL,NM,1,Frees a block of task memory previously allocated through           memory as the physical device, which is intended to be the compound file foundation.
a call to the CoTaskMemAlloc or CoTaskMemRealloc function.                                       CreateIoCompletionPort,KERNEL32.DLL,NM,4 can associate an instance of an opened file
CoTaskMemRealloc,OLE32.DLL,NM,2,Changes the size of a previously allocated block of task         with a newly created or an existing input/output completion port; or it can create an input/output
memory.                                                                                          completion port without associating it with a file.
CoTreatAsClass,OLE32.DLL,NM,2, This function establishes or removes an emulation, in             CreateIProp,MAPI32.DLL,NM,6, creates a property data object, that is, an IPropData object.
which objects of one class are treated as objects of a different class.                          CreateItemMoniker,OLE32.DLL,NM,3,This function creates an item moniker that identifies an
CoUninitialize,OLE32.DLL,NM,0,Closes the COM library on the current thread, unloads all          object within a containing object (typically a compound document).
DLLs loaded by the thread, frees any other resources that the thread maintains, and forces all   CreateMailslot,KERNEL32.DLL,AW,4 creates a mailslot with the specifiedname and returns a
RPC connections on the thread to close.                                                          handle that a mailslot server can use to performoperations on the mailslot.
CoUnmarshalHresult,OLE32.DLL,NM,2, Pointer to the stream from which the HRESULT is to            CreateMappedBitmap,COMCTL32.DLL,NM,5, creates a bitmap for use in a toolbar.
be unmarshaled.                                                                                  CreateMDIWindow,USER32.DLL,AW,10, creates a multiple document interface (MDI) child
CoUnmarshalInterface,OLE32.DLL,NM,3,4.2 CoUnmarshalInterface This function initializes a         window.
newly created proxy using data written into the stream by a previous call to the function, and   CreateMenu,USER32.DLL,NM,0, creates a menu.
CountClipboardFormats,USER32.DLL,NM,0 retrieves the number of different data formats             CreateMetaFile,GDI32.DLL,AW,1, creates a device context for a Windows-meta file.
currently on the clipboard.                                                                      CreateMultiProfileTransform,MSCMS.DLL,NM,6, accepts an array of profiles or a single device
CPlApplet,ODBCCP32.DLL,NM,4, is a library-defined callback function that serves as the entry     link profile and creates a color transform that
point for a Control Panel application.                                                           CreateMutex,KERNEL32.DLL,AW,3, creates a named or unnamed mutex object.
CreateAcceleratorTable,USER32.DLL,AW,2, creates an accelerator table.                            CreateNamedPipe,KERNEL32.DLL,AW,8 creates an instance of a named pipe and returns a
CreateAntiMoniker,OLE32.DLL,NM,1, Address of IMoniker* pointer variable that receives the        handle for subsequent pipe operations.
interface pointer to the new anti-moniker.                                                       CreateNtmsMedia,NTMSAPI.DLL,AW,4,The CreateNtmsMediaPool function creates a new
CreateAsyncBindCtx,URLMON.DLL,NM,4, Creates an asynchronous bind context for use with            application media pool.
asynchronous monikers.                                                                           CreateNtmsMediaPool,NTMSAPI.DLL,AW,6, creates a new application media pool.
CreateBindCtx,OLE32.DLL,NM,2,This function supplies a pointer to an implementation of            CreateOleAdviseHolder,OLE32.DLL,NM,1, instantiates an advise holder object for managing
IBindCtx, an object that stores information about a particular moniker-binding operation.        compound document notifications. It passes out a pointer to
CreateBitmap,GDI32.DLL,NM,5, creates a bitmap with the specified width, height, and color        CreatePalette,GDI32.DLL,NM,1, creates a logical color palette.
format (color planes and bits per pixel).                                                        CreatePatternBrush,GDI32.DLL,NM,1, creates a logical brush with the specified bitmap pattern.
CreateBitmapIndirect,GDI32.DLL,NM,1 creates a bitmap with thespecified width, height, and        CreatePen,GDI32.DLL,NM,3, creates a logical pen that has the specified style, width, and color.
color format (color planes and bitsper pixel).                                                   CreatePenIndirect,GDI32.DLL,NM,1, creates a logical cosmetic pen that has the style, width,
CreateBrushIndirect,GDI32.DLL,NM,1, creates a logical brush that has the specified style,        and color specified in a structure.
color, and pattern.                                                                              CreatePipe,KERNEL32.DLL,NM,4, creates an anonymous pipe, and returns handles to the
CreateCaret,USER32.DLL,NM,4, creates a new shape for the system caret and assigns                read and write ends of the pipe.
ownership of the caret to the specified window.                                                  CreatePointerMoniker,OLE32.DLL,NM,2, This function creates a pointer moniker based on a
CreateClassMoniker,OLE32.DLL,NM,2,Creates a class moniker that refers to the given class.        pointer to an object.
CreateColorTransform,MSCMS.DLL,AW,4, creates a color transform that applications can use         CreatePolygonRgn,GDI32.DLL,NM,3, creates a polygonal region.
to perform color management.                                                                     CreatePolyPolygonRgn,GDI32.DLL,NM,4, creates a region consisting of a series of polygons.
CreateCompatibleBitmap,GDI32.DLL,NM,3 creates a bitmap compatiblewith the device that is         CreatePopupMenu,USER32.DLL,NM,0, creates a drop-down menu, submenu, or shortcut
associated with the specified devicecontext.                                                     menu.
CreateCompatibleDC,GDI32.DLL,NM,1, can only be used with devices that support raster             CreatePrivateObjectSecurity,ADVAPI32.DLL,NM,6 allocates and initializesa self-relative
operations.                                                                                      security descriptor for a new protected server?sis being created.
CreateConsoleScreenBuffer,KERNEL32.DLL,NM,5, creates a console screen buffer and                 CreateProcess,KERNEL32.DLL,AW,10, creates a new process and its primary thread.
returns a handle of it.                                                                          CreateProcessAsUser,ADVAPI32.DLL,AW,11, creates a new process and its primary thread.
CreateCursor,USER32.DLL,NM,7 creates a cursor having the specified size, bit patterns, and       CreateProfileFromLogColorSpace,MSCMS.DLL,AW,2, converts a logical color space to a
hot spot.                                                                                        CreatePropertySheetPage,COMCTL32.DLL,AW,1, creates a new page for a property sheet.
CreateDataAdviseHolder,OLE32.DLL,NM,1,Supplies a pointer to the OLE implementation of            CreateRectRgn,GDI32.DLL,NM,4 creates a rectangular region.
IDataAdviseHolder on the data advise holder object.                                              CreateRectRgnIndirect,GDI32.DLL,NM,1, creates a rectangular region.
CreateDataCache,OLE32.DLL,NM,4,Supplies a pointer to a new instance of an OLE-provided           CreateRemoteThread,KERNEL32.DLL,NM,7, creates a thread that runs in the address space
implementation of a data cache.                                                                  of another process.
CreateDC,GDI32.DLL,AW,4, creates a device context (DC) for a device by using the specified       CreateRoundRectRgn,GDI32.DLL,NM,6, creates a rectangular region with rounded corners.
name.                                                                                            CreateScalableFontResource,GDI32.DLL,AW,4, creates a font resource file for a scalable font.
CreateDesktop,USER32.DLL,AW,6, returns a handle that can be used to access the desktop.          CreateSemaphore,KERNEL32.DLL,AW,4, creates a named or unnamed semaphore object.
CreateDeviceLinkProfile,MSCMS.DLL,NM,4, creates a device link profile from a set of color        CreateService,ADVAPI32.DLL,AW,13, creates a service object and adds it to the specified
profiles, using the specified intents.                                                           service control manager database.
CreateDialogIndirectParam,USER32.DLL,AW,5, creates a modeless dialog box from a dialog           CreateSolidBrush,GDI32.DLL,NM,1, creates a logical brush that has the specified solid color.
box template in memory.                                                                          CreateStatusWindow,COMCTL32.DLL,AW,4, creates a status window, which is typically used
CreateDialogParam,USER32.DLL,AW,5, creates a modeless dialog box from a dialog box               to display the status of an application.
template resource.                                                                               CreateStdDispatch,OLEAUT32.DLL,NM,4,Creates a standard implementation of the IDispatch
CreateDIBitmap,GDI32.DLL,NM,6 creates a device-dependent bitmap (DDB)from a device-              interface through a single function call. This simplifies exposing objects through Automation.
independent bitmap (DIB) and, optionally, sets thebitmap bits.                                   CreateStreamOnHGlobal,OLE32.DLL,NM,3,Creates a stream object stored in global memory.
CreateDIBPatternBrush,GDI32.DLL,NM,2 creates a logical brush that has the pattern specified      CreateTable,MAPI32.DLL,NM,9 creates structures and an object handle for a table data object
by the specified device-independent bitmap (DIB).                                                an ITableData object which can be used to create table contents.
CreateDIBPatternBrushPt,GDI32.DLL,NM,2 creates a logical brush that has the pattern              CreateTapePartition,KERNEL32.DLL,NM,4 reformats a tape.
specified by the device-independent bitmap (DIB).                                                CreateTextServices,RICHED20.DLL,NM,3,creates an instance of a text services object.
CreateDIBSection,GDI32.DLL,NM,6, creates a device-independent bitmap (DIB) that                  CreateThread,KERNEL32.DLL,NM,6, creates a thread to execute within the address space of
applications can write to directly.                                                              the calling process.
CreateDirectory,KERNEL32.DLL,AW,2, creates a new directory.                                      CreateToolbarEx,COMCTL32.DLL,NM,13, creates a toolbar window and adds the specified
CreateDirectoryEx,KERNEL32.DLL,AW,3 creates a new directory with a specified path that           buttons to the toolbar.
retains the attributes of a specified template directory.                                        CreateToolhelp32Snapshot,TOOLHELP.DLL,NM,2, takes a snapshot of the specified
CreateDiscardableBitmap,GDI32.DLL,NM,3, creates a discardable bitmap that is compatible          processes in the system, as well as the heaps, modules, and threads used by these processes.
with the specified device.                                                                       CreateTypeLib,OLEAUT32.DLL,NM,3, creates a type library in the current file format.
CreateDispTypeInfo,OLEAUT32.DLL,NM,3,Creates simplified type information for use in an           CreateTypeLib2,OLEAUT32.DLL,NM,3, creates a type library in the current file format.
implementation of IDispatch.                                                                     CreateUpDownControl,COMCTL32.DLL,NM,12, creates an up-down control.
CreateEllipticRgn,GDI32.DLL,NM,4, creates an elliptical region.                                  CreateUrlCacheEntry,WININET.DLL,AW,5,Creates a local file name for saving the cache entry
CreateEllipticRgnIndirect,GDI32.DLL,NM,1, creates an elliptical region.                          based on the specified URL and the file extension.
CreateEnhMetaFile,GDI32.DLL,AW,4, creates a device context for an enhanced-format                CreateUrlCacheGroup,WININET.DLL,NM,2,Generates cache group identifications.
metafile.                                                                                        CreateURLMoniker,URLMON.DLL,NM,3, Creates a URL moniker from either a full URL string
CreateEnvironmentBlock,USERENV.DLL,NM,3, retrieves the environment variables for the             or from a base context URL moniker and a partial URL string.
specified user. This block can then be passed to the CreateProcessAsUser function.               CreateUserProfile,USERENV.DLL,AW,5 creates a user profile with the specified account name
CreateErrorInfo,OLEAUT32.DLL,NM,1, This function creates an instance of a generic error          and preferred name.
object.                                                                                          CreateWaitableTimer,KERNEL32.DLL,AW,3, creates a ?waitable? timer object.
CreateEvent,KERNEL32.DLL,AW,4, creates a named or unnamed event object.                          CreateWindow,USER32.DLL,AW,1 creates an overlapped, pop-up, or childwindow
CreateFiber,KERNEL32.DLL,NM,3 allocates a fiber object, assigns it astack, and sets up           CreateWindowEx,USER32.DLL,AW,12 creates an overlapped, pop-up, or childwindow with an
execution to begin at the specified startaddress, typically the fiber function.                  extended style; otherwise, this function isidentical to the CreateWindow function.
CreateFile,KERNEL32.DLL,AW,7, creates or opens file                                              CreateWindowStation,USER32.DLL,AW,4, creates a window station object.
 CreateFileMapping,KERNEL32.DLL,AW,6, creates a named or unnamed file- mapping object            CryptAcquireContext,ADVAPI32.DLL,AW,5,used to acquire a handle to a particular key
for the specified file.                                                                          container within a particular CSP.
CreateFileMoniker,OLE32.DLL,NM,2,creates a file moniker based on the specified path.             CryptCreateHash,ADVAPI32.DLL,NM,5,used to initiate the hashing of a stream of data. It
CreateFont,GDI32.DLL,AW,14, creates a logical font that has specific characteristics.            returns to the caller a handle to a CSP hash object.
                                                                                             125
CryptDecodeMessage,CRYPT32.DLL,NM,13,Decodes, decrypts, and verifies a cryptographic               CryptRegisterDefaultOIDFunction,CRYPT32.DLL,NM,4,The CryptRegisterDefaultOIDFunction
message.                                                                                           registers a DLL containing the default function to be called for the specified encoding type and
CryptDecodeObject,CRYPT32.DLL,NM,7, decodes a structure of the type indicated by the               function name. Unlike CryptRegisterOIDFunction, the function name to be exported by the DLL
lpszStructType parameter. The use of CryptDecodeObjectEx is recommended as an API that             cannot be overridden.
performs the same function with significant performance improvements.                              CryptRegisterOIDFunction,CRYPT32.DLL,NM,5,Registers a DLL that contains the function to
CryptDecrypt,ADVAPI32.DLL,NM,6,The CryptDecryptAndVerifyMessageSignature function                  be called for the specified encoding type, function name, and object identifier (OID).
decrypts a message and verifies its signature.                                                     CryptReleaseContext,ADVAPI32.DLL,NM,2,is used to release a handle to a CSP and a key
CryptDecryptAndVerifyMessageSignature,CRYPT32.DLL,NM,9, decrypts a message and                     container.
verifies its signature.                                                                            CryptSetHashParam,ADVAPI32.DLL,NM,4,in theory, customizes the operations of a hash
CryptDecryptMessage,CRYPT32.DLL,NM,6, decodes and decrypts a message.                              object.
CryptDeriveKey,ADVAPI32.DLL,NM,5,generates cryptographic keys derived from base data.              CryptSetKeyParam,ADVAPI32.DLL,NM,4,customizes various aspects of a key?s operations.
CryptDestroyHash,ADVAPI32.DLL,NM,1,destroys the hash object referenced by the hHash                CryptSetOIDFunctionValue,CRYPT32.DLL,NM,7, sets a value for the specified encoding type,
parameter.                                                                                         function name, OID, and value name.
CryptDestroyKey,ADVAPI32.DLL,NM,1,releases the handle referenced by the hKey parameter.            CryptSetProvider,ADVAPI32.DLL,AW,2,is used to specify the current user default CSP.
CryptEncodeObject,CRYPT32.DLL,NM,5, encodes a structure of the type indicated by the               CryptSetProvParam,ADVAPI32.DLL,NM,4,customizes the operations of a CSP.
value of the lpszStructType parameter. The use of CryptEncodeObjectEx is recommended as            CryptSignAndEncodeCertificate,CRYPT32.DLL,NM,9,Security SDK content provides details
an API that performs the same function with significant performance improvements.                  about using authentication, authorization, cryptography, and related technologies in the
CryptEncrypt,ADVAPI32.DLL,NM,7,is used to encrypt data.                                            Microsoft Windows Server, Windows, and Windows NT platforms.
CryptEncryptMessage,CRYPT32.DLL,NM,7, encrypts and encodes a message.                              CryptSignAndEncryptMessage,CRYPT32.DLL,NM,8, creates a hash of the specified content,
CryptEnumOIDFunction,CRYPT32.DLL,NM,6, enumerates the registered object identifier (OID)           signs the hash, encrypts the content, hashes the encrypted contents and the signed hash, and
functions.                                                                                         then encodes both the encrypted content and the signed hash.
CryptExportKey,ADVAPI32.DLL,NM,6,used to export cryptographic keys out of a cryptographic          CryptSignCertificate,CRYPT32.DLL,NM,9, signs the
service provider in a secure manner.                                                               CryptSignHash,ADVAPI32.DLL,AW,6,is used to sign a piece of data.
CryptExportPublicKeyInfo,CRYPT32.DLL,NM,5, exports the public key information associated           CryptSignMessage,CRYPT32.DLL,NM,7, creates a hash of the specified content, signs the
with the corresponding private key of the provider. For an updated version of this function, see   hash, and then encodes both the original message content and the signed hash.
CryptExportPublicKeyInfoEx.                                                                        CryptUnregisterDefaultOIDFunction,CRYPT32.DLL,NM,3, removes the registration of a DLL
CryptExportPublicKeyInfoEx,CRYPT32.DLL,NM,8, exports the public key information                    containing the default function to be called for the specified encoding type and function name.
associated with the provider's corresponding private key.                                          CryptUnregisterOIDFunction,CRYPT32.DLL,NM,3, removes the registration of a DLL containing
CryptFormatObject,CRYPT32.DLL,NM,9, formats the encoded data and returns a Unicode                 the function to be called for the specified encoding type, function name, and OID.
string in the allocated buffer according to the certificate encoding type.                         CryptVerifyCertificateSignature,CRYPT32.DLL,NM,5,Verifies the signature of a certificate,
CryptFreeOIDFunctionAddress,CRYPT32.DLL,NM,2, releases a handle returned by                        certificate revocation list (CRL), or certificate request by using the public key in a
CryptGetOIDFunctionAddress or CryptGetDefaultOIDFunctionAddress by decrementing the                CERT_PUBLIC_KEY_INFO structure.
reference count on the function handle.                                                            CryptVerifyDetachedMessageHash,CRYPT32.DLL,NM,8, verifies a detached hash.
CryptGenKey,ADVAPI32.DLL,NM,4,generates random cryptographic keys for use with the CSP             CryptVerifyDetachedMessageSignature,CRYPT32.DLL,NM,8, verifies a signed message
module.                                                                                            containing a detached signature or signatures.
CryptGenRandom,ADVAPI32.DLL,NM,3,fills a buffer with random bytes.                                 CryptVerifyMessageHash,CRYPT32.DLL,NM,7, verifies the hash of specified content.
CryptGetDefaultOIDDllList,CRYPT32.DLL,NM,4, acquires the list of the names of DLL files that       CryptVerifyMessageSignature,CRYPT32.DLL,NM,7,Verifies a signed message's signature.
contain registered default object identifier (OID) functions for a specified function set and      CryptVerifySignature,ADVAPI32.DLL,AW,6,is used to verify a signature against a hash object.
encoding type.                                                                                     DAPIAllocBuffer,DAPI.DLL,NM,2, allocates or reallocates a block of memory.
CryptGetDefaultOIDFunctionAddress,CRYPT32.DLL,NM,6, loads the DLL that contains a                  DAPIEnd,DAPI.DLL,NM,1, closes a directory operation session.
default function address.                                                                          DAPIFreeMemory,DAPI.DLL,NM,1, releases or frees a block of memory.
CryptGetHashParam,ADVAPI32.DLL,NM,5,retrieves data that governs the operations of a hash           DAPIGetSiteInfo,DAPI.DLL,AW,3, retrieves the site information for a directory service agent.
object.                                                                                            DAPIRead,DAPI.DLL,AW,6, reads (exports) attributes from a directory object.
CryptGetKeyParam,ADVAPI32.DLL,NM,5,retrieves data that govern the operations of a key.             DAPIStart,DAPI.DLL,AW,2, initializes a directory operation session.
CryptGetMessageCertificates,CRYPT32.DLL,NM,5, returns the handle of an open certificate            DAPIUninitialize,DAPI.DLL,NM,1, terminates background processes.
store containing the message's certificates and CRLs. This function calls CertOpenStore using      DAPIWrite,DAPI.DLL,AW,7, writes (imports) information to a directory object.
provider type CERT_STORE_PROV_PKCS7 as its lpszStoreProvider parameter.                            DceErrorInqText,RPCRT4.DLL,AW,2, returns the message text for a status code.
CryptGetMessageSignerCount,CRYPT32.DLL,NM,3, returns the number of signers of a signed             DdeAbandonTransaction,USER32.DLL,NM,3 abandons the specifiedasynchronous transaction
message.                                                                                           and releases all resources associated withthe transaction.
CryptGetOIDFunctionAddress,CRYPT32.DLL,NM,6, searches the list of registered and installed         DdeAccessData,USER32.DLL,NM,2, provides access to the data in the specified dynamic data
functions for an encoding type and object identifier (OID) match.                                  exchange (DDE) object.
CryptGetOIDFunctionValue,CRYPT32.DLL,NM,7, queries a value associated with an OID.                 DdeAddData,USER32.DLL,NM,4, adds data to the specified dynamic data exchange (DDE)
CryptGetProvParam,ADVAPI32.DLL,NM,5,retrieves parameters that govern the operations of a           object.
CSP.                                                                                               DdeClientTransaction,USER32.DLL,NM,8, begins a data transaction between a client and a
CryptGetUserKey,ADVAPI32.DLL,NM,3,retrieves a handle to a permanent user key pair, such            server.
as the user?s signature key pair.                                                                  DdeCmpStringHandles,USER32.DLL,NM,2, compares the values of two string handles.
CryptHashCertificate,CRYPT32.DLL,NM,7, hashes the entire encoded content of a certificate          DdeConnect,USER32.DLL,NM,4 establishes a conversation with a server application that
including its signature.                                                                           supports the specified service name and topic name pair.
CryptHashData,ADVAPI32.DLL,NM,4,used to compute the cryptographic hash on a stream of              DdeCreateStringHandle,USER32.DLL,AW,3 creates a handle that identifies the string pointed
data.                                                                                              to by the psz parameter.
CryptHashMessage,CRYPT32.DLL,NM,9, creates a hash of the message.                                  DdeConnectList,USER32.DLL,NM,5 establishes a conversation with allserver applications that
CryptHashPublicKeyInfo,CRYPT32.DLL,NM,7, encodes the public key information in a                   support the specified service name andtopic name pair.
CERT_PUBLIC_KEY_INFO structure and computes the hash of the encoded bytes. The hash                DdeCreateDataHandle,USER32.DLL,NM,7 creates a dynamic data exchange(DDE) object and
created is used with key identifier functions.                                                     fills the object with data from the specifiedbuffer.
CryptHashSessionKey,ADVAPI32.DLL,NM,3,used to compute the cryptographic hash on a key              DdeDisconnect,USER32.DLL,NM,1 terminates a conversation started byeither the DdeConnect
object.                                                                                            or DdeConnectList function and invalidatesthe specified conversation handle.
CryptHashToBeSigned,CRYPT32.DLL,NM,6, computes the hash of the encoded content from a              DdeDisconnectList,USER32.DLL,NM,1, destroys the specified conversation list and terminates
signed and encoded certificate. The hash is performed on only the                                  all conversations associated with the list.
CryptImportKey,ADVAPI32.DLL,NM,6,is used to transfer a cryptographic key from a key blob to        DdeEnableCallback,USER32.DLL,NM,3 enables or disables transactions fora specific
the CSP.                                                                                           conversation or for all conversations currentlyestablished by the calling application.
CryptImportPublicKeyInfo,CRYPT32.DLL,NM,4, converts and imports the public key information         DdeFreeDataHandle,USER32.DLL,NM,1, frees a dynamic data exchange (DDE) object and
into the provider and returns a handle of the public key. CryptImportPublicKeyInfoEx provides a    deletes the data handle associated with the object.
revised version of this function.                                                                  DdeFreeStringHandle,USER32.DLL,NM,2, frees a string handle in the calling application.
CryptImportPublicKeyInfoEx,CRYPT32.DLL,NM,7, imports public key information into the               DdeGetData,USER32.DLL,NM,4, copies data from the specified dynamic data exchange (DDE)
cryptographic service provider (CSP) and returns a handle of the public key.                       object to the specified local buffer.
CryptInitOIDFunctionSet,CRYPT32.DLL,NM,2,The CryptInitOIDFunctionSet initializes and               DdeGetLastError,USER32.DLL,NM,1 returns the most recent error code set by the failure of a
returns the handle of the OID function set identified by a supplied function set name.             Dynamic Data Exchange Management Library (DDEML) function and resets the error code to
CryptInstallOIDFunctionAddress,CRYPT32.DLL,NM,6, installs a set of callable object identifier      DMLERR_NO_ERROR.
(OID) function addresses.                                                                          DdeImpersonateClient,USER32.DLL,NM,1, impersonates a dynamic data exchange (DDE)
CryptMsgCalculateEncodedLength,CRYPT32.DLL,NM,6, calculates the maximum number of                  client application in a DDE client conversation.
bytes need for an encoded cryptographic message given the message type, encoding                   DdeInitialize,USER32.DLL,AW,4, registers an application with the Dynamic Data Exchange
parameters, and total length of the data to be encoded.                                            Management Library (DDEML).
CryptMsgClose,CRYPT32.DLL,NM,1, closes a cryptographic message handle. At each call to             DdeKeepStringHandle,USER32.DLL,NM,2, increments the usage count associated with the
this function, the reference count on the message is reduced by one. When the reference count      specified handle.
reaches zero, the message is fully released.                                                       DdeNameService,USER32.DLL,NM,4 registers or unregisters the service names a dynamic
CryptMsgControl,CRYPT32.DLL,NM,4, performs a control operation after a message has been            data exchange (DDE) server supports.
decoded by a final call to the CryptMsgUpdate function.                                            DdePostAdvise,USER32.DLL,NM,3 causes the system to send an XTYP_ADVREQ transaction
CryptMsgCountersign,CRYPT32.DLL,NM,4, countersigns an existing signature in a message.             to the calling (server) application?s dynamic data exchange (DDE) callback function for each
CryptMsgCountersignEncoded,CRYPT32.DLL,NM,7, countersigns an existing PKCS #7                      client with an active advise loop on the specified topic and item.
message signature.                                                                                 DdeQueryConvInfo,USER32.DLL,NM,3 obtains information about a dynamic data exchange
CryptMsgEncodeAndSignCTL,CRYPT32.DLL,NM,6, encodes a CTL and creates a signed                      (DDE) transaction and about the conversation in which the transaction takes place.
message containing the encoded CTL.This function first encodes the CTL pointed to by pCtlInfo      DdeQueryNextServer,USER32.DLL,NM,2 obtains the next conversation handle in the specified
and then calls CryptMsgSignCTL to sign the encoded message.                                        conversation list.
CryptMsgGetAndVerifySigner,CRYPT32.DLL,NM,6, verifies a cryptographic message's                    DdeQueryString,USER32.DLL,AW,5 copies text associated with a string handle into a buffer. +
signature.                                                                                         DdeReconnect,USER32.DLL,NM,1 allows a client Dynamic Data Exchange Management
CryptMsgGetParam,CRYPT32.DLL,NM,5, acquires a message parameter after a cryptographic              Library (DDEML) application to attempt to reestablish a conversation with a service that has
message has been encoded or decoded. This function is called after the final CryptMsgUpdate        terminated a conversation with the client.
call.                                                                                              DdeSetQualityOfService,USER32.DLL,NM,3 specifies the quality of service a raw DDE
CryptMsgOpenToDecode,CRYPT32.DLL,NM,6,Opens a cryptographic message for decoding                   application desires for future DDE conversations it initiates.
and returns a handle of the opened message.                                                        DdeSetUserHandle,USER32.DLL,NM,3, associates an application-defined 32- bit value with a
CryptMsgOpenToEncode,CRYPT32.DLL,NM,6, opens a cryptographic message for encoding                  conversation handle or a transaction identifier.
and returns a handle of the opened message. The message remains open until CryptMsgClose           DdeUnaccessData,USER32.DLL,NM,1, unaccesses a dynamic data exchange (DDE) object.
is called.                                                                                         DdeUninitialize,USER32.DLL,NM,1 frees all Dynamic Data ExchangeManagement Library
CryptMsgSignCTL,CRYPT32.DLL,NM,7, creates a signed message containing an encoded                   (DDEML) resources associated with the callingapplication.
CTL.                                                                                               DeallocateNtmsMedia,NTMSAPI.DLL,NM,3, deallocates the side associated with the specified
CryptMsgUpdate,CRYPT32.DLL,NM,4, adds contents to a cryptographic message.                         logical media.
CryptMsgVerifyCountersignatureEncoded,CRYPT32.DLL,NM,7, verifies the countersignature of           DebugActiveProcess,KERNEL32.DLL,NM,1, allows a debugger to attach to an active process
a message.                                                                                         and then debug it.
                                                                                              126
DebugBreak,KERNEL32.DLL,NM,0 causes a breakpoint exception to occur inthe current                DisableNtmsObject,NTMSAPI.DLL,NM,3, disables the specified RSM object.
process so that the calling thread can signal thedebugger and force it to take some action.      DisableThreadLibraryCalls,KERNEL32.DLL,NM,1, lets a DLL disable the
DecommissionNtmsMedia,NTMSAPI.DLL,NM,2, moves a side from the Available state to the             DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls.
Decommissioned state.                                                                            DisassociateColorProfileFromDevice,MSCMS.DLL,AW,3, disassociates a specified color profile
DecryptMessage,SECUR32.DLL,NM,4,Decrypts a message by using Negotiate.                           with a specified device on a specified computer.
DefDlgProc,USER32.DLL,AW,4 carries out default message processing fora window procedure DisconnectNamedPipe,KERNEL32.DLL,NM,1, disconnects the server end of a named pipe
belonging to an application-defined dialog boxclass.                                             instance from a client process.
DefFrameProc,USER32.DLL,AW,5 provides default processing for anywindow messages that DismountNtmsDrive,NTMSAPI.DLL,NM,2, queues a command to move the media in the
the window procedure of a multiple documentinterface (MDI) frame window does not process. specified drive to its storage slot. This function should be paired with the MountNtmsMedia
DefineDosDevice,KERNEL32.DLL,AW,3 lets an application define, redefine, or delete MS-DOS function.
device names.                                                                                    DismountNtmsMedia,NTMSAPI.DLL,NM,4, queues a command to move the specified media in
DefMDIChildProc,USER32.DLL,AW,4 provides default processing for anywindow message that a drive to its storage. This function should be paired with the MountNtmsMedia function.
the window procedure of a multiple documentinterface (MDI) child window does not process.        DispatchMessage,USER32.DLL,AW,1, dispatches a message to a window procedure.
DefWindowProc,USER32.DLL,AW,4 calls the default window procedure toprovide default               DispGetIDsOfNames,OLEAUT32.DLL,NM,4,Uses type information to convert a set of names to
processing for any window messages that anapplication does not process.                          DISPIDs. This is the recommended implementation of IDispatch::GetIDsOfNames.
DeinitMapiUtil,MAPI32.DLL,NM,0 releases utility functions calledexplicitly by the ScInitMapiUtil DispGetParam,OLEAUT32.DLL,NM,5, This function retrieves a parameter from the
function or implicitly by theMAPIInitialize function.                                            DISPPARAMS structure, checks both named parameters and positional parameters, and
DeleteAce,ADVAPI32.DLL,NM,2, deletes an ACE from an ACL.                                         coerces the parameter to the specified type.
DeleteColorTransform,MSCMS.DLL,NM,1, deletes a given color transform.                            DispInvoke,OLEAUT32.DLL,NM,8,Automatically calls member functions on an interface, given
DeleteCriticalSection,KERNEL32.DLL,NM,1, releases all resources used by an unowned critical the type information for the interface. You can describe an interface with type information and
section object.                                                                                  implement IDispatch::Invoke for the interface using this single call.
DeleteDC,GDI32.DLL,NM,1, deletes the specified device context (DC).                              DlgDirList,USER32.DLL,AW,5, fills the specified list box with the names of all files matching the
DeleteEnhMetaFile,GDI32.DLL,NM,1, deletes an enhanced-format metafile or an enhanced-            specified path or filename.
format metafile handle.                                                                          DlgDirListComboBox,USER32.DLL,AW,5, fills the specified combo box with a directory listing.
DeleteFiber,KERNEL32.DLL,NM,1, deletes an existing fiber.                                        DlgDirSelectComboBoxEx,USER32.DLL,AW,4, retrieves the current selection from a combo
DeleteFile,KERNEL32.DLL,AW,1, deletes an existing file.                                          box filled by using the DlgDirListComboBox function.
DeleteForm,WINMM.DLL,AW,2, removes a form name from the list of supported forms.                 DlgDirSelectEx,USER32.DLL,AW,4, retrieves the current selection from a single-selection list
DeleteMenu,USER32.DLL,NM,3, deletes an item from the specified menu.                             box.
DeleteMetaFile,GDI32.DLL,NM,1, deletes a Windows-format metafile or Windows-format               DllDebugObjectRPCHook,OLE32.DLL,NM,2, This function is not yet supported.
metafile handle.                                                                                 DllEntryPoint,EDBBCLI.DLL,NM,3, is an optional method of entry into a dynamic-link library
DeleteMonitor,WINMM.DLL,AW,3, removes a printer monitor added by the AddMonitor                  (DLL).
function.                                                                                        DllEntryPoint,MSCMS.DLL,NM,3, is an optional method of entry into a dynamic-link library
DeleteNtmsDrive,NTMSAPI.DLL,NM,2, deletes a drive from the RSM database. The drive must (DLL).
have a dwOperationalState of NTMS_NOT_PRESENT.                                                   DocumentProperties,WINMM.DLL,AW,6 retrieves or modifies printerinitialization information or
DeleteNtmsLibrary,NTMSAPI.DLL,NM,2, deletes a library, and all the devices contained in the displays a printer-configurationdialog box for the specified printer.
library, from the RSM database. All media in the library is moved to the offline library.        DoDragDrop,OLE32.DLL,NM,4,Carries out an OLE drag and drop operation.
DeleteNtmsMedia,NTMSAPI.DLL,NM,2, deletes a physical piece of offline media from RSM by DosDateTimeToFileTime,KERNEL32.DLL,NM,3, converts MS-DOS date and time values to a
removing all references to the specified media from the database.                                64-bit file time.
DeleteNtmsMediaPool,NTMSAPI.DLL,NM,2, deletes the specified application media pool.              DosDateTimeToVariantTime,OLEAUT32.DLL,NM,3,Converts the MS-DOS representation of
DeleteNtmsMediaType,NTMSAPI.DLL,NM,3, deletes the specified media type relation from the time to the date and time representation stored in a variant.
specified library, provided that the library does not contain any physical media objects of the  DPtoLP,GDI32.DLL,NM,3, converts device coordinates into logical coordinates.
specified media type.                                                                            DragAcceptFiles,SHELL32.DLL,NM,2, registers whether a window accepts dropped files.
DeleteObject,GDI32.DLL,NM,1 deletes a logical pen, brush, font, bitmap, region, or palette,      DragDetect,USER32.DLL,NM,3 captures the mouse and tracks its movement until the user
freeing all system resources associated with the object.                                         releases the left button, presses the ESC key, or moves the mouse outside the ?drag
DeletePort,WINMM.DLL,AW,3, displays a dialog box that allows the user to delete a port name. rectangle? around the specified point.
DeletePrinter,WINMM.DLL,NM,1, deletes the specified printer object.                              DragFinish,SHELL32.DLL,NM,1, releases memory that Windows allocated for use in
DeletePrinterConnection,WINMM.DLL,AW,1 deletes a connection to aprinter that was                 transferring filenames to the application.
established by a call to AddPrinterConnection orConnectToPrinterDlg.                             DragQueryFile,SHELL32.DLL,AW,4, retrieves the filenames of dropped files.
DeletePrinterDriver,WINMM.DLL,AW,3 removes the specified printer-driver name from the list DragQueryPoint,SHELL32.DLL,NM,2, retrieves the position of the mouse pointer at the time a
of names of supported drivers for aserver.                                                       file was dropped.
DeletePrintProcessor,WINMM.DLL,AW,3, removes a printer processor added by the                    DrawAnimatedRects,USER32.DLL,NM,4 draws a wire-frame rectangle andanimates it to
AddPrintProcessor function.                                                                      indicate the opening of an icon or the minimizing ormaximizing of a window.
DeletePrintProvidor,WINMM.DLL,AW,3, removes a printer provider added by the                      DrawCaption,USER32.DLL,NM,4, draws a window caption.
AddPrintProvidor function.                                                                       DrawDibBegin,MSVFW32.DLL,NM,8 changes parameters of a DrawDib DC or initializes a new
DeleteSecurityContext,SECUR32.DLL,NM,1, deletes the local data structures associated with DrawDib DC.
the specified security context.                                                                  DrawDibChangePalette,MSVFW32.DLL,NM,4, sets the palette entries used for drawing DIBs.
DeleteService,ADVAPI32.DLL,NM,1 marks the specified service for deletion from the service        DrawDibClose,MSVFW32.DLL,NM,1, closes a DrawDib DC and frees the resources DrawDib
control manager database.                                                                        allocated for it.
DeleteUrlCacheEntry,WININET.DLL,AW,1,Removes the file associated with the source name DrawDibDraw,MSVFW32.DLL,NM,13, draws a DIB to the screen.
from the cache, if the file exists.                                                              DrawDibEnd,MSVFW32.DLL,NM,1 clears the flags and other settings of aDrawDib DC that are
DeleteUrlCacheGroup,WININET.DLL,NM,4,Releases the specified GROUPID and any                      set by the DrawDibBegin or DrawDibDrawfunctions.
associated state in the cache index file.                                                        DrawDibGetBuffer,MSVFW32.DLL,NM,4, retrieves the location of the buffer used by DrawDib
DeregisterEventSource,ADVAPI32.DLL,NM,1, closes a handle to the specified event log.             for decompression.
DeregisterIdleRoutine,MAPI32.DLL,NM,1, removes a FNIDLE - based idle routine from the            DrawDibGetPalette,MSVFW32.DLL,NM,1, retrieves the palette used by a DrawDib DC.
MAPI system.                                                                                     DrawDibOpen,MSVFW32.DLL,NM,0, opens the DrawDib library for use and creates a DrawDib
DescribePixelFormat,GDI32.DLL,NM,4 obtains information about thepixel format identified by DC for drawing.
iPixelFormat of the device associatedwith hdc.                                                   DrawDibProfileDisplay,MSVFW32.DLL,NM,1, determines settings for the display system when
DestroyAcceleratorTable,USER32.DLL,NM,1, destroys an accelerator table.                          using DrawDib functions.
DestroyCaret,USER32.DLL,NM,0, destroys the caret?s current shape, frees the caret from the DrawDibRealize,MSVFW32.DLL,NM,3, realizes the palette of the DrawDib DC for use with the
window, and removes the caret from the screen.                                                   specified DC.
DestroyCursor,USER32.DLL,NM,1, destroys a cursor and frees any memory the cursor                 DrawDibSetPalette,MSVFW32.DLL,NM,2 sets the palette used for drawing DIBs.
occupied.                                                                                        DrawDibStart,MSVFW32.DLL,NM,2, prepares a DrawDib DC for streaming playback.
DestroyEnvironmentBlock,USERENV.DLL,NM,1, frees environment variables created by the             DrawDibStop,MSVFW32.DLL,NM,1, frees the resources used by a DrawDib DC for streaming
CreateEnvironmentBlock function.                                                                 playback.
DestroyIcon,USER32.DLL,NM,1, destroys an icon and frees any memory the icon occupied.            DrawDibTime,MSVFW32.DLL,NM,2, retrieves timing information about the drawing operation
DestroyMenu,USER32.DLL,NM,1 destroys the specified menu and frees any memory that the and is used during debug operations.
menu occupies.                                                                                   DrawEdge,USER32.DLL,NM,4, draws one or more edges of rectangle.
DestroyPrivateObjectSecurity,ADVAPI32.DLL,NM,1 deletes a protected server object?s               DrawEscape,GDI32.DLL,NM,4 accesses drawing capabilities of a video display that are not
security descriptor.                                                                             directly available through the graphics device interface (GDI).
DestroyPropertySheetPage,COMCTL32.DLL,NM,1, destroys a property sheet not been passed DrawFocusRect,USER32.DLL,NM,2, draws a rectangle in the style used to indicate that the
to the PropertySheet function.                                                                   rectangle has the focus.
DestroyWindow,USER32.DLL,NM,1, destroys the specified window.                                    DrawFrameControl,USER32.DLL,NM,4, draws a frame control of the specified type and style.
DeviceCapabilities,WINMM.DLL,AW,5, retrieves the capabilities of a printer device driver.        DrawIcon,USER32.DLL,NM,4, draws an icon in the client area of the window of the specified
DeviceIoControl,KERNEL32.DLL,NM,8 sends a control code directly to a specified device            device context.
driver, causing the corresponding device to perform the specified operation.                     DrawIconEx,USER32.DLL,NM,9 draws an icon or cursor in the client area of the window of the
DialogBoxIndirectParam,USER32.DLL,AW,5, creates a modal dialog box from a dialog box             specified device context, performing the specified raster operations, and stretching or
template in memory.                                                                              compressing the icon or cursor as specified.
DialogBoxParam,USER32.DLL,AW,5, creates a modal dialog box from a dialog box template            DrawInsert,COMCTL32.DLL,NM,3, draws the insert icon in the parent window of the specified
resource.                                                                                        drag list box.
DirectDrawCreate,DDRAW.DLL,NM,3,creates an instance of a DirectDraw object.                      DrawMenuBar,USER32.DLL,NM,1, redraws the menu bar of the specified window.
DirectDrawCreateClipper,DDRAW.DLL,NM,3,creates an instance of a DirectDrawClipper object DrawState,USER32.DLL,AW,10, displays an image and applies a visual effect to indicate a
not associated with a DirectDraw object.                                                         state, such as a disabled or default state.
DirectDrawEnumerate,DDRAW.DLL,AW,2,enumerates the primary DirectDraw display device DrawStatusText,COMCTL32.DLL,AW,4, draws the specified text in the style of a status window
and a nondisplay device (such as a 3-D accelerator that has no 2-D capabilities), if one is      with borders.
installed.                                                                                       DrawText,USER32.DLL,AW,5, draws formatted text in the specified rectangle.
DirectInputCreate,DINPUT.DLL,AW,4,This function creates a DirectInput object that supports       DrawTextEx,USER32.DLL,AW,6 draws formatted text in the specified rectangle.
the IDirectInput COM interface.                                                                  DriveType,SHELL32.DLL,NM,1 Determines the drive type based on the drive number.
DirectPlayCreate,DPLAY.DLL,NM,3,Creates an instance of a DirectPlay object.                      DumpCAP,CAP.DLL,NM,0,Write data for the current instance of CAP.DLL. The name of the
DirectPlayCreate,DPLAYX.DLL,NM,3,Creates an instance of a DirectPlay object.                     text file is APPNAME.CAP.
DirectPlayEnumerate,DPLAY.DLL,NM,2,Enumerates the DirectPlay service providers installed DuplicateHandle,KERNEL32.DLL,NM,7, duplicates an object handle.
on the system.                                                                                   DuplicateToken,ADVAPI32.DLL,NM,3, creates a new access token that duplicates one already
DirectPlayEnumerate,DPLAYX.DLL,AW,2,Enumerates the DirectPlay service providers                  in existence.
installed on the system.                                                                         DuplicateTokenEx,ADVAPI32.DLL,NM,6, creates a new access token that duplicates an
DirectPlayLobbyCreate,DPLAYX.DLL,AW,5,Creates an instance of a DirectPlayLobby object. existing token.
DirectXFileCreate,D3DXOF.DLL,NM,1,Creates an instance of a DirectXFile object.                   EjectNtmsCleaner,NTMSAPI.DLL,NM,4, ejects the cleaning cartridge from the currently
DirectXRegisterApplication,DSETUP.DLL,AW,2,Registers an ISV's game as an application             reserved cleaner slot.
designed to work with DirectPlayLobby.                                                           EjectNtmsMedia,NTMSAPI.DLL,NM,4, ejects the specified medium from the port of the current
DirectXSetup,DSETUP.DLL,AW,3,Installs one or more DirectX components.                            library. If the library is busy, RSM queues EjectNtmsMedia and returns success.
                                                                                              127
Ellipse,GDI32.DLL,NM,5 draws an ellipse. The center of the ellipse is the center of the specified   EnumSystemLocales,KERNEL32.DLL,AW,2, enumerates the locales that are either installed on
bounding rectangle.                                                                                 or supported by a system.
EmptyClipboard,USER32.DLL,NM,0, empties the clipboard and frees handles to data in the              EnumThreadWindows,USER32.DLL,NM,3 enumerates all nonchild windows associated with a
clipboard.                                                                                          thread by passing the handle of each window, in turn, to an application-defined callback
EmptyWorkingSet,PSAPI.DLL,NM,1, removes as many pages as possible from the working set              function.
of the specified process.                                                                           EnumTimeFormats,KERNEL32.DLL,AW,3, enumerates the time formats that are available for a
EnableIdleRoutine,MAPI32.DLL,NM,2 enables or disables a FNIDLE based idle routine.                  specified locale.
EnableMenuItem,USER32.DLL,NM,3, enables, disables, or grays the specified menu item.                EnumWindows,USER32.DLL,NM,2 enumerates all top-level windows on thescreen by passing
EnableNtmsObject,NTMSAPI.DLL,NM,3, enables the specified object.                                    the handle of each window, in turn, to anapplication-defined callback function.
EnableScrollBar,USER32.DLL,NM,3, enables or disables one or both scroll bar arrows.                 EnumWindowStations,USER32.DLL,AW,2, enumerates only those window stations for which
EnableWindow,USER32.DLL,NM,2, enables or disables mouse and keyboard input to the                   the calling process has WINSTA_ENUMERATE access.
specified window or control.                                                                        EqualPrefixSid,ADVAPI32.DLL,NM,2, tests two security-identifier (SID) prefix values for
EncryptMessage,SECUR32.DLL,NM,4,Encrypts a message to provide privacy by using                      equality.
Negotiate.                                                                                          EqualRect,USER32.DLL,NM,2 determines whether the two specifiedrectangles are equal by
EndDialog,USER32.DLL,NM,2, destroys a modal dialog box, causing the system to end any               comparing the coordinates of their upper-left and lower-right corners.
processing for the dialog box.                                                                      EqualRgn,GDI32.DLL,NM,2, checks the two specified regions to determine whether they are
EndDoc,GDI32.DLL,NM,1 ends a print job. This function replaces the ENDDOC printer escape.           identical.
EndDocPrinter,WINMM.DLL,NM,1, returns an error if the print job was not started by calling the      EqualSid,ADVAPI32.DLL,NM,2, tests two security identifier (SID) values.
StartDocPrinter function.                                                                           EraseTape,KERNEL32.DLL,NM,3 erases all or part of a tape.
EndPage,GDI32.DLL,NM,1 informs the device that the application has finished writing to a            Escape,GDI32.DLL,NM,5, allows applications to access capabilities of a particular device not
page.                                                                                               directly available through GDI.
EndPagePrinter,WINMM.DLL,NM,1, indicates the end of one page and the beginning of the               EscapeCommFunction,KERNEL32.DLL,NM,2, directs a specified communications device to
next page for the specified printer.                                                                perform an extended function.
EndPaint,USER32.DLL,NM,2, marks the end of painting in the specified window.                        ExcludeClipRect,GDI32.DLL,NM,5 creates a new clipping region thatconsists of the existing
EndPath,GDI32.DLL,NM,1, closes a path bracket and selects the path defined by the bracket           clipping region minus the specifiedrectangle.
into the specified device context.                                                                  ExcludeUpdateRgn,USER32.DLL,NM,2 prevents drawing within invalid areasof a window by
EndUpdateResource,KERNEL32.DLL,AW,2, ends a resource update in an executable file.                  excluding an updated region in the window from aclipping region.
EnterCriticalPolicySection,USERENV.DLL,NM,1, pauses the application of policy to allow              ExitProcess,KERNEL32.DLL,NM,1,l does not return until no threads are in their DLL
applications to safely read policy settings.                                                        initialization or detach routines.
EnterCriticalSection,KERNEL32.DLL,NM,1, waits for ownership of the specified critical section       ExitThread,KERNEL32.DLL,NM,1, ends a thread.
object.                                                                                             ExitWindowsEx,USER32.DLL,NM,2, returns as soon as it has initiated the shutdown.
EnumCalendarInfo,KERNEL32.DLL,AW,4, enumerates calendar information for a specified                 ExpandEnvironmentStrings,KERNEL32.DLL,AW,3, expands environment-variable strings and
locale.                                                                                             replaces them with their defined values.
EnumChildWindows,USER32.DLL,NM,3, enumerates the child windows that belong to the                   ExpandEnvironmentStringsForUser,USERENV.DLL,AW,4, expands the source string by using
specified parent window by passing the handle of each child window, in turn, to an application-     the environment block established for the specified user.
defined callback function.                                                                          ExportNtmsDatabase,NTMSAPI.DLL,NM,1, creates a consistent set of database files in the
EnumClipboardFormats,USER32.DLL,NM,1, lets you enumerate the data formats that are                  RSM database directory.
currently available on the clipboard.                                                               ExportSecurityContext,SECUR32.DLL,NM,4, creates a serialized representation of a security
EnumColorProfiles,MSCMS.DLL,AW,5, enumerates all the profiles satisfying the given                  context that can later be imported into a different process by calling ImportSecurityContext.
enumeration criteria.                                                                               ExtCreatePen,GDI32.DLL,NM,5, creates a logical cosmetic or geometric pen that has the
EnumDateFormats,KERNEL32.DLL,AW,3 enumerates the long or short dateformats that are                 specified style, width, and brush attributes.
available for a specified locale, including dateformats for any alternate calendars.                ExtCreateRegion,GDI32.DLL,NM,3, creates a region from the specified region and
EnumDependentServices,ADVAPI32.DLL,AW,6 provides the name and status of each service                transformation data.
that depends on the specified service; that is, the specified service must be running before the    ExtensionPropSheetPageProc,SETUPAPI.DLL,NM,3 specifies an application-defined callback
dependent services can run.                                                                         function that receives the address of the AddPropSheetPageProc function, which resides in the
EnumDesktopWindows,USER32.DLL,NM,3 enumerates all windows in a desktopby passing the                module that creates a property sheet.
handle of each window, in turn, to an application-defined callback function.                        ExtEscape,GDI32.DLL,NM,6, allows applications to access capabilities of a particular device
EnumDeviceDrivers,PSAPI.DLL,NM,3, retrieves the load address for each device driver in the          that are not available through GDI.
system.                                                                                             ExtFloodFill,GDI32.DLL,NM,5, fills an area of the display surface with the current brush.
EnumDisplayMonitors,USER32.DLL,NM,4 enumerates display monitors (including invisible                ExtractAssociatedIcon,SHELL32.DLL,AW,3 returns the handle of an indexedicon found in a file
pseudo-monitors associated with the mirroring drivers) that intersect a region formed by the        or an icon found in an associated executablefile.
intersection of a specified clipping rectangle and the visible region of a device context.          ExtractIcon,SHELL32.DLL,AW,3 retrieves the handle of an icon from thespecified executable
EnumDisplaySettings,USER32.DLL,AW,3 obtains information about one of a display device?s             file, dynamic-link library (DLL), or iconfile.
graphics modes.                                                                                     ExtractIconEx,SHELL32.DLL,AW,5 retrieves the handle of an icon from thespecified executable
EnumEnhMetaFile,GDI32.DLL,NM,5 enumerates the records within anenhanced-format                      file, dynamic-link library (DLL), or iconfile.
metafile by retrieving each record and passing itto the specified callback function.                ExtSelectClipRgn,GDI32.DLL,NM,3 combines the specified region with the current clipping
EnumerateNtmsObject,NTMSAPI.DLL,NM,6, enumerates the RSM objects contained in the                   region by using the specified mode.
lpContainerId parameter.                                                                            ExtTextOut,GDI32.DLL,AW,8, draws a character string by using the currently selected font.
EnumerateSecurityPackages,SECUR32.DLL,AW,2,Returns an array of SecPkgInfo structures                FatalAppExit,KERNEL32.DLL,AW,2 displays a message box and terminates the application
that describe the security packages available to the client.                                        when the message box is closed.
EnumFontFamilies,GDI32.DLL,AW,4, enumerates the fonts in a specified font family that are           FatalExit,KERNEL32.DLL,NM,1, transfers execution control to the debugger.
available on a specified device.                                                                    FaxAbort,WINFAX.DLL,NM,2, A fax client application calls the FaxAbort function to terminate a
EnumFontFamiliesEx,GDI32.DLL,AW,5 enumerates all fonts in the systemthat match the font             fax job.
characteristics specified by the LOGFONTstructure.                                                  FaxAccessCheck,WINFAX.DLL,NM,2, A fax client application calls the FaxAccessCheck
EnumFonts,GDI32.DLL,AW,4, enumerates the fonts available on a specified device.                     function to query the fax access privileges of a user.
EnumForms,WINMM.DLL,AW,6 enumerates the forms supported by the specified printer.                   FaxClose,WINFAX.DLL,NM,1, closes the following types of fax handles: A fax server handle
EnumJobs,WINMM.DLL,AW,8 initializes an array of either JOB_INFO_1 orJOB_INFO_2                      returned by a call the FaxConnectFaxServer function A fax port handle returned by a call
structures with data describing the specified print jobsfor the specified printer.                  FaxCompleteJobParams,WINFAX.DLL,AW,2, creates both a FAX_COVERPAGE_INFO
EnumMetaFile,GDI32.DLL,NM,4 enumerates the records within a Windows-format metafile by              structure and a FAX_JOB_PARAM structure for a fax client application.
retrieving each record and passing it to the specified callback function.                           FaxConnectFaxServer,WINFAX.DLL,AW,2, connects a fax client application to the local fax
EnumMonitors,WINMM.DLL,AW,6 initializes an array of structures with data describing the             server.
monitors for the specified server.                                                                  FaxEnableRoutingMethod,WINFAX.DLL,AW,3, enables or disables a fax routing method for a
EnumObjects,GDI32.DLL,NM,4, enumerates the pens or brushes available for the specified              specific fax device. A fax administration application typically calls this function for device
device context.                                                                                     management.
EnumPorts,WINMM.DLL,AW,5, can succeed even if the server specified by pName does not                FaxEnumGlobalRoutingInfo,WINFAX.DLL,AW,3, enumerates all fax routing methods
have a printer defined.                                                                             associated with a specific fax server.
EnumPrinterDrivers,WINMM.DLL,AW,7, enumerates all of the printer drivers installed on the           FaxEnumJobs,WINFAX.DLL,AW,3, enumerates all queued and active fax jobs on the fax
specified printer server.                                                                           server to which the client has connected. The function returns detailed information for each fax
EnumPrinters,WINMM.DLL,AW,7, enumerates available printers, print servers, domains, or              job to the fax client application.
print providers.                                                                                    FaxEnumPorts,WINFAX.DLL,AW,3, enumerates all fax devices currently attached to the fax
EnumPrintProcessorDatatypes,WINMM.DLL,AW,7, enumerates the data types that a specifed               server to which the client has connected. The function returns detailed information for each fax
print processor supports.                                                                           port to the fax client application.
EnumPrintProcessors,WINMM.DLL,AW,7, enumerates the print processors installed on the                FaxEnumRoutingMethods,WINFAX.DLL,AW,3, enumerates all fax routing methods for a
specified server.                                                                                   specific fax device. The function returns information about each routing method to a fax client
EnumProcesses,PSAPI.DLL,NM,3, retrieves the process identifier for each process object in           application.
the system.                                                                                         FaxFreeBuffer,WINFAX.DLL,NM,1, releases resources associated with a buffer allocated
EnumProcessModules,PSAPI.DLL,NM,4, retrieves a handle for each module in the specified              previously as the result of a function call by a fax client application.
process.                                                                                            FaxGetConfiguration,WINFAX.DLL,AW,2, returns to a fax client application the global
EnumProps,USER32.DLL,AW,2 enumerates all entries in the property listof a window by                 configuration settings for the fax server to which the client has connected.
passing them, one by one, to the specified callbackfunction.                                        FaxGetDeviceStatus,WINFAX.DLL,AW,2, returns to a fax client application current status
EnumPropsEx,USER32.DLL,AW,3 enumerates all entries in the propertylist of a window by               information for the fax device of interest.
passing them, one by one, to the specifiedcallback function.                                        FaxGetJob,WINFAX.DLL,AW,3, A fax client application calls the FaxGetJob function to retrieve
EnumProtocols,MSWSOCK.DLL,AW,3,Important is a Microsoft-specific extension to the                   detailed information for the specified queued or active fax job. The function returns the
Windows Sockets 1.                                                                                  information in a FAX_JOB_ENTRY structure.
EnumProtocols,WSOCK32.DLL,AW,3,Important is a Microsoft-specific extension to the                   FaxGetLoggingCategories,WINFAX.DLL,AW,3, returns to a fax client application the current
Windows Sockets 1.                                                                                  logging categories for the fax server to which the client has connected.
EnumResourceLanguages,KERNEL32.DLL,AW,5 searches a module for eachresource of the                   FaxGetPageData,WINFAX.DLL,NM,6, returns to a fax client application the first page of data
specified type and name and passes the language ofeach resource it locates to a defined             for a fax job. The fax job must be an outbound job, but it can be queued or active.
callback function.                                                                                  FaxGetPort,WINFAX.DLL,AW,2, returns information for a specified fax port to a fax client
EnumResourceNames,KERNEL32.DLL,AW,4 searches a module for each resourceof the                       application.
specified type and passes the name of each resource itlocates to an application-defined             FaxGetRoutingInfo,WINFAX.DLL,AW,4, returns to a fax client application routing information for
callback function.                                                                                  a fax routing method that is associated with a specific fax device.
EnumResourceTypes,KERNEL32.DLL,AW,3 searches a module for resources andpasses each                  FaxInitializeEventQueue,WINFAX.DLL,NM,5, creates a fax event queue for the calling fax client
resource type it finds to an application-definedcallback function.                                  application. The queue enables the application to receive notifications of asynchronous events
EnumServicesStatus,ADVAPI32.DLL,AW,8 enumerates services in the specified service control           from the fax server.
manager database.                                                                                   FaxOpenPort,WINFAX.DLL,NM,4, returns a fax port handle to a fax client application. The port
EnumSystemCodePages,KERNEL32.DLL,AW,2 enumerates the code pages that are either                     handle is required when the application calls other fax client functions that facilitate device
installed on or supported by a system.                                                              management and fax document routing.
                                                                                               128
FaxPrintCoverPage,WINFAX.DLL,AW,2, prints a fax transmission cover page to the specified             FindWindowEx,USER32.DLL,AW,4 retrieves the handle to a window whose class name and
device context for a fax client application. A device context handle is obtained by using the        window name match the specified strings.
FaxStartPrintJob function.                                                                           FixBrushOrgEx,GDI32.DLL,NM,4, is not implemented in the Win32 API.
FaxSendDocument,WINFAX.DLL,AW,5,ForBroadcast A fax client application calls the                      FlashWindow,USER32.DLL,NM,2, flashes the window only once; for repeated flashing, the
FaxSendDocumentForBroadcast function to queue several fax jobs that will transmit the same           application should create a system timer.
outgoing fax transmission to several recipients.                                                     FlatSB_EnableScrollBar,COMCTL32.DLL,NM,3,Enables or disables one or both flat scroll bar
FaxSendDocumentForBroadcast,WINFAX.DLL,AW,5, A fax client application calls the                      direction buttons.
FaxSendDocumentForBroadcast function to queue several fax jobs that will transmit the same           FlatSB_GetScrollInfo,COMCTL32.DLL,NM,3,Retrieves the information for a flat scroll bar.
outgoing fax transmission to several recipients.                                                     FlatSB_GetScrollPos,COMCTL32.DLL,NM,2,Retrieves the thumb position in a flat scroll bar.
FaxSetConfiguration,WINFAX.DLL,AW,2, A fax client application calls the FaxSetConfiguration          FlatSB_GetScrollProp,COMCTL32.DLL,NM,3,Retrieves the properties for a flat scroll bar.
function to change the global configuration settings for the fax server to which the client has      FlatSB_GetScrollRange,COMCTL32.DLL,NM,4,Retrieves the scroll range for a flat scroll bar.
connected.                                                                                           FlatSB_SetScrollInfo,COMCTL32.DLL,NM,4,Sets the information for a flat scroll bar.
FaxSetGlobalRoutingInfo,WINFAX.DLL,AW,2, A fax management application calls the                      FlatSB_SetScrollPos,COMCTL32.DLL,NM,4,Sets the current position of the thumb in a flat
FaxSetGlobalRoutingInfo function to modify fax routing method data, such as routing priority,        scroll bar.
that applies globally to the fax server.                                                             FlatSB_SetScrollProp,COMCTL32.DLL,NM,4,Sets the properties for a flat scroll bar.
FaxSetJob,WINFAX.DLL,AW,4, A fax client application calls the FaxSetJob function to pause,           FlatSB_SetScrollRange,COMCTL32.DLL,NM,5,Sets the scroll range of a flat scroll bar.
resume, cancel, or restart a specified fax job.                                                      FlatSB_ShowScrollBar,COMCTL32.DLL,NM,3,Shows or hides a flat scroll bar.
FaxSetLoggingCategories,WINFAX.DLL,AW,3, A fax client application calls the                          FlattenPath,GDI32.DLL,NM,1 transforms any curves in the path that isselected into the current
FaxSetLoggingCategories function to modify the current logging categories for the fax server to      device context (DC), turning each curveinto a sequence of lines.
which the client has connected.                                                                      FloodFill,GDI32.DLL,NM,4, fills an area of the display surface with the current brush.
FaxSetPort,WINFAX.DLL,AW,2, A fax client application calls the FaxSetPort function to change         FlushConsoleInputBuffer,KERNEL32.DLL,NM,1 flushes the console input buffer. All input
the configuration of the fax port of interest.                                                       records currently in the input buffer are discarded.
FaxSetRoutingInfo,WINFAX.DLL,AW,4, A fax management application calls the                            FlushFileBuffers,KERNEL32.DLL,NM,1, clears the buffers for the specified file and causes all
FaxSetRoutingInfo function to modify the routing information for a fax routing method that is        buffered data to be written to the file.
associated with a specific fax device.                                                               FlushInstructionCache,KERNEL32.DLL,NM,3, flushes the instruction cache for the specified
FaxStartPrintJob,WINFAX.DLL,AW,4, A fax client application calls the FaxStartPrintJob                process.
function to start printing an outbound fax transmission on the specified fax printer. The function   FlushViewOfFile,KERNEL32.DLL,NM,2, writes to the disk a byte range within a mapped view of
returns a handle to a device context.                                                                a file.
FBadColumnSet,MAPI32.DLL,NM,1 tests the validity of a table column setfor use by a service           FmtIdToPropStgName,IPROP.DLL,NM,2,Converts a property set format identifier (FMTID) to
provider in a subsequent call to theIMAPITable::SetColumns method.                                   its storage or stream name.
FBadEntryList,MAPI32.DLL,NM,1, validates a list of MAPI entry identifiers.                           FoldString,KERNEL32.DLL,AW,5, maps one string to another, performing a specified
FBadProp,MAPI32.DLL,NM,1, validates a specified property.                                            transformation option.
FBadPropTag,MAPI32.DLL,NM,1, validates a specified property tag.                                     FormatMessage,KERNEL32.DLL,AW,7, formats a message string.
FBadRestriction,MAPI32.DLL,NM,1, validates a restriction used to limit a table view.                 FPropCompareProp,MAPI32.DLL,NM,3, compares two property values using a binary relational
FBadRglpNameID,MAPI32.DLL,NM,2, validates an array of structures that describe named                 operator.
properties and verifies their allocation.                                                            FPropContainsProp,MAPI32.DLL,NM,3 compares two property values,generally strings or
FBadRglpsz,MAPI32.DLL,AW,2 validates all strings in an array of Unicode strings.                     binary arrays, to see if one contains theother.
FBadRow,MAPI32.DLL,NM,1, validates a row in a table.                                                 FPropExists,MAPI32.DLL,NM,2 searches for a given property tag in anIMAPIProp interface or
FBadRowSet,MAPI32.DLL,NM,1, validates all table rows included in a set of table rows.                an interface derived from IMAPIProp, such asIMessage or IMAPIFolder.
FBadSortOrderSet,MAPI32.DLL,NM,1, validates a sort order set by verifying its memory                 FrameRect,USER32.DLL,NM,3, draws a border around the specified rectangle by using the
allocation.                                                                                          specified brush.
FBinFromHex,MAPI32.DLL,NM,2 converts a string representation of a hexadecimal number to              FrameRgn,GDI32.DLL,NM,5, draws a border around the specified region by using the specified
binary data.                                                                                         brush.
FEqualNames,MAPI32.DLL,NM,2, determines whether two MAPI named properties are the                    FreeConsole,KERNEL32.DLL,NM,0, detaches the calling process from its console.
same.                                                                                                FreeContextBuffer,SECUR32.DLL,NM,1,Enables callers of security package functions to free a
FileTimeToDosDateTime,KERNEL32.DLL,NM,3, converts a 64-bit file time to MS-DOS date                  memory buffer that was allocated by the security package as a result of calls to
and time values.                                                                                     InitializeSecurityContext (General) and AcceptSecurityContext (General).
FileTimeToLocalFileTime,KERNEL32.DLL,NM,2, converts a file time based on the Coordinated             FreeCredentialsHandle,SECUR32.DLL,NM,1,Notifies the security system that the credentials
Universal Time (UTC) to a local file time.                                                           are no longer needed. An application calls this function to free the credential handle acquired in
FileTimeToSystemTime,KERNEL32.DLL,NM,2, converts a 64-bit file time to system time                   the call to the AcquireCredentialsHandle (General) function.
format.                                                                                              FreeDDElParam,USER32.DLL,NM,2, frees the memory specified by the lParam parameter of a
FillConsoleOutputAttribute,KERNEL32.DLL,NM,5 sets the text and background color attributes           posted DDE message.
for a specified number of charactercells, beginning at the specified coordinates in a screen         FreeEnvironmentStrings,KERNEL32.DLL,AW,1 frees a block of environment strings.
buffer.                                                                                              FreeGPOList,USERENV.DLL,AW,1, frees the specified linked list of GPOs.
FillConsoleOutputCharacter,KERNEL32.DLL,AW,5 writes a character to the screen buffer a               FreeLibrary,KERNEL32.DLL,NM,1, decrements the reference count of the loaded dynamic-link
specified number of times, beginning at the specified coordinates.                                   library (DLL) module.
FillPath,GDI32.DLL,NM,1 closes any open figures in the current pathand fills the path?s interior     FreeLibraryAndExitThread,KERNEL32.DLL,NM,2 decrements the reference count of a loaded
by using the current brush andpolygon-filling mode.                                                  dynamic-link library (DLL) by one, and then calls ExitThread to terminate the calling thread.
FillRect,USER32.DLL,NM,3, fills a rectangle by using the specified brush.                            FreePadrlist,MAPI32.DLL,NM,1 destroys an ADRLIST structure and freesassociated memory,
FillRgn,GDI32.DLL,NM,3, fills a region by using the specified brush.                                 including memory allocated for all member arraysand structures.
FindAtom,KERNEL32.DLL,AW,1 searches the local atom table for thespecified character string           FreePrinterNotifyInfo,WINMM.DLL,NM,1 frees a system-allocated bufferthat was returned by
and retrieves the atom associated withthat string.                                                   the FindNextPrinterChangeNotificationfunction.
FindClose,KERNEL32.DLL,NM,1, closes the specified search handle.                                     FreePropVariantArray,IPROP.DLL,NM,2, calls PropVariantClear on each of the
FindCloseChangeNotification,KERNEL32.DLL,NM,1, stops change notification handle                      PROPVARIANT structures in the rgvars array to make the value zero for each of the members
monitoring.                                                                                          of the array.
FindClosePrinterChangeNotification,WINMM.DLL,NM,1 closes a change notification object                FreePropVariantArray,OLE32.DLL,NM,2, calls PropVariantClear on each of the
created by calling the FindFirstPrinterChangeNotification function.                                  PROPVARIANT structures in the rgvars array to make the value zero for each of the members
FindCloseUrlCache,WININET.DLL,NM,1,Closes the specified cache enumeration handle.                    of the array.
FindDebugInfoFile,IMAGEHLP.DLL,NM,3, locates a debug (.dbg) file.                                    FreeProws,MAPI32.DLL,NM,1 destroys an SRowSet structure and freesassociated memory,
FindExecutable,SHELL32.DLL,AW,3, retrieves the name and handle to the executable (.                  including memory allocated for all member arraysand structures.
FindExecutableImage,IMAGEHLP.DLL,NM,3, locates an executable file.                                   FreeResource,KERNEL32.DLL,NM,1, is obsolete.
FindFirstChangeNotification,KERNEL32.DLL,AW,3 creates a change notification handle and               FreeSid,ADVAPI32.DLL,NM,1, frees a security identifier (SID) previously allocated by using the
sets up initial change notification filter conditions.                                               AllocateAndInitializeSid function.
FindFirstFile,KERNEL32.DLL,AW,2, searches a directory for a file whose name matches the              FtAddFt,MAPI32.DLL,NM,4, adds one unsigned 64-bit integer to another.
specified filename.                                                                                  FtgRegisterIdleRoutine,MAPI32.DLL,NM,5, adds a FNIDLE - based idle routine to the MAPI
FindFirstFileEx,KERNEL32.DLL,AW,6, searches a directory for a file whose name and                    system.
attributes match those specified in the function call.                                               FtMulDw,MAPI32.DLL,NM,3, multiplies an unsigned 64-bit integer by an unsigned 32-bit
FindFirstFreeAce,ADVAPI32.DLL,NM,2, retrieves a pointer to the first free byte in an access-         integer.
control list (ACL).                                                                                  FtMulDwDw,MAPI32.DLL,NM,2, multiplies one unsigned 32-bit integer by another.
FindFirstPrinterChangeNotification,WINMM.DLL,NM,3, creates a change notification object and          FtNegFt,MAPI32.DLL,NM,2, computes the two?s complement of an unsigned 64-bit integer.
returns a handle to the object.                                                                      FtpCommand,WININET.DLL,AW,6,Sends commands directly to an FTP server.
FindFirstUrlCacheEntry,WININET.DLL,AW,3,Begins the enumeration of the Internet cache.                FtpCreateDirectory,WININET.DLL,AW,2,Creates a new directory on the FTP server.
FindFirstUrlCacheEntryEx,WININET.DLL,AW,10,Starts a filtered enumeration of the Internet             FtpDeleteFile,WININET.DLL,AW,2,Deletes a file stored on the FTP server.
cache.                                                                                               FtpFindFirstFile,WININET.DLL,AW,5,Searches the specified directory of the given FTP session.
FindFirstUrlCacheGroup,WININET.DLL,NM,6,Initiates the enumeration of the cache groups in             File and directory entries are returned to the application in the WIN32_FIND_DATA structure.
the Internet cache.                                                                                  FtpGetCurrentDirectory,WININET.DLL,AW,3,Retrieves the current directory for the specified
FindMediaType,URLMON.DLL,NM,2,Class Retrieves the CLSID for the specified media type.                FTP session.
FindMediaTypeClass,URLMON.DLL,NM,4, Retrieves the CLSID for the specified media type.                FtpGetFile,WININET.DLL,AW,7,Retrieves a file from the FTP server and stores it under the
FindNextChangeNotification,KERNEL32.DLL,NM,1 requests that the operating system signal a             specified file name, creating a new local file in the process.
change notification handle the next time it detects an appropriate change.                           FtpGetFileEx,WININET.DLL,NM,7,retrieves a file from the FTP server and stores it under the
FindNextFile,KERNEL32.DLL,AW,2, continues a file search from a previous call to the                  specified file name, creating a new local file in the process.
FindFirstFile function.                                                                              FtpGetFileSize,WININET.DLL,NM,2,Retrieves the file size of the requested FTP resource.
FindNextPrinterChangeNotification,WINMM.DLL,NM,3 retrieves information about the most                FtpOpenFile,WININET.DLL,AW,5,Initiates access to a remote file on an FTP server for reading
recent change notification for a change notification object associated with a printer or print       or writing.
server.                                                                                              FtpPutFile,WININET.DLL,AW,5,Stores a file on the FTP server.
FindNextUrlCacheEntry,WININET.DLL,AW,3,Retrieves the next entry in the Internet cache.               FtpPutFileEx,WININET.DLL,NM,5,This function stores a file on the FTP server.
FindNextUrlCacheEntryEx,WININET.DLL,AW,6,Finds the next cache entry in a cache                       FtpRemoveDirectory,WININET.DLL,AW,2,Removes the specified directory on the FTP server.
enumeration started by the FindFirstUrlCacheEntryEx function.                                        FtpRenameFile,WININET.DLL,AW,3,Renames a file stored on the FTP server.
FindNextUrlCacheGroup,WININET.DLL,NM,3,Retrieves the next cache group in a cache group               FtpSetCurrentDirectory,WININET.DLL,AW,2,Changes to a different working directory on the
enumeration started by FindFirstUrlCacheGroup.                                                       FTP server.
FindResource,KERNEL32.DLL,AW,3 determines the location of a resource with the specified              FtSubFt,MAPI32.DLL,NM,4, subtracts one unsigned 64-bit integer from another.
type and name in the specified module.                                                               GdiComment,GDI32.DLL,NM,3, copies a comment from a buffer into a specified enhanced
FindResourceEx,KERNEL32.DLL,AW,4 determines the location of the resourcewith the                     format metafile.
specified type, name, and language in the specifiedmodule.                                           GdiFlush,GDI32.DLL,NM,0, flushes the calling thread?s current batch.
FindText,COMDLG32.DLL,AW,1 creates a system-defined modeless dialog boxthat lets the                 GdiGetBatchLimit,GDI32.DLL,NM,0, returns the batch limit.
user specify a string to search for and options touse when searching for text in a document.         GdiSetBatchLimit,GDI32.DLL,NM,1, sets the maximum number of functions that can be
FindWindow,USER32.DLL,AW,2 retrieves the handle to the top-levelwindow whose class name              accumulated in the calling thread?s current batch.
and window name match the specifiedstrings.
                                                                                              129
GenerateConsoleCtrlEvent,KERNEL32.DLL,NM,2 sends a specified signal to aconsole process             GetColorProfileFromHandle,MSCMS.DLL,NM,3,Given a handle to an open color profile, the
group that shares the console associated with thecalling process.                                   GetColorProfileFromHandle function will copy the contents of the profile into a buffer supplied
GenerateCopyFilePaths,MSCMS.DLL,NM,9,graphics, GraphicsDrivers, Reference,                          by the application.
GenerateCopyFilePaths                                                                               GetColorProfileHeader,MSCMS.DLL,NM,2, retrieves the header of a color profile.
GetAcceptExSockaddrs,MSWSOCK.DLL,NM,8, parses the data obtained from a call to the                  GetCommandLine,KERNEL32.DLL,AW,0 returns a pointer to the command-line string for the
AcceptEx function and passes the local and remote addresses to a SOCKADDR structure.                current process.
GetAcceptExSockaddrs,WSOCK32.DLL,NM,8, parses the data obtained from a call to the                  GetCommConfig,KERNEL32.DLL,NM,3 gets the current configuration of a communications
AcceptEx function and passes the local and remote addresses to a SOCKADDR structure.                device.
GetAclInformation,ADVAPI32.DLL,NM,4, retrieves information about an access-control list             GetCommMask,KERNEL32.DLL,NM,2, retrieves the value of the event mask for a specified
(ACL).                                                                                              communications device.
GetACP,KERNEL32.DLL,NM,0, retrieves the current ANSI code-page identifier for the system.           GetCommModemStatus,KERNEL32.DLL,NM,2, retrieves modem control-register values.
GetActiveObject,OLEAUT32.DLL,NM,3,Retrieves a pointer to a running object that has been             GetCommProperties,KERNEL32.DLL,NM,2 fills a buffer with informationabout the
registered with OLE.                                                                                communications properties for a specified communicationsdevice.
GetActiveWindow,USER32.DLL,NM,0, retrieves the window handle to the active window                   GetCommState,KERNEL32.DLL,NM,2 fills in a device-control block (a DCBstructure) with the
associated with the thread that calls the function.                                                 current control settings for a specifiedcommunications device.
GetAddressByName,MSWSOCK.DLL,AW,10,Important is a Microsoft-specific extension to the               GetCommTimeouts,KERNEL32.DLL,NM,2, retrieves the time-out parameters for all read and
Windows Sockets 1.                                                                                  write operations on a specified communications device.
GetAddressByName,WSOCK32.DLL,AW,10,Important is a Microsoft-specific extension to the               GetCompressedFileSize,KERNEL32.DLL,AW,2, obtains the compressed size of a file.
Windows Sockets 1.                                                                                  GetComputerName,KERNEL32.DLL,AW,2, retrieves the computer name of the current system.
GetAllUsersProfileDirectory,USERENV.DLL,AW,2, retrieves the path to the root of the All Users       GetComputerObjectName,SECUR32.DLL,AW,3, retrieves the local computer's name in a
profile.                                                                                            specified format.
GetAltMonthNames,OLEAUT32.DLL,NM,2,Retrieves the secondary (altername) month names.                 GetConsoleCP,KERNEL32.DLL,NM,0 Windows NT: returns the identity of theinput code page
GetAppliedGPOList,USERENV.DLL,AW,5, retrieves the list of GPOs applied for the specified            used by the console associated with the callingprocess.
user or computer and the specified extension.                                                       GetConsoleCursorInfo,KERNEL32.DLL,NM,2 retrieves information about thesize and visibility
GetArcDirection,GDI32.DLL,NM,1, returns the current arc direction for the specified device          of the cursor for the specified console screenbuffer.
context..                                                                                           GetConsoleMode,KERNEL32.DLL,NM,2 reports the current input mode of aconsole?s input
GetAspectRatioFilterEx,GDI32.DLL,NM,2, retrieves the setting for the current aspect-ratio filter.   buffer or the current output mode of a consolescreen buffer.
GetAsyncKeyState,USER32.DLL,NM,1 determines whether a key is up ordown at the time the              GetConsoleOutputCP,KERNEL32.DLL,NM,0 Windows NT: returns the identity ofthe output
function is called, and whether the key waspressed after a previous call to GetAsyncKeyState.       code page used by the console associated with thecalling process.
GetAtomName,KERNEL32.DLL,AW,3, retrieves a copy of the character string associated with             GetConsoleScreenBufferInfo,KERNEL32.DLL,NM,2, retrieves information about the specified
the specified local atom.                                                                           console screen buffer.
GetAttribIMsgOnIStg,MAPI32.DLL,NM,3, retrieves attributes of properties on an IMessage              GetConsoleTitle,KERNEL32.DLL,AW,2, retrieves the title bar string for the current console
object supplied by the OpenIMsgOnIStg function.                                                     window.
GetAuditedPermissionsFromAcl,ADVAPI32.DLL,AW,4, returns the audited access rights for a             GetConvertStg,OLE32.DLL,NM,1, returns the current value of the convert bit for the specified
specified trustee.                                                                                  storage object.
GetBinaryType,KERNEL32.DLL,AW,2, determines whether a file is executable, and if so, what           GetCountColorProfileElements,MSCMS.DLL,NM,2, retrieves the number of tagged elements in
type of executable file it is.                                                                      a given color profile.
GetBitmapBits,GDI32.DLL,NM,3, is obsolete.                                                          GetCPInfo,KERNEL32.DLL,NM,2, retrieves information about any valid installed or available
GetBitmapDimensionEx,GDI32.DLL,NM,2, retrieves the dimensions of a                                  code page.
SetBitmapDimensionEx function.                                                                      GetCurrencyFormat,KERNEL32.DLL,AW,6, formats a number string as a currency string for a
GetBkColor,GDI32.DLL,NM,1, returns the current background color for the specified device            specified locale.
context.                                                                                            GetCurrentDirectory,KERNEL32.DLL,AW,2 retrieves the current directory for the current
GetBkMode,GDI32.DLL,NM,1, returns the current background mix mode for a specified device            process.
context.                                                                                            GetCurrentHwProfile,ADVAPI32.DLL,AW,1, retrieves the display name and globally unique
GetBoundsRect,GDI32.DLL,NM,3 obtains the current accumulated bounding rectangle for a               identifier (GUID) string for the hardware profile.
specified device context.                                                                           GetCurrentObject,GDI32.DLL,NM,2, obtains a handle to a device context? s currently selected
GetBrushOrgEx,GDI32.DLL,NM,2, retrieves the current brush origin for the specified device           object of a specified type.
context.                                                                                            GetCurrentPositionEx,GDI32.DLL,NM,2, retrieves the current position in logical coordinates.
GetCapture,USER32.DLL,NM,0, retrieves the handle of the window (if any) that has captured           GetCurrentProcess,KERNEL32.DLL,NM,0, returns a pseudohandle for the current process.
the mouse.                                                                                          GetCurrentProcessId,KERNEL32.DLL,NM,0, returns the process identifier of the calling
GetCaretBlinkTime,USER32.DLL,NM,0, returns the elapsed time, in milliseconds, required to           process.
invert the caret?s pixels.                                                                          GetCurrentThread,KERNEL32.DLL,NM,0, returns a pseudohandle for the current thread.
GetCaretPos,USER32.DLL,NM,1, copies the caret?s position, in client coordinates, to the             GetCurrentThreadId,KERNEL32.DLL,NM,0, returns the thread identifier of the calling thread.
specified POINT structure.                                                                          GetCursor,USER32.DLL,NM,0, retrieves the handle of the current cursor.
GetCharABCWidths,GDI32.DLL,AW,4 retrieves the widths, in logicalunits, of consecutive               GetCursorPos,USER32.DLL,NM,1, retrieves the cursor?s position, in screen coordinates.
characters in a given range from the currentTrueType font.                                          GetDateFormat,KERNEL32.DLL,AW,6 formats a date as a date string for a specified locale.
GetCharABCWidthsFloat,GDI32.DLL,AW,4 retrieves the widths, in logicalunits, of consecutive          GetDC,USER32.DLL,NM,1, retrieves a handle of a display device context (DC) for the client
characters in a specified range from thecurrent font.                                               area of the specified window.
GetCharacterPlacement,GDI32.DLL,AW,6 retrieves information about a character string, such           GetDCEx,USER32.DLL,NM,3, retrieves the handle of a display device (DC) context for the
as character widths, caret positioning, ordering within the string, and glyph rendering.            specified window.
GetCharWidth,GDI32.DLL,AW,4 retrieves the widths, in logicalcoordinates, of consecutive             GetDCOrgEx,GDI32.DLL,NM,2, obtains the final translation origin for a specified device context
characters in a specified range fromthe current font.                                               (DC).
GetCharWidth32,GDI32.DLL,AW,4 retrieves the widths, in logicalcoordinates, of consecutive           GetDefaultCommConfig,KERNEL32.DLL,AW,3, gets the default configuration for a
characters in a specified range fromthe current font.                                               communications device.
GetCharWidthFloat,GDI32.DLL,AW,4, retrieves the fractional widths of consecutive characters         GetDefaultUserProfileDirectory,USERENV.DLL,AW,2, retrieves the path to the root of the
in a specified range from the current font.                                                         Default User profile.
GetClassFile,OLE32.DLL,NM,2,OrMime Retrieves the CLSID of the object to instantiate for the         GetDesktopWindow,USER32.DLL,NM,0, returns the handle of the Windows desktop window.
specified file.                                                                                     GetDeviceCaps,GDI32.DLL,NM,2, retrieves device-specific information about a specified
GetClassFileOrMime,URLMON.DLL,NM,7, Retrieves the CLSID of the object to instantiate for            device.
the specified file.                                                                                 GetDeviceDriverBaseName,PSAPI.DLL,AW,3, retrieves the base name of the specified device
GetClassInfo,USER32.DLL,AW,3, retrieves information about a window class.                           driver.
GetClassInfoEx,USER32.DLL,AW,3 retrieves information about a windowclass, including the             GetDeviceDriverFileName,PSAPI.DLL,AW,3, retrieves the fully qualified path for the specified
handle of the small icon associated with thewindow class.                                           device driver.
GetClassLong,USER32.DLL,AW,2 retrieves the specified 32-bit (long)value from the                    GetDialogBaseUnits,USER32.DLL,NM,0 returns the system's dialog baseunits, which are the
WNDCLASSEX structure associated with the specifiedwindow.                                           average width and height of characters in thesystem font.
GetClassName,USER32.DLL,AW,3, retrieves the name of the class to which the specified                GetDIBColorTable,GDI32.DLL,NM,4 retrieves RGB (red, green, blue) color values from a range
window belongs.                                                                                     of entries in the color table of the DIB section bitmap that is currently selected into a specified
GetClassURL,URLMON.DLL,NM,2, GetClassURL Function Not currently implemented.                        device context.
GetClassWord,USER32.DLL,NM,2 retrieves the 16-bit (word) value at thespecified offset into          GetDIBits,GDI32.DLL,NM,7, retrieves the bits of the specified bitmap and copies them into a
the extra class memory for the window classto which the specified window belongs.                   buffer using the specified format.
GetClientRect,USER32.DLL,NM,2 retrieves the coordinates of a window?s client area.                  GetDiskFreeSpace,KERNEL32.DLL,AW,5, retrieves information about the specified disk,
GetClipboardData,USER32.DLL,NM,1, retrieves data from the clipboard in a specified format.          including the amount of free space on the disk.
GetClipboardFormatName,USER32.DLL,AW,3, retrieves from the clipboard the name of the                GetDiskFreeSpaceEx,KERNEL32.DLL,AW,4, lets you avoid the arithmetic required by the
specified registered format.                                                                        GetDiskFreeSpace function.
GetClipboardOwner,USER32.DLL,NM,0, retrieves the window handle of the current owner of              GetDlgCtrlID,USER32.DLL,NM,1, returns the identifier of the specified control.
the clipboard.                                                                                      GetDlgItem,USER32.DLL,NM,2, retrieves the handle of a control in the specified dialog box.
GetClipboardSequenceNumber,USER32.DLL,NM,0, returns the clipboard sequence number for               GetDlgItemInt,USER32.DLL,NM,4, translates the text of a specified control in a dialog box into
the current window station.                                                                         an integer value.
GetClipboardViewer,USER32.DLL,NM,0, retrieves the handle of the first window in the                 GetDlgItemText,USER32.DLL,AW,4, retrieves the title or text associated with a control in a
clipboard viewer chain.                                                                             dialog box.
GetClipBox,GDI32.DLL,NM,2 retrieves the dimensions of the tightestbounding rectangle that           GetDoubleClickTime,USER32.DLL,NM,0, retrieves the current double-click time for the mouse.
can be drawn around the current visiblearea on the device.                                          GetDriveType,KERNEL32.DLL,AW,1, determines whether a disk drive is a removable, fixed,
GetClipCursor,USER32.DLL,NM,1, retrieves the screen coordinates of the rectangular area to          CD-ROM, RAM disk, or network drive.
which the cursor is confined.                                                                       GetEffectiveClientRect,COMCTL32.DLL,NM,3, calculates the dimensions of a rectangle in the
GetClipRgn,GDI32.DLL,NM,2 retrieves a handle identifying the currentapplication-defined             client area.
clipping region for the specified devicecontext.                                                    GetEffectiveRightsFromAcl,ADVAPI32.DLL,AW,3, retrieves the effective access rights that an
GetCMMInfo,MSCMS.DLL,NM,2, retrieves various information about the color management                 ACL allows for a specified trustee.
module (CMM) that created the specified color transform.                                            GetEnhMetaFile,GDI32.DLL,AW,1, creates a handle that identifies the enhanced-format
GetColorAdjustment,GDI32.DLL,NM,2 retrieves the color adjustmentvalues for the specified            metafile stored in the specified file.
device context.                                                                                     GetEnhMetaFileBits,GDI32.DLL,NM,3, retrieves the contents of the specified enhanced-format
GetColorDirectory,MSCMS.DLL,AW,3, retrieves the path of the Windows COLOR directory on              metafile and copies them into a buffer.
a specified machine.                                                                                GetEnhMetaFileDescription,GDI32.DLL,AW,3 retrieves an optional textdescription from an
GetColorProfileElement,MSCMS.DLL,NM,6, copies data from a specified tagged profile                  enhanced-format metafile and copies the stringto the specified buffer.
element of a specified color profile into a buffer.                                                 GetEnhMetaFileHeader,GDI32.DLL,NM,3 retrieves the record containing the header for the
GetColorProfileElementTag,MSCMS.DLL,NM,3, retrieves the tag name specified by dwIndex in            specified enhanced-format metafile.
the tag table of a given color profile, where dwIndex is a one-based index into that table.         GetEnhMetaFilePaletteEntries,GDI32.DLL,NM,3, retrieves optional palette entries from the
                                                                                                    specified enhanced metafile.
                                                                                            130
GetEnvironmentStrings,KERNEL32.DLL,AW,0, returns the address of the environment block for         GetMenuCheckMarkDimensions,USER32.DLL,NM,0, returns the dimensions of the default
the current process.                                                                              check mark bitmap.
GetEnvironmentVariable,KERNEL32.DLL,AW,3 retrieves the value of thespecified variable from        GetMenuContextHelpId,USER32.DLL,NM,1, retrieves the help context identifier associated with
the environment block of the callingprocess.                                                      the specified menu.
GetErrorInfo,OLEAUT32.DLL,NM,2,Obtains the error information pointer set by the previous          GetMenuDefaultItem,USER32.DLL,NM,3 determines the default menu item on the specified
call to SetErrorInfo in the current logical thread.                                               menu.
GetExitCodeProcess,KERNEL32.DLL,NM,2 retrieves the termination status ofthe specified             GetMenuItemCount,USER32.DLL,NM,1, determines the number of items in the specified menu.
process.                                                                                          GetMenuItemID,USER32.DLL,NM,2, retrieves the menu item identifier of a menu item located
GetExitCodeThread,KERNEL32.DLL,NM,2, retrieves the termination status of the specified            at the specified position in a menu.
thread.                                                                                           GetMenuItemInfo,USER32.DLL,AW,4, retrieves information about a menu item.
GetExpandedName,LZ32.DLL,AW,2 retrieves the original name of acompressed file, if the file        GetMenuItemRect,USER32.DLL,NM,4, retrieves the bounding rectangle for the specified menu
was compressed by using the MicrosoftFile Compression Utility (COMPRESS.                          item.
GetExplicitEntriesFromAcl,ADVAPI32.DLL,AW,3 retrieves an array ofEXPLICIT_ACCESS                  GetMenuState,USER32.DLL,NM,3 retrieves the menu flags associated with the specified menu
structures that describe the access-control entries(ACEs) in an access-control list (ACL).        item.
GetFileAttributes,KERNEL32.DLL,AW,1, returns attributes for a specified file or directory.        GetMenuString,USER32.DLL,AW,5, copies the text string of the specified menu item into the
GetFileAttributesEx,KERNEL32.DLL,AW,3, obtains attribute information about a specified file or    specified buffer.
directory.                                                                                        GetMessage,USER32.DLL,AW,4, retrieves a message from the calling thread?s message
GetFileInformationByHandle,KERNEL32.DLL,NM,2, retrieves information about a specified file.       queue and places it in the specified structure.
GetFileSecurity,ADVAPI32.DLL,AW,5, obtains specified information about the security of a file     GetMessageExtraInfo,USER32.DLL,NM,0, gets the extra message information for the current
or directory.                                                                                     thread.
GetFileSize,KERNEL32.DLL,NM,2, retrieves the size, in bytes, of the specified file.               GetMessagePos,USER32.DLL,NM,0, returns a long value that gives the cursor position in
GetFileTime,KERNEL32.DLL,NM,4, retrieves the date and time that a file was created, last          screen coordinates.
accessed, and last modified.                                                                      GetMessageTime,USER32.DLL,NM,0 returns the message time for the lastmessage retrieved
GetFileTitle,COMDLG32.DLL,AW,3, returns the name of the file identified by the lpszFile           by the GetMessage function from the currentthread?s message queue.
parameter.                                                                                        GetMetaFile,GDI32.DLL,AW,1, creates a handle that identifies the given Windows-format
GetFileType,KERNEL32.DLL,NM,1 returns the type of the specified file.                             metafile.
GetFileVersionInfo,VERSION.DLL,AW,4, returns version information about a specified file.          GetMetaFileBitsEx,GDI32.DLL,NM,3, retrieves the contents of a Windows- format metafile and
GetFileVersionInfoSize,VERSION.DLL,AW,2 determines whether operating system can obtain            copies them into the specified buffer.
version information about a specifiedfile.                                                        GetMetaRgn,GDI32.DLL,NM,2, retrieves the current metaregion for the specified device
GetFocus,USER32.DLL,NM,0 retrieves the handle of the window that hasthe keyboard focus, if        context.
the window is associated with the callingthread?s message queue.                                  GetMiterLimit,GDI32.DLL,NM,2, returns the miter limit for the specified device context.
GetFontData,GDI32.DLL,NM,5, retrieves font metric data for a TrueType font.                       GetModuleBaseName,PSAPI.DLL,AW,4, retrieves the base name of the specified module.
GetFontLanguageInfo,GDI32.DLL,NM,1, returns information about the currently selected font         GetModuleFileName,KERNEL32.DLL,AW,3, retrieves the full path and filename for the
for the specified display context.                                                                executable file containing the specified module.
GetForegroundWindow,USER32.DLL,NM,0 returns the handle of theforeground window (the               GetModuleFileNameEx,PSAPI.DLL,AW,4, retrieves the fully-qualified path for the file containing
window with which the user is currentlyworking).                                                  the specified module.
GetForm,WINMM.DLL,AW,6, initializes a FORM_INFO_1 structure with data describing the              GetModuleHandle,KERNEL32.DLL,AW,1 returns a module handle for thespecified module if
specified form for a printer.                                                                     the file has been mapped into the address spaceof the calling process.
GetFullPathName,KERNEL32.DLL,AW,4, retrieves the full path and filename of a specified file.      GetModuleInformation,PSAPI.DLL,NM,4, retrieves information about the specified module in
GetGlyphOutline,GDI32.DLL,AW,7 retrieves the outline or bitmap for acharacter in the              the MODULEINFO structure.
TrueType font that is selected into the specifieddevice context.                                  GetMonitorInfo,USER32.DLL,AW,2, lets you obtain information about a display monitor.
GetGPOList,USERENV.DLL,AW,6, retrieves the list of GPOs for the specified user or                 GetMultipleTrustee,ADVAPI32.DLL,AW,1, is provided for future use.
computer.                                                                                         GetMultipleTrusteeOperation,ADVAPI32.DLL,AW,1, is provided for future use.
GetGraphicsMode,GDI32.DLL,NM,1, retrieves the current graphics mode for the specified             GetNameByType,MSWSOCK.DLL,AW,3, obtains the name of a network service.
device context.                                                                                   GetNameByType,WSOCK32.DLL,AW,3, obtains the name of a network service.
GetGuiResources,USER32.DLL,NM,2 returns the count of handles to graphical user interface          GetNamedPipeHandleState,KERNEL32.DLL,AW,7 GetNamedPipeHandleStatespecified
(GUI) objects in use by the specified process.                                                    named pipe.
GetHandleInformation,KERNEL32.DLL,NM,2, obtains information about certain properties of an        GetNamedPipeInfo,KERNEL32.DLL,NM,5, retrieves information about the specified named
object handle.                                                                                    pipe.
GetHGlobalFromILockBytes,OLE32.DLL,NM,2, retrieves a global memory handle to a byte               GetNamedSecurityInfo,ADVAPI32.DLL,AW,8, retrieves a copy of the security descriptor for an
array object created using the CreateILockBytesOnHGlobal function.                                object specified by name.
GetHGlobalFromStream,OLE32.DLL,NM,2, This function retrieves the global memory handle to          GetNearestColor,GDI32.DLL,NM,2 returns a color value identifying acolor from the system
a stream that was created through a call to the CreateStreamOnHGlobal function.                   palette that will be displayed when thespecified color value is used.
gethostbyaddr,WS2_32.DLL,NM,3 retrieves the host information corresponding to a network           GetNearestPaletteIndex,GDI32.DLL,NM,2 retrieves the index for theentry in the specified
address.                                                                                          logical palette most closely matching aspecified color value.
gethostbyaddr,WSOCK32.DLL,NM,3 retrieves the hostinformation corresponding to a network           GetNextDlgGroupItem,USER32.DLL,NM,3 retrieves the handle of the firstcontrol in a group of
address.                                                                                          controls that precedes (or follows) thespecified control in a dialog box.
gethostbyname,WS2_32.DLL,NM,1, retrieves host information corresponding to a host name            GetNextDlgTabItem,USER32.DLL,NM,3 retrieves the handle of the firstcontrol that has the
from a host database.Note The gethostbyname function has been deprecated by the                   WS_TABSTOP style that precedes (or follows)the specified control.
introduction of the getaddrinfo function.                                                         GetNtmsMediaPoolName,NTMSAPI.DLL,AW,4, retrieves the specified media pool's full name
gethostbyname,WSOCK32.DLL,NM,1, retrieves host information corresponding to a host name           hierarchy.
from a host database.Note The gethostbyname function has been deprecated by the                   GetNtmsObjectAttribute,NTMSAPI.DLL,AW,6, retrieves the extended attribute (named private
introduction of the getaddrinfo function.                                                         data) from the specified RSM object.
gethostname,WS2_32.DLL,NM,2, retrieves the standard host name for the local computer.             GetNtmsObjectInformation,NTMSAPI.DLL,AW,3, returns an object's information structure for
gethostname,WSOCK32.DLL,NM,2, retrieves the standard host name for the local computer.            the specified object.
GetIconInfo,USER32.DLL,NM,2, retrieves information about the specified icon or cursor.            GetNtmsObjectSecurity,NTMSAPI.DLL,NM,7, reads the security descriptor for the specified
GetImageConfigInformation,IMAGEHLP.DLL,NM,2, locates and returns the load configuration           RSM object.
data of an image.                                                                                 GetNtmsRequestOrder,NTMSAPI.DLL,NM,3, gets the order that the specified request will be
GetImageUnusedHeaderBytes,IMAGEHLP.DLL,NM,2, returns the offset and size of the part of           processed in the library queue.
the PE header that is currently unused.                                                           GetNumberFormat,KERNEL32.DLL,AW,6, formats a number string as a number string
GetInputState,USER32.DLL,NM,0, determines whether there are mouse- button or keyboard             customized for a specified locale.
messages in the calling thread?s message queue.                                                   GetNumberOfConsoleInputEvents,KERNEL32.DLL,NM,2, retrieves the number of unread input
GetJob,WINMM.DLL,AW,6, retrieves print-job data for the specified printer.                        records in the console?s input buffer.
GetKBCodePage,USER32.DLL,NM,0 returns the current Windows code page.                              GetNumberOfConsoleMouseButtons,KERNEL32.DLL,NM,1, retrieves the number of buttons on
GetKernelObjectSecurity,ADVAPI32.DLL,NM,5, retrieves a copy of the security descriptor            the mouse used by the current console.
protecting a kernel object.                                                                       GetNumberOfEventLogRecords,ADVAPI32.DLL,NM,2 retrieves the number of records in the
GetKerningPairs,GDI32.DLL,AW,3, retrieves the character-kerning pairs for the currently           specified event log.
selected font for the specified device context.                                                   GetObject,GDI32.DLL,AW,3 obtains information about a specified graphics object.
GetKeyboardLayout,USER32.DLL,NM,1, retrieves the active keyboard layout for a specified           GetObjectType,GDI32.DLL,NM,1 identifies the type of the specified object.
thread.                                                                                           GetOEMCP,KERNEL32.DLL,NM,0, retrieves the current OEM code-page identifier for the
GetKeyboardLayoutList,USER32.DLL,NM,2 retrieves the keyboard layouthandles                        system.
corresponding to the current set of input locales in thesystem.                                   GetOldestEventLogRecord,ADVAPI32.DLL,NM,2, retrieves the absolute record number of the
GetKeyboardLayoutName,USER32.DLL,AW,1, retrieves the name of the active keyboard                  oldest record in the specified event log.
layout.                                                                                           GetOpenClipboardWindow,USER32.DLL,NM,0, retrieves the handle of the window that
GetKeyboardState,USER32.DLL,NM,1 copies the status of the 256 virtual keys to the specified       currently has the clipboard open.
buffer.                                                                                           GetOpenFileName,COMDLG32.DLL,AW,1 creates an Open common dialog box thatlets the
GetKeyboardType,USER32.DLL,NM,1, retrieves information about the current keyboard.                user specify the drive, directory, and the name of a fileor set of files to open.
GetKeyNameText,USER32.DLL,AW,3, retrieves a string that represents the name of a key.             GetOpenFileNamePreview,MSVFW32.DLL,AW,1, selects a file by using the Open dialog box.
GetKeyState,USER32.DLL,NM,1, retrieves the status of the specified virtual key.                   GetOutlineTextMetrics,GDI32.DLL,AW,3, retrieves text metrics for TrueType fonts.
GetLargestConsoleWindowSize,KERNEL32.DLL,NM,1 returns the size of thelargest possible             GetOverlappedResult,KERNEL32.DLL,NM,4 returns the results of anoverlapped operation on
console window, based on the current font and thesize of the display.                             the specified file, named pipe, orcommunications device.
GetLastActivePopup,USER32.DLL,NM,1, determines which pop-up window owned by the                   GetPaletteEntries,GDI32.DLL,NM,4, retrieves a specified range of palette entries from the given
specified window was most recently active.                                                        logical palette.
GetLastError,KERNEL32.DLL,NM,0, returns the calling thread?s last-error code value.               GetParent,USER32.DLL,NM,1, retrieves the handle of the specified child window?s parent
GetLengthSid,ADVAPI32.DLL,NM,1, returns the length, in bytes, of a valid SID structure.           window.
GetLocaleInfo,KERNEL32.DLL,AW,4, always retrieves information in text format.                     GetPath,GDI32.DLL,NM,4 retrieves the coordinates defining theendpoints of lines and the
GetLocalTime,KERNEL32.DLL,NM,1 retrieves the current local date and time.                         control points of curves found in thepath that is selected into the specified device context.
GetLogicalDrives,KERNEL32.DLL,NM,0, returns a bitmask representing the currently available        getpeername,WS2_32.DLL,NM,3 retrieves the name of thepeer to which a socket is connected.
disk drives.                                                                                      getpeername,WSOCK32.DLL,NM,3 retrieves the name of thepeer to which a socket is
GetLogicalDriveStrings,KERNEL32.DLL,AW,2, fills a buffer with strings that specify valid drives   connected.
in the system.                                                                                    GetPixel,GDI32.DLL,NM,3, retrieves the red, green, blue (RGB) color value of the pixel at the
GetMailslotInfo,KERNEL32.DLL,NM,5, retrieves information about the specified mailslot.            specified coordinates.
GetMapMode,GDI32.DLL,NM,1 retrieves the current mapping mode.                                     GetPixelFormat,GDI32.DLL,NM,1, obtains the index of the currently selected pixel format of the
GetMappedFileName,PSAPI.DLL,AW,4, checks if the specified address is within a memory-             specified device context.
mapped file in the address space of the specified process. If so, the function returns the name   GetPolyFillMode,GDI32.DLL,NM,1, retrieves the current polygon fill mode.
of the memory-mapped file.                                                                        GetPrinter,WINMM.DLL,AW,5, retrieves information about a specified printer.
GetMenu,USER32.DLL,NM,1, retrieves the handle of the menu assigned to the given window.           GetPrinterData,WINMM.DLL,AW,6, retrieves printer-configuration data for the specified printer.
                                                                                                  GetPrinterDriver,WINMM.DLL,AW,6, retrieves driver data for the specified printer.
                                                                                           131
GetPrinterDriverDirectory,WINMM.DLL,AW,6, retrieves the path of the printer-driver directory.    GetSidIdentifierAuthority,ADVAPI32.DLL,NM,1 returns the address of
GetPrintProcessorDirectory,WINMM.DLL,AW,6, retrieves the path for the print processor on the     theSID_IDENTIFIER_AUTHORITY structure in a specified securityidentifier (SID).
specified server.                                                                                GetSidLengthRequired,ADVAPI32.DLL,NM,1 returns the length, in bytes, ofthe buffer required
GetPriorityClass,KERNEL32.DLL,NM,1, returns the priority class for the specified process.        to store a SID structure with a specifiednumber of subauthorities.
GetPriorityClipboardFormat,USER32.DLL,NM,2, returns the first available clipboard format in      GetSidSubAuthority,ADVAPI32.DLL,NM,2, returns the address of a specified subauthority in a
the specified list.                                                                              SID structure.
GetPrivateObjectSecurity,ADVAPI32.DLL,NM,5 retrieves information from a protectedserver          GetSidSubAuthorityCount,ADVAPI32.DLL,NM,1, returns the address of the field in a SID
object?s security descriptor.                                                                    structure containing the subauthority count.
GetPrivateProfileInt,KERNEL32.DLL,AW,4 retrieves an integer associatedwith a key in the          getsockname,WS2_32.DLL,NM,3, retrieves the current name for the specified socket descriptor
specified section of the given initializationfile.                                               in name.
GetPrivateProfileSection,KERNEL32.DLL,AW,4, retrieves all of the keys and values for the         getsockname,WSOCK32.DLL,NM,3, retrieves the current name for the specified socket
specified section from an initialization file.                                                   descriptor in name.
GetPrivateProfileSectionNames,KERNEL32.DLL,AW,3, retrieves the names of all sections in          getsockopt,WS2_32.DLL,NM,5 retrieves a socket option.
an initialization file.                                                                          getsockopt,WSOCK32.DLL,NM,5 retrieves a socket option.
GetPrivateProfileString,KERNEL32.DLL,AW,6, retrieves a string from the specified section in      GetStandardColorSpaceProfile,MSCMS.DLL,AW,4, retrieves the color profile registered for the
an initialization file.                                                                          specified standard color space.
GetPrivateProfileStruct,KERNEL32.DLL,AW,5 retrieves the data associated with the specified       GetStartupInfo,KERNEL32.DLL,AW,1 retrieves the contents of the STARTUPINFO structure
key in the given section of an initialization file.                                              that was specified when the calling process was created.
GetProcAddress,KERNEL32.DLL,NM,2, returns the address of the specified exported dynamic-         GetStdHandle,KERNEL32.DLL,NM,1, returns a handle for the standard input, standard output,
link library (DLL) function.                                                                     or standard error device.
GetProcessAffinityMask,KERNEL32.DLL,NM,3 obtains a process affinity mask for the specified       GetStockObject,GDI32.DLL,NM,1, retrieves a handle to one of the predefined stock pens,
process and the system affinity mask for the system.                                             brushes, fonts, or palettes.
GetProcessHeap,KERNEL32.DLL,NM,0, obtains a handle to the heap of the calling process.           GetStretchBltMode,GDI32.DLL,NM,1, retrieves the current stretching mode.
GetProcessMemoryInfo,PSAPI.DLL,NM,3, retrieves information about the memory usage of the         GetStringType,KERNEL32.DLL,AW,5 returns character-type information for the characters in
specified process in the PROCESS_MEMORY_COUNTERS structure.                                      the specified source string.
GetProcessPriorityBoost,KERNEL32.DLL,NM,2, returns the priority boost control state of the       GetStringTypeEx,KERNEL32.DLL,AW,5, returns character-type information for the characters
specified process.                                                                               in the specified source string.
GetProcessShutdownParameters,KERNEL32.DLL,NM,2, retrieves shutdown parameters for                GetSubMenu,USER32.DLL,NM,2, retrieves the handle of the drop-down menu or submenu
the currently calling process.                                                                   activated by the specified menu item.
GetProcessTimes,KERNEL32.DLL,NM,5, obtains timing information about a specified process.         GetSysColor,USER32.DLL,NM,1, retrieves the current color of the specified display element.
GetProcessVersion,KERNEL32.DLL,NM,1 obtains the major and minor versionnumbers of the            GetSysColorBrush,USER32.DLL,NM,1, retrieves a handle identifying a logical brush that
Windows version on which a specified process expectsto run.                                      corresponds to the specified color index.
GetProcessWindowStation,USER32.DLL,NM,0, returns a handle of the window station                  GetSystemDefaultLangID,KERNEL32.DLL,NM,0, retrieves the system default language
associated with the calling process.                                                             identifier.
GetProcessWorkingSetSize,KERNEL32.DLL,NM,3, obtains the minimum and maximum                      GetSystemDefaultLCID,KERNEL32.DLL,NM,0, retrieves the system default locale identifier.
working set sizes of a specified process.                                                        GetSystemDirectory,KERNEL32.DLL,AW,2, retrieves the path of the Windows system
GetProfileInt,KERNEL32.DLL,AW,3, retrieves an integer from the specified key name in the         directory.
given section of the WIN.                                                                        GetSystemInfo,KERNEL32.DLL,NM,1, returns information about the current system.
GetProfilesDirectory,USERENV.DLL,AW,2, retrieves the path to the root directory where all        GetSystemMenu,USER32.DLL,NM,2 allows the application to access thewindow menu (also
user profiles are stored.                                                                        known as the System menu or the Control menu) forcopying and modifying.
GetProfileSection,KERNEL32.DLL,AW,3, retrieves all of the keys and values for the specified      GetSystemMetrics,USER32.DLL,NM,1, retrieves various system metrics and system
section of the WIN.                                                                              configuration settings.
GetProfileString,KERNEL32.DLL,AW,5, retrieves the string associated with the specified key in    GetSystemPaletteEntries,GDI32.DLL,NM,4 retrieves a range of palette entries from the system
the given section of the WIN.                                                                    palette that is associated with the specified device context.
GetProfileType,USERENV.DLL,NM,1, retrieves the type of profile loaded for the current user.      GetSystemPaletteUse,GDI32.DLL,NM,1, retrieves the current state of the system (physical)
GetProp,USER32.DLL,AW,2, retrieves a data handle from the property list of the given window.     palette for the specified device context.
getprotobyname,WS2_32.DLL,NM,1 information corresponding to a protocol name.                     GetSystemPowerStatus,KERNEL32.DLL,NM,1 retrieves the power status of the system.
getprotobyname,WSOCK32.DLL,NM,1 information corresponding to a protocol name.                    GetSystemTime,KERNEL32.DLL,NM,1, retrieves the current system date and time.
getprotobynumber,WS2_32.DLL,NM,1 getprotobynumberretrieves protocolinformation                   GetSystemTimeAdjustment,KERNEL32.DLL,NM,3 determines whether the system is applying
corresponding to a protocol number.                                                              periodic time adjustments to its time-of-day clock at each clock interrupt, along with the value
getprotobynumber,WSOCK32.DLL,NM,1 retrieves protocolinformation corresponding to a               and period of any such adjustments.
protocol number.                                                                                 GetSystemTimeAsFileTime,KERNEL32.DLL,NM,1, obtains the current system date and time.
GetPS2ColorRenderingDictionary,MSCMS.DLL,NM,5, retrieves the PostScript Level 2 color            GetTapeParameters,KERNEL32.DLL,NM,4, retrieves information that describes the tape or the
rendering dictionary from the specified profile.                                                 tape drive.
GetPS2ColorRenderingIntent,MSCMS.DLL,NM,4, retrieves the PostScript Level 2 color                GetTapePosition,KERNEL32.DLL,NM,5, retrieves the current address of the tape, in logical or
rendering intent from a profile.                                                                 absolute blocks.
GetPS2ColorSpaceArray,MSCMS.DLL,NM,6, retrieves the PostScript Level 2 color space array         GetTapeStatus,KERNEL32.DLL,NM,1, indicates whether the tape device is ready to process
from a profile.                                                                                  tape commands.
GetQueuedCompletionStatus,KERNEL32.DLL,NM,5, attempts to dequeue an I/O completion               GetTempFileName,KERNEL32.DLL,AW,4, creates a name for a temporary file.
packet from a specified input/output completion port.                                            GetTempPath,KERNEL32.DLL,AW,2, retrieves the path of the directory designated for
GetQueueStatus,USER32.DLL,NM,1, returns flags that indicate the type of messages found in        temporary files.
the calling thread?s message queue.                                                              GetTextAlign,GDI32.DLL,NM,1, retrieves the text the specified device context.
GetRasterizerCaps,GDI32.DLL,NM,2, returns flags indicating whether TrueType fonts are            GetTextCharacterExtra,GDI32.DLL,NM,1, retrieves the current intercharacter spacing for the
installed in the system.                                                                         specified device context.
GetRegionData,GDI32.DLL,NM,3, fills the specified buffer with data describing a region.          GetTextCharset,GDI32.DLL,NM,1 obtains a character-set identifier forthe font that is currently
GetRgnBox,GDI32.DLL,NM,2, retrieves the bounding rectangle of the specified region.              selected into a specified devicecontext.
GetROP2,GDI32.DLL,NM,1, retrieves the foreground mix mode of the specified device context.       GetTextColor,GDI32.DLL,NM,1, retrieves the current text color for the specified device context.
GetSaveFileName,COMDLG32.DLL,AW,1 creates a Save common dialog box that lets the user            GetTextExtentExPoint,GDI32.DLL,AW,7 retrieves the number of characters in a specified string
specify the drive, directory, and name of a file to save.                                        that will fit within a specified space and fills an array with the text extent for each of those
GetSaveFileNamePreview,MSVFW32.DLL,AW,1 selects a file by using the SaveAs dialog box.           characters.
GetScrollInfo,USER32.DLL,NM,3 retrieves the parameters of a scrollbar, including the minimum     GetTextExtentPoint,GDI32.DLL,AW,4, computes the width and height of the specified string of
and maximum scrolling positions, thepage size, and the position of the scroll box (thumb).       text.
GetScrollPos,USER32.DLL,NM,2, retrieves the current position of the scroll box (thumb) in the    GetTextExtentPoint32,GDI32.DLL,AW,4, computes the width and height of the specified string
specified scroll bar.                                                                            of text.
GetScrollRange,USER32.DLL,NM,4 retrieves the current minimum and maximum scroll box              GetTextFace,GDI32.DLL,AW,3, retrieves the typeface name of the font that is selected into the
(thumb) positions for the specified scroll bar                                                   specified device context.
GetSecurityDescriptorControl,ADVAPI32.DLL,NM,3 retrieves a securitydescriptor?s control          GetTextMetrics,GDI32.DLL,AW,2 fills the specified buffer with the,metrics for the currently
and revision information.                                                                        selected font.
GetSecurityDescriptorDacl,ADVAPI32.DLL,NM,4 retrieves a pointer to thediscretionary access-      GetThreadContext,KERNEL32.DLL,NM,2, retrieves the context of the specified thread.
control list (ACL) in a specified securitydescriptor.                                            GetThreadDesktop,USER32.DLL,NM,1, returns a handle to the desktop associated with a
GetSecurityDescriptorGroup,ADVAPI32.DLL,NM,3, retrieves the primary group information            specified thread.
from a security descriptor.                                                                      GetThreadLocale,KERNEL32.DLL,NM,0, returns the calling thread?s current locale.
GetSecurityDescriptorLength,ADVAPI32.DLL,NM,1, returns the length, in bytes, of a structurally   GetThreadPriority,KERNEL32.DLL,NM,1, returns the priority value for the specified thread.
valid SECURITY_DESCRIPTOR structure.                                                             GetThreadPriorityBoost,KERNEL32.DLL,NM,2, returns the priority boost control state of the
GetSecurityDescriptorOwner,ADVAPI32.DLL,NM,3, retrieves the owner information from a             specified thread.
security descriptor.                                                                             GetThreadSelectorEntry,KERNEL32.DLL,NM,3, retrieves a descriptor table entry for the
GetSecurityDescriptorSacl,ADVAPI32.DLL,NM,4 retrieves a pointer to thesystem access-             specified selector and thread.
control list (ACL) in a specified securitydescriptor.                                            GetThreadTimes,KERNEL32.DLL,NM,5, obtains timing information about a specified thread.
GetSecurityInfo,ADVAPI32.DLL,NM,8 retrieves a copy of the security descriptor for an object      GetTickCount,KERNEL32.DLL,NM,0 retrieves the number of milliseconds that have elapsed
specified by a handle.                                                                           since Windows was started.
getservbyname,WS2_32.DLL,NM,2 getservbynameinformation corresponding to a service                GetTimeFormat,KERNEL32.DLL,AW,6, formats a time as a time string for a specified locale.
name and protocol.                                                                               GetTimestampForLoadedLibrary,IMAGEHLP.DLL,NM,1, returns the timestamp of a loaded
getservbyname,WSOCK32.DLL,NM,2 information corresponding to a service name and                   image.
protocol.                                                                                        GetTimeZoneInformation,KERNEL32.DLL,NM,1, retrieves the current time-zone parameters.
getservbyport,WS2_32.DLL,NM,2, retrieves service information corresponding to a port and         GetTokenInformation,ADVAPI32.DLL,NM,5, retrieves a specified type of information about an
protocol.                                                                                        access token.
getservbyport,WSOCK32.DLL,NM,2, retrieves service information corresponding to a port and        GetTopWindow,USER32.DLL,NM,1 examines the Z order of the child windows associated with
protocol.                                                                                        the specified parent window and retrieves the handle of the child window at the top of the Z
GetService,MSWSOCK.DLL,AW,7,Important is a Microsoft-specific extension to the Windows           order.
Sockets 1.                                                                                       GetTrusteeName,ADVAPI32.DLL,AW,1, retrieves the trustee name from a TRUSTEE structure.
GetService,WSOCK32.DLL,AW,7,Important is a Microsoft-specific extension to the Windows           GetTrusteeType,ADVAPI32.DLL,AW,1, retrieves the value assigned to the TrusteeType
Sockets 1.                                                                                       member of a specified TRUSTEE structure.
GetServiceDisplayName,ADVAPI32.DLL,AW,4 obtains the display name that is associated with         GetTypeByName,MSWSOCK.DLL,AW,2,Important is a Microsoft-specific extension to the
a particular service. .                                                                          Windows Sockets 1.
GetServiceKeyName,ADVAPI32.DLL,AW,4, obtains the service name that is associated with a          GetTypeByName,WSOCK32.DLL,AW,2,Important is a Microsoft-specific extension to the
particular service?s display name.                                                               Windows Sockets 1.
GetShortPathName,KERNEL32.DLL,AW,3, obtains the short path form of a specified input             GetUpdateRect,USER32.DLL,NM,3 retrieves the coordinates of thesmallest rectangle that
path.                                                                                            completely encloses the update region ofthe specified window.
                                                                                           132
GetUpdateRgn,USER32.DLL,NM,3, retrieves the update region of a window by copying it into         glColor3iv,OPENGL32.DLL,NM,1 set the current color
the specified region.                                                                            glColor3s,OPENGL.DLL,NM,3 set the current color
GetUrlCacheEntryInfo,WININET.DLL,AW,3,Retrieves information about a cache entry.                 glColor3s,OPENGL32.DLL,NM,3 set the current color
GetUrlCacheEntryInfoEx,WININET.DLL,AW,7,Retrieves information on the cache entry                 glColor3sv,OPENGL.DLL,NM,1 set the current color
associated with the specified URL, taking into account any redirections that are applied in      glColor3sv,OPENGL32.DLL,NM,1 set the current color
offline mode by the HttpSendRequest function.                                                    glColor3ub,OPENGL.DLL,NM,3 set the current color
GetUrlCacheGroupAttribute,WININET.DLL,AW,7,Retrieves the attribute information of the            glColor3ub,OPENGL32.DLL,NM,3 set the current color
specified cache group.                                                                           glColor3ubv,OPENGL.DLL,NM,1 set the current color
GetUserDefaultLangID,KERNEL32.DLL,NM,0 retrieves the user-default language identifier.           glColor3ubv,OPENGL32.DLL,NM,1 set the current color
GetUserDefaultLCID,KERNEL32.DLL,NM,0, retrieves the user-default locale identifier.              glColor3ui,OPENGL.DLL,NM,3 set the current color
GetUserName,ADVAPI32.DLL,AW,2, retrieves the user name of the current thread.                    glColor3ui,OPENGL32.DLL,NM,3 set the current color
GetUserNameEx,SECUR32.DLL,AW,3, retrieves the name of the user or other security                 glColor3uiv,OPENGL.DLL,NM,1 set the current color
principal associated with the calling thread. You can specify the format of the returned name.   glColor3uiv,OPENGL32.DLL,NM,1 set the current color
GetUserObjectInformation,USER32.DLL,AW,5 returns information about awindow station or            glColor3us,OPENGL.DLL,NM,3 set the current color
desktop object.                                                                                  glColor3us,OPENGL32.DLL,NM,3 set the current color
GetUserObjectSecurity,USER32.DLL,NM,5 retrieves security information for the specified user      glColor3usv,OPENGL.DLL,NM,1 set the current color
object.                                                                                          glColor3usv,OPENGL32.DLL,NM,1 set the current color
GetUserProfileDirectory,USERENV.DLL,AW,3, retrieves the path to the root directory of the        glColor4b,OPENGL.DLL,NM,4 set the current color
specified user's profile.                                                                        glColor4b,OPENGL32.DLL,NM,4 set the current color
GetVersion,KERNEL32.DLL,NM,0 returns the current version number of Windows and                   glColor4bv,OPENGL.DLL,NM,1 set the current color
information about the operating system platform.                                                 glColor4bv,OPENGL32.DLL,NM,1 set the current color
GetViewportExtEx,GDI32.DLL,NM,2, retrieves the x-extents and y-extents of the current            glColor4d,OPENGL.DLL,NM,4 set the current color
viewport for the specified device context.                                                       glColor4d,OPENGL32.DLL,NM,4 set the current color
GetViewportOrgEx,GDI32.DLL,NM,2 retrieves the x-coordinates and y-coordinates of the             glColor4dv,OPENGL.DLL,NM,1 set the current color
viewport origin for the specified devicecontext.                                                 glColor4dv,OPENGL32.DLL,NM,1 set the current color
GetVolumeInformation,KERNEL32.DLL,AW,8, returns information about a file system and              glColor4f,OPENGL.DLL,NM,4 set the current color
volume whose root directory is specified.                                                        glColor4f,OPENGL32.DLL,NM,4 set the current color
GetWindow,USER32.DLL,NM,2, retrieves the handle of a window that has the specified               glColor4fv,OPENGL.DLL,NM,1 set the current color
relationship (Z order or owner) to the specified window.                                         glColor4fv,OPENGL32.DLL,NM,1 set the current color
GetWindowContextHelpId,USER32.DLL,NM,1, retrieves the help context identifier, if any,           glColor4i,OPENGL.DLL,NM,4 set the current color
associated with the specified window.                                                            glColor4i,OPENGL32.DLL,NM,4 set the current color
GetWindowDC,USER32.DLL,NM,1 retrieves the handle of a display device (DC)context for the         glColor4iv,OPENGL.DLL,NM,1 set the current color
specified window.                                                                                glColor4iv,OPENGL32.DLL,NM,1 set the current color
GetWindowExtEx,GDI32.DLL,NM,2 retrieves the x-extents and y-extents of the windowfor the         glColor4s,OPENGL.DLL,NM,4 set the current color
specified device context.                                                                        glColor4s,OPENGL32.DLL,NM,4 set the current color
GetWindowLong,USER32.DLL,AW,2, retrieves information about the specified window.                 glColor4sv,OPENGL.DLL,NM,1 set the current color
GetWindowOrgEx,GDI32.DLL,NM,2, retrieves the x-coordinates and y- coordinates of the             glColor4sv,OPENGL32.DLL,NM,1 set the current color
window origin for the specified device context.                                                  glColor4ub,OPENGL.DLL,NM,4 set the current color
GetWindowPlacement,USER32.DLL,NM,2 retrieves the show state and therestored, minimized,          glColor4ub,OPENGL32.DLL,NM,4 set the current color
and maximized positions of the specifiedwindow.                                                  glColor4ubv,OPENGL.DLL,NM,1 set the current color
GetWindowRect,USER32.DLL,NM,2, retrieves the dimensions of the bounding rectangle of the         glColor4ubv,OPENGL32.DLL,NM,1 set the current color
specified window.                                                                                glColor4ui,OPENGL.DLL,NM,4 set the current color
GetWindowRgn,USER32.DLL,NM,2, obtains a copy of the window region of a window.                   glColor4ui,OPENGL32.DLL,NM,4 set the current color
GetWindowsDirectory,KERNEL32.DLL,AW,2, retrieves the path of the Windows directory.              glColor4uiv,OPENGL.DLL,NM,1 set the current color
GetWindowText,USER32.DLL,AW,3, copies the text of the specified window? s title bar (if it       glColor4uiv,OPENGL32.DLL,NM,1 set the current color
has one) into a buffer.                                                                          glColor4us,OPENGL.DLL,NM,4 set the current color
GetWindowTextLength,USER32.DLL,AW,1 retrieves the length, incharacters, of the specified         glColor4us,OPENGL32.DLL,NM,4 set the current color
window?s title bar text (if the windowhas a title bar).                                          glColor4usv,OPENGL.DLL,NM,1 set the current color
GetWindowThreadProcessId,USER32.DLL,NM,2, retrieves the identifier of the thread that            glColor4usv,OPENGL32.DLL,NM,1 set the current color
created the specified window and, optionally, the identifier of the process that created the     glColorMask,OPENGL.DLL,NM,4, specifies whether the individual color components in the
window.                                                                                          frame buffer can or cannot be written.
GetWindowWord,USER32.DLL,NM,2, is obsolete.                                                      glColorMask,OPENGL32.DLL,NM,4, specifies whether the individual color components in the
GetWinMetaFileBits,GDI32.DLL,NM,5 converts the enhanced-formatrecords from a metafile            frame buffer can or cannot be written.
into Windows-format records and stores theconverted records in the specified buffer.             glColorMaterial,OPENGL.DLL,NM,2, causes a material color to track the current color.
GetWorldTransform,GDI32.DLL,NM,2, retrieves the current world-space to page-space                glColorMaterial,OPENGL32.DLL,NM,2, causes a material color to track the current color.
transformation.                                                                                  glColorPointer,OPENGL.DLL,NM,4, defines an array of colors.
GetWsChanges,PSAPI.DLL,NM,3, retrieves information about the pages that have been added          glColorPointer,OPENGL32.DLL,NM,4, defines an array of colors.
to the working set of the specified process since the InitializeProcessForWsWatch function       glCopyPixels,OPENGL.DLL,NM,5, copies pixels in the frame buffer.
initiated monitoring.                                                                            glCopyPixels,OPENGL32.DLL,NM,5, copies pixels in the frame buffer.
glAccum,OPENGL.DLL,NM,2, operates on the accumulation buffer.                                    glCopyTexImage1D,OPENGL.DLL,NM,7, copies pixels from the frame buffer into a one-
glAccum,OPENGL32.DLL,NM,2, operates on the accumulation buffer.                                  dimensional texture image.
glAlphaFunc,OPENGL.DLL,NM,2, specifies the alpha test function.                                  glCopyTexImage1D,OPENGL32.DLL,NM,7, copies pixels from the frame buffer into a one-
glAlphaFunc,OPENGL32.DLL,NM,2, specifies the alpha test function.                                dimensional texture image.
glAreTexturesResident,OPENGL.DLL,NM,3, determines whether specified texture objects are          glCopyTexImage2D,OPENGL.DLL,NM,4, copies pixels from the frame buffer into a two-
resident.                                                                                        dimensional texture image.
glAreTexturesResident,OPENGL32.DLL,NM,3, determines whether specified texture objects            glCopyTexImage2D,OPENGL32.DLL,NM,4, copies pixels from the frame buffer into a two-
are resident.                                                                                    dimensional texture image.
glArrayElement,OPENGL.DLL,NM,1, specifies the array elements used to render a vertex.            glCopyTexSubImage1D,OPENGL.DLL,NM,3, copies a sub-image of a one- dimensional texture
glArrayElement,OPENGL32.DLL,NM,1, specifies the array elements used to render a vertex.          image from the frame buffer.
glBindTexture,OPENGL.DLL,NM,2, enables the creation of a named texture that is bound to a        glCopyTexSubImage1D,OPENGL32.DLL,NM,3, copies a sub-image of a one- dimensional
texture target.                                                                                  texture image from the frame buffer.
glBindTexture,OPENGL32.DLL,NM,2, enables the creation of a named texture that is bound to        glCopyTexSubImage2D,OPENGL.DLL,NM,4, copies a sub-image of a two- dimensional texture
a texture target.                                                                                image from the frame buffer.
glBitmap,OPENGL.DLL,NM,7, draws a bitmap.                                                        glCopyTexSubImage2D,OPENGL32.DLL,NM,4, copies a sub-image of a two- dimensional
glBitmap,OPENGL32.DLL,NM,7, draws a bitmap.                                                      texture image from the frame buffer.
glBlendFunc,OPENGL.DLL,NM,2, specifies pixel arithmetic.                                         glCullFace,OPENGL.DLL,NM,1, specifies whether front- or back-facing facets can be culled.
glBlendFunc,OPENGL32.DLL,NM,2, specifies pixel arithmetic.                                       glCullFace,OPENGL32.DLL,NM,1, specifies whether front- or back-facing facets can be culled.
glCallList,OPENGL.DLL,NM,1, executes a display list.                                             glDeleteLists,OPENGL.DLL,NM,2, deletes a contiguous group of display lists.
glCallList,OPENGL32.DLL,NM,1, executes a display list.                                           glDeleteLists,OPENGL32.DLL,NM,2, deletes a contiguous group of display lists.
glCallLists,OPENGL.DLL,NM,3, executes a list of display lists.                                   glDeleteTextures,OPENGL.DLL,NM,2, deletes named textures.
glCallLists,OPENGL32.DLL,NM,3, executes a list of display lists.                                 glDeleteTextures,OPENGL32.DLL,NM,2, deletes named textures.
glClear,OPENGL.DLL,NM,1, clears buffers to preset values.                                        glDepthFunc,OPENGL.DLL,NM,1, specifies the value used for depth-buffer comparisons.
glClear,OPENGL32.DLL,NM,1, clears buffers to preset values.                                      glDepthFunc,OPENGL32.DLL,NM,1, specifies the value used for depth-buffer comparisons.
glClearAccum,OPENGL.DLL,NM,4, clears values for the accumulation buffer.                         glDepthMask,OPENGL.DLL,NM,1, enables or disables writing into the depth buffer.
glClearAccum,OPENGL32.DLL,NM,4, clears values for the accumulation buffer.                       glDepthMask,OPENGL32.DLL,NM,1, enables or disables writing into the depth buffer.
glClearColor,OPENGL.DLL,NM,4, specifies clear values for the color buffers.                      glDepthRange,OPENGL.DLL,NM,4, specifies the mapping of z values from normalized device
glClearColor,OPENGL32.DLL,NM,4, specifies clear values for the color buffers.                    coordinates to window coordinates.
glClearDepth,OPENGL.DLL,NM,2, specifies the clear value for the depth buffer.                    glDepthRange,OPENGL32.DLL,NM,4, specifies the mapping of z values from normalized
glClearDepth,OPENGL32.DLL,NM,2, specifies the clear value for the depth buffer.                  device coordinates to window coordinates.
glClearIndex,OPENGL.DLL,NM,1, specifies the clear value for the color- index buffers.            glDisable,OPENGL.DLL,NM,1 disable OpenGL capabilities.
glClearIndex,OPENGL32.DLL,NM,1, specifies the clear value for the color- index buffers.          glDisable,OPENGL32.DLL,NM,1 disable OpenGL capabilities.
glClearStencil,OPENGL.DLL,NM,1, specifies the clear value for the stencil buffer.                glDisableClientState,OPENGL.DLL,NM,1 disable array.
glClearStencil,OPENGL32.DLL,NM,1, specifies the clear value for the stencil buffer.              glDisableClientState,OPENGL32.DLL,NM,1 disable array.
glColor3b,OPENGL.DLL,NM,3 set the current color                                                  glDrawArrays,OPENGL.DLL,NM,3, specifies multiple primitives to render.
glColor3b,OPENGL32.DLL,NM,3 set the current color                                                glDrawArrays,OPENGL32.DLL,NM,3, specifies multiple primitives to render.
glColor3bv,OPENGL.DLL,NM,1 set the current color                                                 glDrawBuffer,OPENGL.DLL,NM,1, specifies which color buffers are to be drawn into.
glColor3bv,OPENGL32.DLL,NM,1 set the current color                                               glDrawBuffer,OPENGL32.DLL,NM,1, specifies which color buffers are to be drawn into.
glColor3d,OPENGL.DLL,NM,3 set the current color                                                  glDrawElements,OPENGL.DLL,NM,4, renders primitives from array data.
glColor3d,OPENGL32.DLL,NM,3 set the current color                                                glDrawElements,OPENGL32.DLL,NM,4, renders primitives from array data.
glColor3dv,OPENGL.DLL,NM,1 set the current color                                                 glDrawPixels,OPENGL.DLL,NM,5, writes a block of pixels to the frame buffer.
glColor3dv,OPENGL32.DLL,NM,1 set the current color                                               glDrawPixels,OPENGL32.DLL,NM,5, writes a block of pixels to the frame buffer.
glColor3f,OPENGL.DLL,NM,3 set the current color                                                  glEdgeFlag,OPENGL.DLL,NM,1 flag edges as either boundary or nonboundary
glColor3f,OPENGL32.DLL,NM,3 set the current color                                                glEdgeFlag,OPENGL32.DLL,NM,1 flag edges as either boundary or nonboundary
glColor3fv,OPENGL.DLL,NM,1 set the current color                                                 glEdgeFlagPointer,OPENGL.DLL,NM,2, defines an array of edge flags.
glColor3fv,OPENGL32.DLL,NM,1 set the current color                                               glEdgeFlagPointer,OPENGL32.DLL,NM,2, defines an array of edge flags.
glColor3i,OPENGL.DLL,NM,3 set the current color                                                  glEdgeFlagv,OPENGL.DLL,NM,1 flag edges as either boundary or nonboundary
glColor3i,OPENGL32.DLL,NM,3 set the current color                                                glEdgeFlagv,OPENGL32.DLL,NM,1 flag edges as either boundary or nonboundary
glColor3iv,OPENGL.DLL,NM,1 set the current color                                                 glEnable,OPENGL.DLL,NM,1 enable OpenGL capabilities.
                                                                                        133
glEnable,OPENGL32.DLL,NM,1 enable OpenGL capabilities.                                       glGetTexLevelParameterfv,OPENGL.DLL,NM,4 return texture parameter values for a specific
glEnableClientState,OPENGL.DLL,NM,1 enable array.                                            level of detail.
glEnableClientState,OPENGL32.DLL,NM,1 enable array.                                          glGetTexLevelParameterfv,OPENGL32.DLL,NM,4 return texture parameter values for a specific
glEnd,OPENGL.DLL,NM,0 delimit the vertices of a primitive or a group of like primitives.     level of detail.
glEnd,OPENGL32.DLL,NM,0 delimit the vertices of a primitive or a group of like primitives.   glGetTexLevelParameteriv,OPENGL.DLL,NM,4 return texture parameter values for a specific
glEndList,OPENGL.DLL,NM,0 create or replace a display list.                                  level of detail.
glEndList,OPENGL32.DLL,NM,0 create or replace a display list.                                glGetTexLevelParameteriv,OPENGL32.DLL,NM,4 return texture parameter values for a specific
glEvalCoord1d,OPENGL.DLL,NM,2 evaluate enabled one- and two-dimensional maps.                level of detail.
glEvalCoord1d,OPENGL32.DLL,NM,2 evaluate enabled one- and two-dimensional maps.              glGetTexParameterfv,OPENGL.DLL,NM,3 return texture parameter values.
glEvalCoord1dv,OPENGL.DLL,NM,1 evaluate enabled one- and two-dimensional maps.               glGetTexParameterfv,OPENGL32.DLL,NM,3 return texture parameter values.
glEvalCoord1dv,OPENGL32.DLL,NM,1 evaluate enabled one- and two-dimensional maps.             glGetTexParameteriv,OPENGL.DLL,NM,3 return texture parameter values.
glEvalCoord1f,OPENGL.DLL,NM,1 evaluate enabled one- and two-dimensional maps.                glGetTexParameteriv,OPENGL32.DLL,NM,3 return texture parameter values.
glEvalCoord1f,OPENGL32.DLL,NM,1 evaluate enabled one- and two-dimensional maps.              glHint,OPENGL.DLL,NM,2, specifies implementation-specific hints.
glEvalCoord1fv,OPENGL.DLL,NM,1 evaluate enabled one- and two-dimensional maps.               glHint,OPENGL32.DLL,NM,2, specifies implementation-specific hints.
glEvalCoord1fv,OPENGL32.DLL,NM,1 evaluate enabled one- and two-dimensional maps.             glIndexd,OPENGL.DLL,NM,2 set the current color index.
glEvalCoord2d,OPENGL.DLL,NM,2 evaluate enabled one- and two-dimensional maps.                glIndexd,OPENGL32.DLL,NM,2 set the current color index.
glEvalCoord2d,OPENGL32.DLL,NM,2 evaluate enabled one- and two-dimensional maps.              glIndexdv,OPENGL.DLL,NM,1 set the current color index.
glEvalCoord2dv,OPENGL.DLL,NM,1 evaluate enabled one- and two-dimensional maps.               glIndexdv,OPENGL32.DLL,NM,1 set the current color index.
glEvalCoord2dv,OPENGL32.DLL,NM,1 evaluate enabled one- and two-dimensional maps.             glIndexf,OPENGL.DLL,NM,1 set the current color index.
glEvalCoord2f,OPENGL.DLL,NM,2 evaluate enabled one- and two-dimensional maps.                glIndexf,OPENGL32.DLL,NM,1 set the current color index.
glEvalCoord2f,OPENGL32.DLL,NM,2 evaluate enabled one- and two-dimensional maps.              glIndexfv,OPENGL.DLL,NM,1 set the current color index.
glEvalCoord2fv,OPENGL.DLL,NM,1 evaluate enabled one- and two-dimensional maps.               glIndexfv,OPENGL32.DLL,NM,1 set the current color index.
glEvalCoord2fv,OPENGL32.DLL,NM,1 evaluate enabled one- and two-dimensional maps.             glIndexi,OPENGL.DLL,NM,1 set the current color index.
glEvalMesh1,OPENGL.DLL,NM,3 compute a one- or two-dimensional grid of points or lines.       glIndexi,OPENGL32.DLL,NM,1 set the current color index.
glEvalMesh1,OPENGL32.DLL,NM,3 compute a one- or two-dimensional grid of points or lines.     glIndexiv,OPENGL.DLL,NM,1 set the current color index.
glEvalMesh2,OPENGL.DLL,NM,5 compute a one- or two-dimensional grid of points or lines.       glIndexiv,OPENGL32.DLL,NM,1 set the current color index.
glEvalMesh2,OPENGL32.DLL,NM,5 compute a one- or two-dimensional grid of points or lines.     glIndexMask,OPENGL.DLL,NM,1, controls the writing of individual bits in the color-index
glEvalPoint1,OPENGL.DLL,NM,1 generate and evaluate a single point in a mesh.                 buffers.
glEvalPoint1,OPENGL32.DLL,NM,1 generate and evaluate a single point in a mesh.               glIndexMask,OPENGL32.DLL,NM,1, controls the writing of individual bits in the color-index
glEvalPoint2,OPENGL.DLL,NM,2 generate and evaluate a single point in a mesh.                 buffers.
glEvalPoint2,OPENGL32.DLL,NM,2 generate and evaluate a single point in a mesh.               glIndexPointer,OPENGL.DLL,NM,3, defines an array of color indexes.
glFeedbackBuffer,OPENGL.DLL,NM,3, controls feedback mode.                                    glIndexPointer,OPENGL32.DLL,NM,3, defines an array of color indexes.
glFeedbackBuffer,OPENGL32.DLL,NM,3, controls feedback mode.                                  glIndexs,OPENGL.DLL,NM,1 set the current color index.
glFinish,OPENGL.DLL,NM,0, blocks until all OpenGL execution is complete.                     glIndexs,OPENGL32.DLL,NM,1 set the current color index.
glFinish,OPENGL32.DLL,NM,0, blocks until all OpenGL execution is complete.                   glIndexsv,OPENGL.DLL,NM,1 set the current color index.
glFlush,OPENGL.DLL,NM,0, forces execution of OpenGL functions in finite time.                glIndexsv,OPENGL32.DLL,NM,1 set the current color index.
glFlush,OPENGL32.DLL,NM,0, forces execution of OpenGL functions in finite time.              glInitNames,OPENGL.DLL,NM,0, initializes the name stack.
glFogf,OPENGL.DLL,NM,2 specify fog parameters.                                               glInitNames,OPENGL32.DLL,NM,0, initializes the name stack.
glFogf,OPENGL32.DLL,NM,2 specify fog parameters.                                             glInterleavedArrays,OPENGL.DLL,NM,3, simultaneously specifies and enables several
glFogfv,OPENGL.DLL,NM,2 specify fog parameters.                                              interleaved arrays in a larger aggregate array.
glFogfv,OPENGL32.DLL,NM,2 specify fog parameters.                                            glInterleavedArrays,OPENGL32.DLL,NM,3, simultaneously specifies and enables several
glFogi,OPENGL.DLL,NM,2 specify fog parameters.                                               interleaved arrays in a larger aggregate array.
glFogi,OPENGL32.DLL,NM,2 specify fog parameters.                                             glIsEnabled,OPENGL.DLL,NM,1 tests whether a capability is enabled.
glFogiv,OPENGL.DLL,NM,2 specify fog parameters.                                              glIsEnabled,OPENGL32.DLL,NM,1 tests whether a capability is enabled.
glFogiv,OPENGL32.DLL,NM,2 specify fog parameters.                                            glIsList,OPENGL.DLL,NM,1 tests for display list existence.
glFrontFace,OPENGL.DLL,NM,1, specifies which of the clockwise and counterclockwise facets    glIsList,OPENGL32.DLL,NM,1 tests for display list existence.
are front-facing and back-facing.                                                            glIsTexture,OPENGL.DLL,NM,1, determines if a name corresponds to a texture.
glFrontFace,OPENGL32.DLL,NM,1, specifies which of the clockwise and counterclockwise         glIsTexture,OPENGL32.DLL,NM,1, determines if a name corresponds to a texture.
facets are front-facing and back-facing.                                                     glLightf,OPENGL.DLL,NM,3 set light source parameters.
glFrustum,OPENGL.DLL,NM,12, multiplies the current matrix by a perspective matrix.           glLightf,OPENGL32.DLL,NM,3 set light source parameters.
glFrustum,OPENGL32.DLL,NM,12, multiplies the current matrix by a perspective matrix.         glLightfv,OPENGL.DLL,NM,3 set light source parameters.
glGenLists,OPENGL.DLL,NM,1, generates a contiguous set of empty display lists.               glLightfv,OPENGL32.DLL,NM,3 set light source parameters.
glGenLists,OPENGL32.DLL,NM,1, generates a contiguous set of empty display lists.             glLighti,OPENGL.DLL,NM,3 set light source parameters.
glGenTextures,OPENGL.DLL,NM,2, generates texture names.                                      glLighti,OPENGL32.DLL,NM,3 set light source parameters.
glGenTextures,OPENGL32.DLL,NM,2, generates texture names.                                    glLightiv,OPENGL.DLL,NM,3 set light source parameters.
glGetBooleanv,OPENGL.DLL,NM,2 return the value or values of a selected parameter.            glLightiv,OPENGL32.DLL,NM,3 set light source parameters.
glGetBooleanv,OPENGL32.DLL,NM,2 return the value or values of a selected parameter.          glLightModelf,OPENGL.DLL,NM,2 set the lighting model parameters.
glGetClipPlane,OPENGL.DLL,NM,2, returns in equation the four coefficients of the plane       glLightModelf,OPENGL32.DLL,NM,2 set the lighting model parameters.
equation for plane.                                                                          glLightModelfv,OPENGL.DLL,NM,2 set the lighting model parameters.
glGetClipPlane,OPENGL32.DLL,NM,2, returns in equation the four coefficients of the plane     glLightModelfv,OPENGL32.DLL,NM,2 set the lighting model parameters.
equation for plane.                                                                          glLightModeli,OPENGL.DLL,NM,2 set the lighting model parameters.
glGetDoublev,OPENGL.DLL,NM,2 return the value or values of a selected parameter.             glLightModeli,OPENGL32.DLL,NM,2 set the lighting model parameters.
glGetDoublev,OPENGL32.DLL,NM,2 return the value or values of a selected parameter.           glLightModeliv,OPENGL.DLL,NM,2 set the lighting model parameters.
glGetError,OPENGL.DLL,NM,0, returns error information.                                       glLightModeliv,OPENGL32.DLL,NM,2 set the lighting model parameters.
glGetError,OPENGL32.DLL,NM,0, returns error information.                                     glLineStipple,OPENGL.DLL,NM,2, specifies the line stipple pattern.
glGetFloatv,OPENGL.DLL,NM,2 return the value or values of a selected parameter.              glLineStipple,OPENGL32.DLL,NM,2, specifies the line stipple pattern.
glGetFloatv,OPENGL32.DLL,NM,2 return the value or values of a selected parameter.            glLineWidth,OPENGL.DLL,NM,1, specifies the width of rasterized lines.
glGetIntegerv,OPENGL.DLL,NM,2 return the value or values of a selected parameter.            glLineWidth,OPENGL32.DLL,NM,1, specifies the width of rasterized lines.
glGetIntegerv,OPENGL32.DLL,NM,2 return the value or values of a selected parameter.          glListBase,OPENGL.DLL,NM,1, makes an additional level of indirection available.
glGetLightfv,OPENGL.DLL,NM,3 return light source parameter values.                           glListBase,OPENGL32.DLL,NM,1, makes an additional level of indirection available.
glGetLightfv,OPENGL32.DLL,NM,3 return light source parameter values.                         glLoadIdentity,OPENGL.DLL,NM,0, replaces the current matrix with the identity matrix.
glGetLightiv,OPENGL.DLL,NM,3 return light source parameter values.                           glLoadIdentity,OPENGL32.DLL,NM,0, replaces the current matrix with the identity matrix.
glGetLightiv,OPENGL32.DLL,NM,3 return light source parameter values.                         glLoadMatrixd,OPENGL.DLL,NM,1 replace the current matrix with an arbitrary matrix.
glGetMapdv,OPENGL.DLL,NM,3 return evaluator parameters.                                      glLoadMatrixd,OPENGL32.DLL,NM,1 replace the current matrix with an arbitrary matrix.
glGetMapdv,OPENGL32.DLL,NM,3 return evaluator parameters.                                    glLoadMatrixf,OPENGL.DLL,NM,1 replace the current matrix with an arbitrary matrix.
glGetMapfv,OPENGL.DLL,NM,3 return evaluator parameters.                                      glLoadMatrixf,OPENGL32.DLL,NM,1 replace the current matrix with an arbitrary matrix.
glGetMapfv,OPENGL32.DLL,NM,3 return evaluator parameters.                                    glLoadName,OPENGL.DLL,NM,1, loads a name onto the name stack.
glGetMapiv,OPENGL.DLL,NM,3 return evaluator parameters.                                      glLoadName,OPENGL32.DLL,NM,1, loads a name onto the name stack.
glGetMapiv,OPENGL32.DLL,NM,3 return evaluator parameters.                                    glLogicOp,OPENGL.DLL,NM,1, specifies a logical pixel operation for color index rendering.
glGetMaterialfv,OPENGL.DLL,NM,3 return material parameters.                                  glLogicOp,OPENGL32.DLL,NM,1, specifies a logical pixel operation for color index rendering.
glGetMaterialfv,OPENGL32.DLL,NM,3 return material parameters.                                glMap1d,OPENGL.DLL,NM,4 define a one-dimensional evaluator.
glGetMaterialiv,OPENGL.DLL,NM,3 return material parameters.                                  glMap1d,OPENGL32.DLL,NM,4 define a one-dimensional evaluator.
glGetMaterialiv,OPENGL32.DLL,NM,3 return material parameters.                                glMap1f,OPENGL.DLL,NM,6 define a one-dimensional evaluator.
glGetPixelMapfv,OPENGL.DLL,NM,2 return the specified pixel map.                              glMap1f,OPENGL32.DLL,NM,6 define a one-dimensional evaluator.
glGetPixelMapfv,OPENGL32.DLL,NM,2 return the specified pixel map.                            glMap2d,OPENGL.DLL,NM,7 define a two-dimensional evaluator.
glGetPixelMapuiv,OPENGL.DLL,NM,2 return the specified pixel map.                             glMap2d,OPENGL32.DLL,NM,7 define a two-dimensional evaluator.
glGetPixelMapuiv,OPENGL32.DLL,NM,2 return the specified pixel map.                           glMap2f,OPENGL.DLL,NM,10 define a two-dimensional evaluator.
glGetPixelMapusv,OPENGL.DLL,NM,2 return the specified pixel map.                             glMap2f,OPENGL32.DLL,NM,10 define a two-dimensional evaluator.
glGetPixelMapusv,OPENGL32.DLL,NM,2 return the specified pixel map.                           glMapGrid1d,OPENGL.DLL,NM,5 define a one- or two-dimensional mesh.
glGetPointerv,OPENGL.DLL,NM,2, returns the address of a vertex data array.                   glMapGrid1d,OPENGL32.DLL,NM,5 define a one- or two-dimensional mesh.
glGetPointerv,OPENGL32.DLL,NM,2, returns the address of a vertex data array.                 glMapGrid1f,OPENGL.DLL,NM,3 define a one- or two-dimensional mesh.
glGetPolygonStipple,OPENGL.DLL,NM,1, returns the polygon stipple pattern.                    glMapGrid1f,OPENGL32.DLL,NM,3 define a one- or two-dimensional mesh.
glGetPolygonStipple,OPENGL32.DLL,NM,1, returns the polygon stipple pattern.                  glMapGrid2d,OPENGL.DLL,NM,5 define a one- or two-dimensional mesh.
glGetString,OPENGL.DLL,NM,1, returns a string describing the current OpenGL connection.      glMapGrid2d,OPENGL32.DLL,NM,5 define a one- or two-dimensional mesh.
glGetString,OPENGL32.DLL,NM,1, returns a string describing the current OpenGL connection.    glMapGrid2f,OPENGL.DLL,NM,6 define a one- or two-dimensional mesh.
glGetTexEnvfv,OPENGL.DLL,NM,3 return texture environment parameters.                         glMapGrid2f,OPENGL32.DLL,NM,6 define a one- or two-dimensional mesh.
glGetTexEnvfv,OPENGL32.DLL,NM,3 return texture environment parameters.                       glMaterialf,OPENGL.DLL,NM,3 specify material parameters for the lighting model.
glGetTexEnviv,OPENGL.DLL,NM,3 return texture environment parameters.                         glMaterialf,OPENGL32.DLL,NM,3 specify material parameters for the lighting model.
glGetTexEnviv,OPENGL32.DLL,NM,3 return texture environment parameters.                       glMaterialfv,OPENGL.DLL,NM,3 specify material parameters for the lighting model.
glGetTexGendv,OPENGL.DLL,NM,3 return texture coordinate generation parameters.               glMaterialfv,OPENGL32.DLL,NM,3 specify material parameters for the lighting model.
glGetTexGendv,OPENGL32.DLL,NM,3 return texture coordinate generation parameters.             glMateriali,OPENGL.DLL,NM,3 specify material parameters for the lighting model.
glGetTexGenfv,OPENGL.DLL,NM,3 return texture coordinate generation parameters.               glMateriali,OPENGL32.DLL,NM,3 specify material parameters for the lighting model.
glGetTexGenfv,OPENGL32.DLL,NM,3 return texture coordinate generation parameters.             glMaterialiv,OPENGL.DLL,NM,3 specify material parameters for the lighting model.
glGetTexGeniv,OPENGL.DLL,NM,3 return texture coordinate generation parameters.               glMaterialiv,OPENGL32.DLL,NM,3 specify material parameters for the lighting model.
glGetTexGeniv,OPENGL32.DLL,NM,3 return texture coordinate generation parameters.             glMatrixMode,OPENGL.DLL,NM,1, sets the current matrix mode.
glGetTexImage,OPENGL.DLL,NM,5, returns a texture image.                                      glMatrixMode,OPENGL32.DLL,NM,1, sets the current matrix mode.
glGetTexImage,OPENGL32.DLL,NM,5, returns a texture image.                                    glMultMatrixd,OPENGL.DLL,NM,1 multiply the current matrix by an arbitrary matrix.
                                                                                             glMultMatrixd,OPENGL32.DLL,NM,1 multiply the current matrix by an arbitrary matrix.
                                                                                            134
glMultMatrixf,OPENGL.DLL,NM,1 multiply the current matrix by an arbitrary matrix.             glRasterPos2d,OPENGL.DLL,NM,2 specify the raster position for pixel operations.
glMultMatrixf,OPENGL32.DLL,NM,1 multiply the current matrix by an arbitrary matrix.           glRasterPos2d,OPENGL32.DLL,NM,2 specify the raster position for pixel operations.
glNewList,OPENGL.DLL,NM,2 create or replace a display list.                                   glRasterPos2dv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
glNewList,OPENGL32.DLL,NM,2 create or replace a display list.                                 glRasterPos2dv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
glNormal3b,OPENGL.DLL,NM,3 set the current normal vector.                                     glRasterPos2f,OPENGL.DLL,NM,2 specify the raster position for pixel operations.
glNormal3b,OPENGL32.DLL,NM,3 set the current normal vector.                                   glRasterPos2f,OPENGL32.DLL,NM,2 specify the raster position for pixel operations.
glNormal3bv,OPENGL.DLL,NM,1 set the current normal vector.                                    glRasterPos2fv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
glNormal3bv,OPENGL32.DLL,NM,1 set the current normal vector.                                  glRasterPos2fv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
glNormal3d,OPENGL.DLL,NM,3 set the current normal vector.                                     glRasterPos2i,OPENGL.DLL,NM,2 specify the raster position for pixel operations.
glNormal3d,OPENGL32.DLL,NM,3 set the current normal vector.                                   glRasterPos2i,OPENGL32.DLL,NM,2 specify the raster position for pixel operations.
glNormal3dv,OPENGL.DLL,NM,1 set the current normal vector.                                    glRasterPos2iv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
glNormal3dv,OPENGL32.DLL,NM,1 set the current normal vector.                                  glRasterPos2iv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
glNormal3f,OPENGL.DLL,NM,3 set the current normal vector.                                     glRasterPos2s,OPENGL.DLL,NM,2 specify the raster position for pixel operations.
glNormal3f,OPENGL32.DLL,NM,3 set the current normal vector.                                   glRasterPos2s,OPENGL32.DLL,NM,2 specify the raster position for pixel operations.
glNormal3fv,OPENGL.DLL,NM,1 set the current normal vector.                                    glRasterPos2sv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
glNormal3fv,OPENGL32.DLL,NM,1 set the current normal vector.                                  glRasterPos2sv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
glNormal3i,OPENGL.DLL,NM,3 set the current normal vector.                                     glRasterPos3d,OPENGL.DLL,NM,3 specify the raster position for pixel operations.
glNormal3i,OPENGL32.DLL,NM,3 set the current normal vector.                                   glRasterPos3d,OPENGL32.DLL,NM,3 specify the raster position for pixel operations.
glNormal3iv,OPENGL.DLL,NM,1 set the current normal vector.                                    glRasterPos3dv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
glNormal3iv,OPENGL32.DLL,NM,1 set the current normal vector.                                  glRasterPos3dv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
glNormal3s,OPENGL.DLL,NM,3 set the current normal vector.                                     glRasterPos3f,OPENGL.DLL,NM,3 specify the raster position for pixel operations.
glNormal3s,OPENGL32.DLL,NM,3 set the current normal vector.                                   glRasterPos3f,OPENGL32.DLL,NM,3 specify the raster position for pixel operations.
glNormal3sv,OPENGL.DLL,NM,1 set the current normal vector.                                    glRasterPos3fv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
glNormal3sv,OPENGL32.DLL,NM,1 set the current normal vector.                                  glRasterPos3fv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
glNormalPointer,OPENGL.DLL,NM,3, defines an array of normals.                                 glRasterPos3i,OPENGL.DLL,NM,3 specify the raster position for pixel operations.
glNormalPointer,OPENGL32.DLL,NM,3, defines an array of normals.                               glRasterPos3i,OPENGL32.DLL,NM,3 specify the raster position for pixel operations.
GlobalAddAtom,KERNEL32.DLL,AW,1 adds a character string to the globalatom table and           glRasterPos3iv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
returns a unique value (an atom) identifying thestring.                                       glRasterPos3iv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
GlobalAlloc,KERNEL32.DLL,NM,2, allocates the specified number of bytes from the heap.         glRasterPos3s,OPENGL.DLL,NM,3 specify the raster position for pixel operations.
GlobalCompact,KERNEL32.DLL,NM,1, is obsolete.                                                 glRasterPos3s,OPENGL32.DLL,NM,3 specify the raster position for pixel operations.
GlobalDeleteAtom,KERNEL32.DLL,NM,1, decrements the reference count of a global string         glRasterPos3sv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
atom.                                                                                         glRasterPos3sv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
GlobalFindAtom,KERNEL32.DLL,AW,1 searches the global atom table for thespecified              glRasterPos4d,OPENGL.DLL,NM,4 specify the raster position for pixel operations.
character string and retrieves the global atom associatedwith that string.                    glRasterPos4d,OPENGL32.DLL,NM,4 specify the raster position for pixel operations.
GlobalFix,KERNEL32.DLL,NM,1, is obsolete.                                                     glRasterPos4dv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
GlobalFlags,KERNEL32.DLL,NM,1, returns information about the specified global memory          glRasterPos4dv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
object.                                                                                       glRasterPos4f,OPENGL.DLL,NM,4 specify the raster position for pixel operations.
GlobalFree,KERNEL32.DLL,NM,1, frees the specified global memory object and invalidates its glRasterPos4f,OPENGL32.DLL,NM,4 specify the raster position for pixel operations.
handle.                                                                                       glRasterPos4fv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
GlobalGetAtomName,KERNEL32.DLL,AW,3, retrieves a copy of the character string associated glRasterPos4fv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
with the specified global atom.                                                               glRasterPos4i,OPENGL.DLL,NM,4 specify the raster position for pixel operations.
GlobalHandle,KERNEL32.DLL,NM,1, retrieves the handle associated with the specified pointer glRasterPos4i,OPENGL32.DLL,NM,4 specify the raster position for pixel operations.
to a global memory block.                                                                     glRasterPos4iv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
GlobalLock,KERNEL32.DLL,NM,1, locks a global memory object and returns a pointer to the       glRasterPos4iv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
first byte of the object?s memory block.                                                      glRasterPos4s,OPENGL.DLL,NM,4 specify the raster position for pixel operations.
GlobalMemoryStatus,KERNEL32.DLL,NM,1 obtains information about thecomputer system?s glRasterPos4s,OPENGL32.DLL,NM,4 specify the raster position for pixel operations.
current usage of both physical and virtualmemory.                                             glRasterPos4sv,OPENGL.DLL,NM,1 specify the raster position for pixel operations.
GlobalReAlloc,KERNEL32.DLL,NM,3, changes the size or attributes of a specified global         glRasterPos4sv,OPENGL32.DLL,NM,1 specify the raster position for pixel operations.
memory object.                                                                                glReadBuffer,OPENGL.DLL,NM,1, selects a color buffer source for pixels.
GlobalSize,KERNEL32.DLL,NM,1, retrieves the current size, in bytes, of the specified global   glReadBuffer,OPENGL32.DLL,NM,1, selects a color buffer source for pixels.
memory object.                                                                                glReadPixels,OPENGL.DLL,NM,7, reads a block of pixels from the frame buffer.
GlobalUnfix,KERNEL32.DLL,NM,1, is obsolete.                                                   glReadPixels,OPENGL32.DLL,NM,7, reads a block of pixels from the frame buffer.
GlobalUnWire,KERNEL32.DLL,NM,1, is obsolete.                                                  glRectd,OPENGL.DLL,NM,4 draw a rectangle.
GlobalWire,KERNEL32.DLL,NM,1 is obsolete.                                                     glRectd,OPENGL32.DLL,NM,4 draw a rectangle.
glOrtho,OPENGL.DLL,NM,12, multiplies the current matrix by an orthographic matrix.            glRectdv,OPENGL.DLL,NM,2 draw a rectangle.
glOrtho,OPENGL32.DLL,NM,12, multiplies the current matrix by an orthographic matrix.          glRectdv,OPENGL32.DLL,NM,2 draw a rectangle.
glPassThrough,OPENGL.DLL,NM,1, places a marker in the feedback buffer.                        glRectf,OPENGL.DLL,NM,4 draw a rectangle.
glPassThrough,OPENGL32.DLL,NM,1, places a marker in the feedback buffer.                      glRectf,OPENGL32.DLL,NM,4 draw a rectangle.
glPixelMapfv,OPENGL.DLL,NM,3 set up pixel transfer maps.                                      glRectfv,OPENGL.DLL,NM,2 draw a rectangle.
glPixelMapfv,OPENGL32.DLL,NM,3 set up pixel transfer maps.                                    glRectfv,OPENGL32.DLL,NM,2 draw a rectangle.
glPixelMapuiv,OPENGL.DLL,NM,3 set up pixel transfer maps.                                     glRecti,OPENGL.DLL,NM,4 draw a rectangle.
glPixelMapuiv,OPENGL32.DLL,NM,3 set up pixel transfer maps.                                   glRecti,OPENGL32.DLL,NM,4 draw a rectangle.
glPixelMapusv,OPENGL.DLL,NM,3 set up pixel transfer maps.                                     glRectiv,OPENGL.DLL,NM,2 draw a rectangle.
glPixelMapusv,OPENGL32.DLL,NM,3 set up pixel transfer maps.                                   glRectiv,OPENGL32.DLL,NM,2 draw a rectangle.
glPixelStoref,OPENGL.DLL,NM,2, can be used to set any pixel store parameter.                  glRects,OPENGL.DLL,NM,4 draw a rectangle.
glPixelStoref,OPENGL32.DLL,NM,2, can be used to set any pixel store parameter.                glRects,OPENGL32.DLL,NM,4 draw a rectangle.
glPixelStorei,OPENGL.DLL,NM,2 set pixel storage modes.                                        glRectsv,OPENGL.DLL,NM,2 draw a rectangle.
glPixelStorei,OPENGL32.DLL,NM,2 set pixel storage modes.                                      glRectsv,OPENGL32.DLL,NM,2 draw a rectangle.
glPixelTransferf,OPENGL.DLL,NM,2, can be used to set any pixel transfer parameter.            glRenderMode,OPENGL.DLL,NM,1, sets the rasterization mode.
glPixelTransferf,OPENGL32.DLL,NM,2, can be used to set any pixel transfer parameter.          glRenderMode,OPENGL32.DLL,NM,1, sets the rasterization mode.
glPixelTransferi,OPENGL.DLL,NM,2 set pixel storage modes.                                     glRotated,OPENGL.DLL,NM,4 multiply the current matrix by a rotation matrix.
glPixelTransferi,OPENGL32.DLL,NM,2 set pixel storage modes.                                   glRotated,OPENGL32.DLL,NM,4 multiply the current matrix by a rotation matrix.
glPixelZoom,OPENGL.DLL,NM,2, specifies values for the x and y zoom factors.                   glRotatef,OPENGL.DLL,NM,4 multiply the current matrix by a rotation matrix.
glPixelZoom,OPENGL32.DLL,NM,2, specifies values for the x and y zoom factors.                 glRotatef,OPENGL32.DLL,NM,4 multiply the current matrix by a rotation matrix.
glPointSize,OPENGL.DLL,NM,1, specifies the diameter of rasterized points.                     glScaled,OPENGL.DLL,NM,3 multiply the current matrix by a general scaling matrix.
glPointSize,OPENGL32.DLL,NM,1, specifies the diameter of rasterized points.                   glScaled,OPENGL32.DLL,NM,3 multiply the current matrix by a rotation matrix.
glPolygonMode,OPENGL.DLL,NM,2, selects a polygon rasterization mode.                          glScalef,OPENGL.DLL,NM,3 multiply the current matrix by a rotation matrix.
glPolygonMode,OPENGL32.DLL,NM,2, selects a polygon rasterization mode.                        glScalef,OPENGL32.DLL,NM,3 multiply the current matrix by a rotation matrix.
glPolygonStipple,OPENGL.DLL,NM,1, sets the polygon stippling pattern.                         glScissor,OPENGL.DLL,NM,4, defines the scissor box.
glPolygonStipple,OPENGL32.DLL,NM,1, sets the polygon stippling pattern.                       glScissor,OPENGL32.DLL,NM,4, defines the scissor box.
glPopAttrib,OPENGL.DLL,NM,0, restores the values of the state variables saved with the last   glSelectBuffer,OPENGL.DLL,NM,2, establishes a buffer for selection mode values.
glPushAttrib command.                                                                         glSelectBuffer,OPENGL32.DLL,NM,2, establishes a buffer for selection mode values.
glPopAttrib,OPENGL32.DLL,NM,0, restores the values of the state variables saved with the last glShadeModel,OPENGL.DLL,NM,1 selects flat or smooth shading.
glPushAttrib command.                                                                         glShadeModel,OPENGL32.DLL,NM,1 selects flat or smooth shading.
glPopClientAttrib,OPENGL.DLL,NM,0, restores the values of the client- state variables last    glStencilFunc,OPENGL.DLL,NM,3, sets the function and reference value for stencil testing.
saved with glPushClientAttrib.                                                                glStencilFunc,OPENGL32.DLL,NM,3, sets the function and reference value for stencil testing.
glPopClientAttrib,OPENGL32.DLL,NM,0, restores the values of the client- state variables last  glStencilMask,OPENGL.DLL,NM,1, controls the writing of individual bits in the stencil planes.
saved with glPushClientAttrib.                                                                glStencilMask,OPENGL32.DLL,NM,1, controls the writing of individual bits in the stencil planes.
glPopMatrix,OPENGL.DLL,NM,0 pop the current matrix stack.                                     glStencilOp,OPENGL.DLL,NM,3, sets the stencil test actions.
glPopMatrix,OPENGL32.DLL,NM,0 pop the current matrix stack.                                   glStencilOp,OPENGL32.DLL,NM,3, sets the stencil test actions.
glPrioritizeTextures,OPENGL.DLL,NM,3, sets the residence priority of textures.                glTexCoord1d,OPENGL.DLL,NM,2 set the current texture coordinates.
glPrioritizeTextures,OPENGL32.DLL,NM,3, sets the residence priority of textures.              glTexCoord1d,OPENGL32.DLL,NM,2 set the current texture coordinates.
glPushAttrib,OPENGL.DLL,NM,1, takes one argument, a mask that indicates which groups of glTexCoord1dv,OPENGL.DLL,NM,1 set the current texture coordinates.
state variables to save on the attribute stack.                                               glTexCoord1dv,OPENGL32.DLL,NM,1 set the current texture coordinates.
glPushAttrib,OPENGL32.DLL,NM,1, takes one argument, a mask that indicates which groups of glTexCoord1f,OPENGL.DLL,NM,1 set the current texture coordinates.
state variables to save on the attribute stack.                                               glTexCoord1f,OPENGL32.DLL,NM,1 set the current texture coordinates.
glPushClientAttrib,OPENGL.DLL,NM,1 save groups of client-state variables on the client-       glTexCoord1fv,OPENGL.DLL,NM,1 set the current texture coordinates.
attribute stack.                                                                              glTexCoord1fv,OPENGL32.DLL,NM,1 set the current texture coordinates.
glPushClientAttrib,OPENGL32.DLL,NM,1 save groups of client-state variables on the client-     glTexCoord1i,OPENGL.DLL,NM,1 set the current texture coordinates.
attribute stack.                                                                              glTexCoord1i,OPENGL32.DLL,NM,1 set the current texture coordinates.
glPushMatrix,OPENGL.DLL,NM,0, pushes the current matrix stack down by one, duplicating        glTexCoord1iv,OPENGL.DLL,NM,1 set the current texture coordinates.
the current matrix.                                                                           glTexCoord1iv,OPENGL32.DLL,NM,1 set the current texture coordinates.
glPushMatrix,OPENGL32.DLL,NM,0, pushes the current matrix stack down by one, duplicating glTexCoord1s,OPENGL.DLL,NM,1 set the current texture coordinates.
the current matrix.                                                                           glTexCoord1s,OPENGL32.DLL,NM,1 set the current texture coordinates.
glPushName,OPENGL.DLL,NM,1, causes name to be pushed onto the name stack, which is            glTexCoord1sv,OPENGL.DLL,NM,1 set the current texture coordinates.
initially empty.                                                                              glTexCoord1sv,OPENGL32.DLL,NM,1 set the current texture coordinates.
glPushName,OPENGL32.DLL,NM,1, causes name to be pushed onto the name stack, which is glTexCoord2d,OPENGL.DLL,NM,2 set the current texture coordinates.
initially empty.                                                                              glTexCoord2d,OPENGL32.DLL,NM,2 set the current texture coordinates.
                                                                                       135
glTexCoord2dv,OPENGL.DLL,NM,1 set the current texture coordinates.                         gluGetNurbsProperty,GLU32.DLL,NM,3, gets a NURBS property.
glTexCoord2dv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       gluLoadSamplingMatrices,GLU32.DLL,NM,4, loads NURBS sampling and culling matrices.
glTexCoord2f,OPENGL.DLL,NM,2 set the current texture coordinates.                          gluLookAt,GLU32.DLL,NM,18, defines a viewing transformation.
glTexCoord2f,OPENGL32.DLL,NM,2 set the current texture coordinates.                        gluNewNurbsRenderer,GLU32.DLL,NM,0, creates a NURBS object.
glTexCoord2fv,OPENGL.DLL,NM,1 set the current texture coordinates.                         gluNewQuadric,GLU32.DLL,NM,0, creates a quadric object.
glTexCoord2fv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       gluNewTess,GLU32.DLL,NM,0, creates a tessellation object.
glTexCoord2i,OPENGL.DLL,NM,2 set the current texture coordinates.                          gluNextContour,GLU32.DLL,NM,2, marks the beginning of another contour.
glTexCoord2i,OPENGL32.DLL,NM,2 set the current texture coordinates.                        gluNurbsCallback,GLU32.DLL,NM,3, defines a callback for a NURBS object.
glTexCoord2iv,OPENGL.DLL,NM,1 set the current texture coordinates.                         gluNurbsCurve,GLU32.DLL,NM,7, defines the shape of a NURBS curve.
glTexCoord2iv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       gluNurbsProperty,GLU32.DLL,NM,3, sets a NURBS property.
glTexCoord2s,OPENGL.DLL,NM,2 set the current texture coordinates.                          gluNurbsSurface,GLU32.DLL,NM,11, defines the shape of a NURBS surface.
glTexCoord2s,OPENGL32.DLL,NM,2 set the current texture coordinates.                        gluOrtho2D,GLU32.DLL,NM,8, defines a 2-D orthographic projection matrix.
glTexCoord2sv,OPENGL.DLL,NM,1 set the current texture coordinates.                         gluPartialDisk,GLU32.DLL,NM,11, draws an arc of a disk.
glTexCoord2sv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       gluPerspective,GLU32.DLL,NM,8, sets up a perspective projection matrix.
glTexCoord3d,OPENGL.DLL,NM,3 set the current texture coordinates.                          gluPickMatrix,GLU32.DLL,NM,9, defines a picking region.
glTexCoord3d,OPENGL32.DLL,NM,3 set the current texture coordinates.                        gluProject,GLU32.DLL,NM,12, maps object coordinates to window coordinates.
glTexCoord3dv,OPENGL.DLL,NM,1 set the current texture coordinates.                         gluPwlCurve,GLU32.DLL,NM,5, describes a piecewise linear NURBS trimming curve.
glTexCoord3dv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       gluQuadricCallback,GLU32.DLL,NM,3, defines a callback for a quadric object.
glTexCoord3f,OPENGL.DLL,NM,3 set the current texture coordinates.                          gluQuadricDrawStyle,GLU32.DLL,NM,2, specifies the draw style for quadrics rendered with
glTexCoord3f,OPENGL32.DLL,NM,3 set the current texture coordinates.                        qobj.
glTexCoord3fv,OPENGL.DLL,NM,1 set the current texture coordinates.                         gluQuadricNormals,GLU32.DLL,NM,2, specifies what kind of normals are to be used for
glTexCoord3fv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       quadrics.
glTexCoord3i,OPENGL.DLL,NM,3 set the current texture coordinates.                          gluQuadricOrientation,GLU32.DLL,NM,2, specifies inside or outside orientation for quadrics.
glTexCoord3i,OPENGL32.DLL,NM,3 set the current texture coordinates.                        gluQuadricTexture,GLU32.DLL,NM,2, specifies whether quadrics are to be textured.
glTexCoord3iv,OPENGL.DLL,NM,1 set the current texture coordinates.                         gluScaleImage,GLU32.DLL,NM,9, scales an image to an arbitrary size.
glTexCoord3iv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       gluSphere,GLU32.DLL,NM,5, draws a sphere.
glTexCoord3s,OPENGL.DLL,NM,3 set the current texture coordinates.                          gluTessCallback,GLU32.DLL,NM,3, defines a callback for a tessellation object.
glTexCoord3s,OPENGL32.DLL,NM,3 set the current texture coordinates.                        gluTessVertex,GLU32.DLL,NM,3, describes a vertex on a polygon that the user is defining.
glTexCoord3sv,OPENGL.DLL,NM,1 set the current texture coordinates.                         gluUnProject,GLU32.DLL,NM,12, maps window coordinates to object coordinates.
glTexCoord3sv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       glVertex2d,OPENGL.DLL,NM,2 specify a vertex.
glTexCoord4d,OPENGL.DLL,NM,4 set the current texture coordinates.                          glVertex2d,OPENGL32.DLL,NM,2 specify a vertex.
glTexCoord4d,OPENGL32.DLL,NM,4 set the current texture coordinates.                        glVertex2dv,OPENGL.DLL,NM,1 specify a vertex.
glTexCoord4dv,OPENGL.DLL,NM,1 set the current texture coordinates.                         glVertex2dv,OPENGL32.DLL,NM,1 specify a vertex.
glTexCoord4dv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       glVertex2f,OPENGL.DLL,NM,2 specify a vertex.
glTexCoord4f,OPENGL.DLL,NM,4 set the current texture coordinates.                          glVertex2f,OPENGL32.DLL,NM,2 specify a vertex.
glTexCoord4f,OPENGL32.DLL,NM,4 set the current texture coordinates.                        glVertex2fv,OPENGL.DLL,NM,1 specify a vertex.
glTexCoord4fv,OPENGL.DLL,NM,1 set the current texture coordinates.                         glVertex2fv,OPENGL32.DLL,NM,1 specify a vertex.
glTexCoord4fv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       glVertex2i,OPENGL.DLL,NM,2 specify a vertex.
glTexCoord4i,OPENGL.DLL,NM,4 set the current texture coordinates.                          glVertex2i,OPENGL32.DLL,NM,2 specify a vertex.
glTexCoord4i,OPENGL32.DLL,NM,4 set the current texture coordinates.                        glVertex2iv,OPENGL.DLL,NM,1 specify a vertex.
glTexCoord4iv,OPENGL.DLL,NM,1 set the current texture coordinates.                         glVertex2iv,OPENGL32.DLL,NM,1 specify a vertex.
glTexCoord4iv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       glVertex2s,OPENGL.DLL,NM,2 specify a vertex.
glTexCoord4s,OPENGL.DLL,NM,4 set the current texture coordinates.                          glVertex2s,OPENGL32.DLL,NM,2 specify a vertex.
glTexCoord4s,OPENGL32.DLL,NM,4 set the current texture coordinates.                        glVertex2sv,OPENGL.DLL,NM,1 specify a vertex.
glTexCoord4sv,OPENGL.DLL,NM,1 set the current texture coordinates.                         glVertex2sv,OPENGL32.DLL,NM,1 specify a vertex.
glTexCoord4sv,OPENGL32.DLL,NM,1 set the current texture coordinates.                       glVertex3d,OPENGL.DLL,NM,3 specify a vertex.
glTexCoordPointer,OPENGL.DLL,NM,4, defines an array of texture coordinates.                glVertex3d,OPENGL32.DLL,NM,3 specify a vertex.
glTexCoordPointer,OPENGL32.DLL,NM,4, defines an array of texture coordinates.              glVertex3dv,OPENGL.DLL,NM,1 specify a vertex.
glTexEnvf,OPENGL.DLL,NM,3 set texture environment parameters.                              glVertex3dv,OPENGL32.DLL,NM,1 specify a vertex.
glTexEnvf,OPENGL32.DLL,NM,3 set texture environment parameters.                            glVertex3f,OPENGL.DLL,NM,3 specify a vertex.
glTexEnvfv,OPENGL.DLL,NM,3 set texture environment parameters.                             glVertex3f,OPENGL32.DLL,NM,3 specify a vertex.
glTexEnvfv,OPENGL32.DLL,NM,3 set texture environment parameters.                           glVertex3fv,OPENGL.DLL,NM,1 specify a vertex.
glTexEnvi,OPENGL.DLL,NM,3 set texture environment parameters.                              glVertex3fv,OPENGL32.DLL,NM,1 specify a vertex.
glTexEnvi,OPENGL32.DLL,NM,3 set texture environment parameters.                            glVertex3i,OPENGL.DLL,NM,3 specify a vertex.
glTexEnviv,OPENGL.DLL,NM,3 set texture environment parameters.                             glVertex3i,OPENGL32.DLL,NM,3 specify a vertex.
glTexEnviv,OPENGL32.DLL,NM,3 set texture environment parameters.                           glVertex3iv,OPENGL.DLL,NM,1 specify a vertex.
glTexGend,OPENGL.DLL,NM,2 control the generation of texture coordinates.                   glVertex3iv,OPENGL32.DLL,NM,1 specify a vertex.
glTexGend,OPENGL32.DLL,NM,2 control the generation of texture coordinates.                 glVertex3s,OPENGL.DLL,NM,3 specify a vertex.
glTexGendv,OPENGL.DLL,NM,3 control the generation of texture coordinates.                  glVertex3s,OPENGL32.DLL,NM,3 specify a vertex.
glTexGendv,OPENGL32.DLL,NM,3 control the generation of texture coordinates.                glVertex3sv,OPENGL.DLL,NM,1 specify a vertex.
glTexGenf,OPENGL.DLL,NM,3 control the generation of texture coordinates.                   glVertex3sv,OPENGL32.DLL,NM,1 specify a vertex.
glTexGenf,OPENGL32.DLL,NM,3 control the generation of texture coordinates.                 glVertex4d,OPENGL.DLL,NM,4 specify a vertex.
glTexGenfv,OPENGL.DLL,NM,3 control the generation of texture coordinates.                  glVertex4d,OPENGL32.DLL,NM,4 specify a vertex.
glTexGenfv,OPENGL32.DLL,NM,3 control the generation of texture coordinates.                glVertex4dv,OPENGL.DLL,NM,1 specify a vertex.
glTexGeni,OPENGL.DLL,NM,3 control the generation of texture coordinates.                   glVertex4dv,OPENGL32.DLL,NM,1 specify a vertex.
glTexGeni,OPENGL32.DLL,NM,3 control the generation of texture coordinates.                 glVertex4f,OPENGL.DLL,NM,4 specify a vertex.
glTexGeniv,OPENGL.DLL,NM,3 control the generation of texture coordinates.                  glVertex4f,OPENGL32.DLL,NM,4 specify a vertex.
glTexGeniv,OPENGL32.DLL,NM,3 control the generation of texture coordinates.                glVertex4fv,OPENGL.DLL,NM,1 specify a vertex.
glTexImage1D,OPENGL.DLL,NM,4 specifies a one-dimensional texture image.                    glVertex4fv,OPENGL32.DLL,NM,1 specify a vertex.
glTexImage1D,OPENGL32.DLL,NM,4 specifies a one-dimensional texture image.                  glVertex4i,OPENGL.DLL,NM,4 specify a vertex.
glTexImage2D,OPENGL.DLL,NM,9, specifies a two-dimensional texture image.                   glVertex4i,OPENGL32.DLL,NM,4 specify a vertex.
glTexImage2D,OPENGL32.DLL,NM,9, specifies a two-dimensional texture image.                 glVertex4iv,OPENGL.DLL,NM,1 specify a vertex.
glTexParameterf,OPENGL.DLL,NM,3 set texture parameters.                                    glVertex4iv,OPENGL32.DLL,NM,1 specify a vertex.
glTexParameterf,OPENGL32.DLL,NM,3 set texture parameters.                                  glVertex4s,OPENGL.DLL,NM,4 specify a vertex.
glTexParameterfv,OPENGL.DLL,NM,3 set texture parameters.                                   glVertex4s,OPENGL32.DLL,NM,4 specify a vertex.
glTexParameterfv,OPENGL32.DLL,NM,3 set texture parameters.                                 glVertex4sv,OPENGL.DLL,NM,1 specify a vertex.
glTexParameteri,OPENGL.DLL,NM,3 set texture parameters.                                    glVertex4sv,OPENGL32.DLL,NM,1 specify a vertex.
glTexParameteri,OPENGL32.DLL,NM,3 set texture parameters.                                  glVertexPointer,OPENGL.DLL,NM,4, defines an array of vertex data.
glTexParameteriv,OPENGL.DLL,NM,3 set texture parameters.                                   glVertexPointer,OPENGL32.DLL,NM,4, defines an array of vertex data.
glTexParameteriv,OPENGL32.DLL,NM,3 set texture parameters.                                 glViewport,OPENGL.DLL,NM,4, sets the viewport.
glTexSubImage1D,OPENGL.DLL,NM,7, specifies a portion of an existing one-dimensional        glViewport,OPENGL32.DLL,NM,4, sets the viewport.
texture image.                                                                             GopherCreateLocator,WININET.DLL,AW,7,Creates a Gopher or Gopher+ locator string from
glTexSubImage1D,OPENGL32.DLL,NM,7, specifies a portion of an existing one-dimensional      the selector string's component parts.
texture image..                                                                            GopherFindFirstFile,WININET.DLL,AW,6,Uses a Gopher locator and search criteria to create a
glTexSubImage2D,OPENGL.DLL,NM,9, specifies a portion of an existing one-dimensional        session with the server and locate the requested documents, binary files, index servers, or
texture image.                                                                             directory trees.
glTexSubImage2D,OPENGL32.DLL,NM,9, specifies a portion of an existing one-dimensional      GopherGetAttribute,WININET.DLL,AW,8,Retrieves the specific attribute information from the
texture image.                                                                             server.
glTranslated,OPENGL.DLL,NM,3 multiply the current matrix by a translation matrix.          GopherGetLocatorType,WININET.DLL,AW,2,Parses a Gopher locator and determines its
glTranslated,OPENGL32.DLL,NM,3 multiply the current matrix by a translation matrix.        attributes.
glTranslatef,OPENGL.DLL,NM,3 multiply the current matrix by a translation matrix.          GopherOpenFile,WININET.DLL,AW,5,Begins reading a Gopher data file from a Gopher server.
glTranslatef,OPENGL32.DLL,NM,3 multiply the current matrix by a translation matrix.        GrayString,USER32.DLL,AW,9, draws gray text at the specified location.
gluBeginCurve,GLU32.DLL,NM,1 delimit a NURBS curve definition.                             Heap32First,TOOLHELP.DLL,NM,3, retrieves information about the first block of a heap that
gluBeginPolygon,GLU32.DLL,NM,1 delimit a polygon description.                              has been allocated by a process.
gluBeginSurface,GLU32.DLL,NM,1 delimit a NURBS surface definition.                         Heap32ListFirst,TOOLHELP.DLL,NM,2, retrieves information about the first heap that has been
gluBeginTrim,GLU32.DLL,NM,1 delimit a NURBS trimming loop definition.                      allocated by a specified process.
gluBuild1DMipmaps,GLU32.DLL,NM,6 creates 1-D mipmaps.                                      Heap32ListNext,TOOLHELP.DLL,NM,2, retrieves information about the next heap that has
gluBuild2DMipmaps,GLU32.DLL,NM,7, creates 2-D mipmaps.                                     been allocated by a process.
gluCylinder,GLU32.DLL,NM,9, draws a cylinder.                                              Heap32Next,TOOLHELP.DLL,NM,1, retrieves information about the next block of a heap that
gluDeleteNurbsRenderer,GLU32.DLL,NM,1, destroys a NURBS object.                            has been allocated by a process.
gluDeleteQuadric,GLU32.DLL,NM,1, destroys a quadric object.                                HeapAlloc,KERNEL32.DLL,NM,3, allocates a block of memory from a heap.
gluDeleteTess,GLU32.DLL,NM,1, destroys a tessellation object.                              HeapCompact,KERNEL32.DLL,NM,2, attempts to compact a specified heap.
gluDisk,GLU32.DLL,NM,7, draws a disk.                                                      HeapCreate,KERNEL32.DLL,NM,3, creates a heap object that can be used by the calling
gluEndCurve,GLU32.DLL,NM,1 delimit a NURBS curve definition.                               process.
gluEndPolygon,GLU32.DLL,NM,1 delimit a polygon description.                                HeapDestroy,KERNEL32.DLL,NM,1, destroys the specified heap object.
gluEndSurface,GLU32.DLL,NM,1 delimit a NURBS surface definition.                           HeapFree,KERNEL32.DLL,NM,3, frees a memory block allocated from a heap by the
gluEndTrim,GLU32.DLL,NM,1 delimit a NURBS trimming loop definition.                        HeapAlloc or HeapReAlloc function.
gluErrorString,GLU32.DLL,NM,1 produces an error string from an OpenGL or GLU error code.
                                                                                                136
HeapLock,KERNEL32.DLL,NM,1, attempts to acquire the critical section object, or lock, that is         HrDecomposeMsgID,MAPI32.DLL,NM,6 separates the ASCII representation of the compound
associated with a specified heap.                                                                     entry identifier of an object, usually a message in a message store, into the entry identifier of
HeapReAlloc,KERNEL32.DLL,NM,4, reallocates a block of memory from a heap.                             that object within the store and the store's entry identifier.
HeapSize,KERNEL32.DLL,NM,3, returns the size, in bytes, of a memory block allocated from a            HrDispatchNotifications,MAPI32.DLL,NM,1, forces dispatching of all queued notifications.
heap by the HeapAlloc or HeapReAlloc function.                                                        HrEntryIDFromSz,MAPI32.DLL,NM,3, recreates an entry identifier from its ASCII encoding.
HeapUnlock,KERNEL32.DLL,NM,1, releases ownership of the critical section object, or lock,             HrGetOneProp,MAPI32.DLL,NM,3 retrieves the value of a single propertyfrom a property
that is associated with a specified heap.                                                             interface, that is, an interface derived fromIMAPIProp.
HeapValidate,KERNEL32.DLL,NM,3, attempts to validate a specified heap.                                HrIStorageFromStream,MAPI32.DLL,NM,4, layers an IStorage interface onto an IStream
HeapWalk,KERNEL32.DLL,NM,2, enumerates the memory blocks in a specified heap.                         object.
HexFromBin,MAPI32.DLL,NM,3, converts a binary number into a string representation of a                HrQueryAllRows,MAPI32.DLL,NM,6 retrieves all rows of a table.
hexadecimal number.                                                                                   HrRestoreEnd,EDBBCLI.DLL,NM,1, cleans up after a restore operation has been performed.
HideCaret,USER32.DLL,NM,1, removes the caret from the screen.                                         HrRestoreGetDatabaseLocations,EDBBCLI.DLL,AW,3, obtains the database locations for the
HiliteMenuItem,USER32.DLL,NM,4, highlights or removes the highlighting from an item in a              server and service.
menu bar.                                                                                             HrRestorePrepare,EDBBCLI.DLL,AW,3, connects to a remote Microsoft Exchange Server
HlinkClone,HLINK.DLL,NM,5, HlinkClone Function Not currently supported.                               database and prepares it for restore.
HlinkCreateBrowseContext,HLINK.DLL,NM,3, Creates an empty, default instance of the system             HrRestoreRegister,EDBBCLI.DLL,AW,8 registers a restore operation, interlocking all
browse context object.                                                                                subsequent restore operations and preventing the restore target from starting until
HlinkCreateExtensionServices,HLINK.DLL,NM,7, HlinkCreateExtensionServices Function Not                HrRestoreRegisterComplete is called.
currently supported.                                                                                  HrRestoreRegisterComplete,EDBBCLI.DLL,NM,2 completes a restore operation, allowing
HlinkCreateFromData,HLINK.DLL,NM,6, Creates a standard hyperlink object from a                        subsequent restore operations.
Component Object Model (COM) object that supports the IDataObject interface.                          HrSetCurrentBackupLog,EDBBCLI.DLL,AW,3, sets the last log number that was backed up.
HlinkCreateFromMoniker,HLINK.DLL,NM,8, Creates a new system hyperlink object from a                   HrSetOneProp,MAPI32.DLL,NM,2, sets or changes the value of a single property on a property
moniker, a location string, and a friendly name string (used for displaying the hyperlink).           interface, that is, an interface derived from IMAPIProp .
HlinkCreateFromString,HLINK.DLL,NM,8, Creates a new hyperlink object from strings                     HrSzFromEntryID,MAPI32.DLL,NM,3, encodes an entry identifier into an ASCII string.
representing the hyperlink target, the location within the target, and a friendly name.               HrThisThreadAdviseSink,MAPI32.DLL,NM,2, creates an advise sink that wraps an existing
HlinkCreateShortcut,HLINK.DLL,NM,6,FromString HlinkCreateShortcutFromString Function                  advise sink for thread safety.
Not currently supported.                                                                              HrValidateIPMSubtree,MAPI32.DLL,NM,5, adds standard interpersonal message (IPM) folders
HlinkCreateShortcutFromMoniker,HLINK.DLL,NM,7, HlinkCreateShortcutFromMoniker Function                to a message store.
Not currently supported.                                                                              htonl,WS2_32.DLL,NM,1 converts a u_long from host toTCP/IP network byte order.
HlinkCreateShortcutFromString,HLINK.DLL,NM,7, HlinkCreateShortcutFromString Function                  htonl,WSOCK32.DLL,NM,1 converts a u_long from host toTCP/IP network byte order.
Not currently supported.                                                                              htons,WS2_32.DLL,NM,1 converts a u_short from host toTCP/IP network byte order.
HlinkGetSpecialReference,HLINK.DLL,NM,2, Retrieves a string for a given value from the                htons,WSOCK32.DLL,NM,1 converts a u_short from host toTCP/IP network byte order.
HLSR enumeration.                                                                                     HttpAddRequestHeaders,WININET.DLL,AW,4,Adds one or more HTTP request headers to the
HlinkGetValueFromParams,HLINK.DLL,NM,3, HlinkGetValueFromParams Function Not                          HTTP request handle.
currently supported.                                                                                  HttpEndRequest,WININET.DLL,AW,4,Ends an HTTP request that was initiated by
HlinkGoBack,URLMON.DLL,NM,1, Executes a hyperlink jump backward within the navigation                 HttpSendRequestEx.
stack.                                                                                                HttpOpenRequest,WININET.DLL,AW,8,Creates an HTTP request handle.
HlinkGoForward,URLMON.DLL,NM,1, Executes a hyperlink jump forward within the navigation               HttpQueryInfo,WININET.DLL,AW,5,Retrieves header information associated with an HTTP
stack.                                                                                                request.
HlinkIsShortcut,HLINK.DLL,NM,1, HlinkIsShortcut Function Not currently supported.                     HttpSendRequest,WININET.DLL,AW,5,Sends the specified request to the HTTP server.
HlinkNavigate,HLINK.DLL,NM,6,String Executes a hyperlink jump, specified by a string, to a            HttpSendRequestEx,WININET.DLL,AW,5,Sends the specified request to the HTTP server.
new document or object. For information about how this function relates to                            ICClose,MSVFW32.DLL,NM,1, closes a compressor or decompressor.
HlinkSimpleNavigateToString, see the Remarks section.                                                 ICCompressorChoose,MSVFW32.DLL,NM,6, displays a dialog box in which a user can select a
HlinkNavigateMoniker,URLMON.DLL,NM,2, Executes a hyperlink jump, specified by a moniker,              compressor.
to a new document or object. For information about how this function relates to the                   ICCompressorFree,MSVFW32.DLL,NM,1, frees the resources in the COMPVARS structure
HlinkSimpleNavigateToMoniker function, see the Remarks section.                                       used by other VCM functions.
HlinkNavigateString,URLMON.DLL,NM,2, Executes a hyperlink jump, specified by a string, to a           ICGetDisplayFormat,MSVFW32.DLL,NM,6, determines the best format available for displaying
new document or object. For information about how this function relates to                            a compressed image.
HlinkSimpleNavigateToString, see the Remarks section.                                                 ICGetInfo,MSVFW32.DLL,NM,3, obtains information about a compressor.
HlinkNavigateToStringReference,HLINK.DLL,NM,9, Creates a hyperlink site from strings                  ICImageCompress,MSVFW32.DLL,NM,7, compresses an image to a given size.
representing the hyperlink target, the location within the target, and a friendly name, and then      ICImageDecompress,MSVFW32.DLL,NM,5, decompresses an image without using initialization
navigates to that site.                                                                               functions.
HlinkOnNavigate,HLINK.DLL,NM,7, Notifies a hyperlink browse context and hyperlink frame, if           ICInfo,MSVFW32.DLL,NM,3, retrieves information about specific installed compressors or
it exists, that a hyperlink target has been navigated to.                                             enumerates the installed compressors.
HlinkOnRenameDocument,HLINK.DLL,NM,4, HlinkOnRenameDocument Function Not                              ICInstall,MSVFW32.DLL,NM,5, installs a new compressor or decompressor.
currently supported.                                                                                  ICLocate,MSVFW32.DLL,NM,5 finds a compressor or decompressor that can handle images
HlinkParseDisplayName,HLINK.DLL,NM,5, HlinkParseDisplayName Function Not currently                    with the specified formats, or finds a driver that can decompress an image with a specified
supported.                                                                                            format directly to hardware.
HlinkPreprocessMoniker,HLINK.DLL,NM,3, HlinkPreprocessMoniker Function Not currently                  IcmpCloseHandle,ICMP.DLL,NM,1,closes a handle opened by a call to IcmpCreateFile.
supported.                                                                                            IcmpCreateFile,ICMP.DLL,NM,0, opens a handle on which ICMP Echo Requests can be
HlinkQueryCreateFromData,HLINK.DLL,NM,1, Determines if a new hyperlink can be created                 issued.
from an IDataObject interface.                                                                        IcmpParseReplies,ICMP.DLL,NM,2, parses the reply buffer provided and returns the number of
HlinkResolveMonikerForData,HLINK.DLL,NM,7, HlinkResolveMonikerForData Function Not                    ICMP responses found.
currently supported.                                                                                  IcmpSendEcho,ICMP.DLL,NM,8,sends an ICMP Echo request and returns any replies.
HlinkResolveShortcut,HLINK.DLL,NM,6,ToString HlinkResolveShortcutToString Function Not                IcmpSendEcho2,ICMP.DLL,NM,11,sends an ICMP Echo request and returns either
currently supported.                                                                                  immediately (if Event or ApcRoutine is non-NULL) or returns after the specified time-out.
HlinkResolveShortcutToMoniker,HLINK.DLL,NM,3, HlinkResolveShortcutToMoniker Function                  ICOpen,MSVFW32.DLL,NM,3, opens a compressor or decompressor.
Not currently supported.                                                                              ICOpenFunction,MSVFW32.DLL,NM,4, opens a compressor or decompressor defined as a
HlinkResolveShortcutToString,HLINK.DLL,NM,3, HlinkResolveShortcutToString Function Not                function.
currently supported.                                                                                  ICRemove,MSVFW32.DLL,NM,3, removes an installed compressor.
HlinkResolveStringForData,HLINK.DLL,NM,7, HlinkResolveStringForData Function Not                      ICSendMessage,MSVFW32.DLL,NM,4, sends a message to a compressor.
currently supported.                                                                                  ICSeqCompressFrame,MSVFW32.DLL,NM,5, compresses one frame in a sequence of frames.
HlinkSetSpecialReference,HLINK.DLL,NM,2, Inserts a string into a specified member of the              ICSeqCompressFrameEnd,MSVFW32.DLL,NM,1 ends sequence compression thatwas initiated
HLSR enumeration.                                                                                     by using the ICSeqCompressFrameStart andICSeqCompressFrame functions.
HlinkSimpleNavigateToMoniker,URLMON.DLL,NM,8, Executes a hyperlink jump, specified by a               ICSeqCompressFrameStart,MSVFW32.DLL,NM,2 initializes resources forcompressing a
moniker, to a new document or object. For information about how this function relates to the          sequence of frames using the ICSeqCompressFramefunction.
HlinkNavigateMoniker function, see the Remarks section.                                               IIDFromString,OLE32.DLL,NM,2,4.2 IIDFromString This function converts a string generated
HlinkSimpleNavigateToString,URLMON.DLL,NM,8, Executes a hyperlink jump to a new                       by the function back into the original interface identifier (IID). WINOLEAPI
document or object. For information about how this function relates to HlinkNavigateString, see       ImageAddCertificate,IMAGEHLP.DLL,NM,3, is used to add a certificate to the specified file.
the Remarks section.                                                                                  ImageDirectoryEntryToData,IMAGEHLP.DLL,NM,4, obtains access to image-specific data.
HlinkTranslateURL,HLINK.DLL,NM,3, HlinkTranslateURL Function Not currently supported.                 ImageEnumerateCertificates,IMAGEHLP.DLL,NM,5, is used to return information about the
HlinkUpdateStackItem,HLINK.DLL,NM,6, HlinkUpdateStackItem Function Not currently                      certificates currently contained in an image file.
supported.                                                                                            ImageGetCertificateData,IMAGEHLP.DLL,NM,4, is used to retrieve a complete certificate from
HrAddColumns,MAPI32.DLL,NM,4 adds or moves columns to the beginning of an existing                    a file.
table.                                                                                                ImageGetCertificateHeader,IMAGEHLP.DLL,NM,3, is used to retrieve the header of the
HrAddColumnsEx,MAPI32.DLL,NM,5, adds or moves columns to the beginning of an existing                 specified certificate, up to, but not including, the section offset array.
table.                                                                                                ImageGetDigestStream,IMAGEHLP.DLL,NM,5, retrieves the requested data from the specified
HrAllocAdviseSink,MAPI32.DLL,NM,3 creates an advise sink object, givena context specified             image file.
by the calling implementation and a callbackfunction to be triggered by an event notification.        ImagehlpApiVersion,IMAGEHLP.DLL,NM,0, retrieves the information about the version of the
HrBackupClose,EDBBCLI.DLL,NM,1, closes the file that is being backed up.                              library installed on the system.
HrBackupEnd,EDBBCLI.DLL,NM,1, cleans up after a backup operation is finished.                         ImagehlpApiVersionEx,IMAGEHLP.DLL,NM,1, modifies the information about the version of the
HrBackupGetBackupLogs,EDBBCLI.DLL,AW,3, obtains the list of log files to back up.                     library used by the application.
HrBackupGetDatabaseNames,EDBBCLI.DLL,AW,3, obtains the list of attached databases on                  ImageList_Add,COMCTL32.DLL,NM,3, adds an image or images to an image list.
the remote computer.                                                                                  ImageList_AddIcon,COMCTL32.DLL,NM,2, adds an icon to an image list.
HrBackupOpenFile,EDBBCLI.DLL,AW,4 opens a remote file for backup and performs whatever                ImageList_AddMasked,COMCTL32.DLL,NM,3, copies the bitmap to an internal data structure.
client and server side operations are necessary to prepare for the backup.                            ImageList_BeginDrag,COMCTL32.DLL,NM,4, begins dragging an image.
HrBackupPrepare,EDBBCLI.DLL,AW,5, connects to a remote Microsoft Exchange Server                      ImageList_Create,COMCTL32.DLL,NM,5, creates a new image list.
database and prepares it for backup.                                                                  ImageList_Destroy,COMCTL32.DLL,NM,1, destroys an image list.
HrBackupRead,EDBBCLI.DLL,NM,4, reads one block from a backup file.                                    ImageList_DragEnter,COMCTL32.DLL,NM,3 locks updates to the specifiedwindow during a
HrBackupTruncateLogs,EDBBCLI.DLL,NM,1, deletes the committed database log files.                      drag operation and displays the drag image at thespecified position within the window.
HrComposeEID,MAPI32.DLL,NM,7, creates a compound entry identifier for an object, usually a            ImageList_DragLeave,COMCTL32.DLL,NM,1, unlocks the specified window and hides the drag
message in a message store.                                                                           image, allowing the window to be updated.
HrComposeMsgID,MAPI32.DLL,NM,6 creates an ASCII string representing acompound entry                   ImageList_DragMove,COMCTL32.DLL,NM,2, moves the image that is being dragged during a
identifier for an object, usually a message in amessage store.                                        drag-and-drop operation.
HrDecomposeEID,MAPI32.DLL,NM,7 separates the compound entry identifier of an object,                  ImageList_DragShowNolock,COMCTL32.DLL,NM,1, shows or hides the image being dragged.
usually a message in a message store, into the entry identifier of that object within the store and   ImageList_Draw,COMCTL32.DLL,NM,6, draws an image list item in the specified device
the store's entry identifier.                                                                         context.
                                                                                                 137
ImageList_DrawEx,COMCTL32.DLL,NM,10, draws an image list item in the specified device                  ImmIsIME,IMM32.DLL,NM,1, checks whether the specified handle identifies an IME.
context.                                                                                               ImmIsUIMessage,IMM32.DLL,AW,4, checks for messages intended for the IME window and
ImageList_DrawIndirect,COMCTL32.DLL,NM,1,Draws an image list image based on an                         sends those messages to the specified window.
IMAGELISTDRAWPARAMS structure                                                                          ImmLockIMC,IMM32.DLL,NM,1,C This function enables an input method editor (IME) to get a
ImageList_Duplicate,COMCTL32.DLL,NM,1,Creates a duplicate of an existing image list.                   pointer to an input method context (IMC) component that can be a member of the IMC.
ImageList_EndDrag,COMCTL32.DLL,NM,0, ends a drag operation.                                            ImmLockIMCC,IMM32.DLL,NM,1, This function enables an input method editor (IME) to get a
ImageList_GetBkColor,COMCTL32.DLL,NM,1, retrieves the current background color for an                  pointer to an input method context (IMC) component that can be a member of the IMC.
image list.                                                                                            ImmNotifyIME,IMM32.DLL,NM,4, notifies the IME about changes to the status of the input
ImageList_GetDragImage,COMCTL32.DLL,NM,2, retrieves the temporary image list that is                   context.
used for the drag image.                                                                               ImmRegisterWord,IMM32.DLL,AW,4, registers a string into the dictionary of the IME associated
ImageList_GetIcon,COMCTL32.DLL,NM,3, creates an icon or cursor based on an image and                   with the specified input locale.
mask in an image list.                                                                                 ImmReleaseContext,IMM32.DLL,NM,2, releases the input context and unlocks the memory
ImageList_GetIconSize,COMCTL32.DLL,NM,3, retrieves the dimensions of images in an image                associated in the context.
list.                                                                                                  ImmReSizeIMCC,IMM32.DLL,NM,2,This function changes the size of an input method context
ImageList_GetImageCount,COMCTL32.DLL,NM,1, retrieves the number of images in an image                  (IMC) component.
list.                                                                                                  ImmSetCandidateWindow,IMM32.DLL,NM,2, sets information about the candidate list window.
ImageList_GetImageInfo,COMCTL32.DLL,NM,3, retrieves information about an image.                        ImmSetCompositionFont,IMM32.DLL,AW,2, sets the logical font to be used to display
ImageList_LoadImage,COMCTL32.DLL,AW,7 Creates an image list from the specified bitmap.                 characters in the composition window.
ImageList_Merge,COMCTL32.DLL,NM,6, creates a new image by combining two existing                       ImmSetCompositionString,IMM32.DLL,AW,6, sets the characters, attributes, and clauses of the
images.                                                                                                composition and reading strings.
ImageList_Read,COMCTL32.DLL,NM,1, reads an image list from a stream.                                   ImmSetCompositionWindow,IMM32.DLL,NM,2, causes a IMN_SETSCOMPOSITIONWINDOW
ImageList_Remove,COMCTL32.DLL,NM,2, removes an image from an image list.                               message to be sent to the application.
ImageList_Replace,COMCTL32.DLL,NM,4, replaces an image in an image list with a new                     ImmSetConversionStatus,IMM32.DLL,NM,3 sets the current conversion status.
image.                                                                                                 ImmSetHotKey,IMM32.DLL,NM,4,This function is called by the IME control panel application to
ImageList_ReplaceIcon,COMCTL32.DLL,NM,3, replaces an image with an icon.                               set the value of the input method editor (IME) hot key.
ImageList_SetBkColor,COMCTL32.DLL,NM,2, sets the background color for an image list.                   ImmSetOpenStatus,IMM32.DLL,NM,2, opens or closes the IME.
ImageList_SetDragCursorImage,COMCTL32.DLL,NM,4 creates a new drag imageby                              ImmSetStatusWindowPos,IMM32.DLL,NM,2, sets the position of the status window.
combining the specified image (typically a mouse cursor image)with the current drag image.             ImmSimulateHotKey,IMM32.DLL,NM,2 simulates the specified IME hot key,causing the same
ImageList_SetIconSize,COMCTL32.DLL,NM,3, sets the dimensions of images in an image list                response as if the user had pressed the hot key inthe specified window.
and removes all images from the list.                                                                  ImmUnlockIMC,IMM32.DLL,NM,1, Handle to the IMC. (Windows CE .NET 4.2)
ImageList_SetImageCount,COMCTL32.DLL,NM,2,Resizes an existing image list.                              ImmUnlockIMCC,IMM32.DLL,NM,1,This function reduces the lock count for the input method
ImageList_SetOverlayImage,COMCTL32.DLL,NM,3, adds a specified image to the list of                     context (IMC) component.
images to be used as overlay masks.                                                                    ImmUnregisterWord,IMM32.DLL,AW,4 removes a register string from thedictionary of the IME
ImageList_Write,COMCTL32.DLL,NM,2, writes an image list to a stream.                                   associated with the specified keyboardlayout.
ImageLoad,IMAGEHLP.DLL,NM,2, maintains a list of loaded DLLs.                                          ImpersonateDdeClientWindow,USER32.DLL,NM,2 enables a Dynamic Data Exchange (DDE)
ImageNtHeader,IMAGEHLP.DLL,NM,1, locates the IMAGE_NT_HEADERS structure in a PE                        server application to impersonate a DDE client application's security context.
image and returns a pointer to the data.                                                               ImpersonateLoggedOnUser,ADVAPI32.DLL,NM,1, lets the calling thread impersonate a user.
ImageRemoveCertificate,IMAGEHLP.DLL,NM,2, is used to remove the specified certificate                  ImpersonateNamedPipeClient,ADVAPI32.DLL,NM,1, impersonates a named-pipe client
from the given file.                                                                                   application.
ImageRvaToSection,IMAGEHLP.DLL,NM,3, locates a relative virtual address (RVA) within the               ImpersonateSecurityContext,SECUR32.DLL,NM,1,Allows a server to impersonate a client by
image header of a file that is mapped as a file and returns a pointer to the section table entry for   using a token previously obtained by a call to AcceptSecurityContext (General) or
that RVA.                                                                                              QuerySecurityContextToken.
ImageRvaToVa,IMAGEHLP.DLL,NM,4, locates a relative virtual address (RVA) within the                    ImpersonateSelf,ADVAPI32.DLL,NM,1, obtains an access token that impersonates the security
image header of a file that is mapped as a file and returns the virtual address of the                 context of the calling process.
corresponding byte in the file.                                                                        ImportNtmsDatabase,NTMSAPI.DLL,NM,1, causes RSM to import the database files from the
ImageUnload,IMAGEHLP.DLL,NM,1, is used to deallocate resources from a previous call to the             database Export directory at the next restart of the RSM.
ImageLoad function.                                                                                    ImportSecurityContext,SECUR32.DLL,AW,4,Imports a security context. The security context
ImmAssociateContext,IMM32.DLL,NM,2, associates the specified input context with the                    must have been exported to the process calling ImportSecurityContext by a previous call to
specified window.                                                                                      ExportSecurityContext.
ImmAssociateContextEx,IMM32.DLL,NM,3, changes the association between the input method                 InetIsOffline,URL.DLL,NM,1,Determines whether or not the system is connected to the Internet.
context and the specified window or its children.                                                      inet_addr,WS2_32.DLL,NM,1, converts a string containing an (Ipv4) Internet Protocol dotted
ImmConfigureIME,IMM32.DLL,AW,4, displays the configuration dialog box for the IME of the               address into a proper address for the IN_ADDR structure.
specified input locale identifier (HKL).                                                               inet_addr,WSOCK32.DLL,NM,1, converts a string containing an (Ipv4) Internet Protocol dotted
ImmCreateContext,IMM32.DLL,NM,0, creates a new input context, allocating memory for the                address into a proper address for the IN_ADDR structure.
context and initializing it.                                                                           inet_ntoa,WS2_32.DLL,NM,1 converts an (Ipv4) Internet network address into a string in
ImmCreateIMCC,IMM32.DLL,NM,1, (Windows CE .NET Application Development)This function                   Internet standard dotted format.
enables an input method editor (IME) to create a new input method context (IMC) component              inet_ntoa,WSOCK32.DLL,NM,1 converts an (Ipv4) Internet network address into a string in
that is a member of an IMC. (Windows CE .NET 4.2)                                                      Internet standard dotted format.
ImmDestroyContext,IMM32.DLL,NM,1, releases the input context and frees any memory                      InflateRect,USER32.DLL,NM,3, increases or decreases the width and height of the specified
associated with it.                                                                                    rectangle.
ImmDestroyIMCC,IMM32.DLL,NM,1, Handle to the IMC component.                                            InitAtomTable,KERNEL32.DLL,NM,1, initializes the local atom table and sets it to the specified
ImmDisableIME,IMM32.DLL,NM,1, disables the input method editor (IME) for a thread or all               size.
threads in a process.                                                                                  InitCommonControls,COMCTL32.DLL,NM,0 Registers and initializes the common control
ImmEnumInputContext,IMM32.DLL,NM,3, retrieves the input context for the specified thread.              window classes. This function is obsolete.
ImmEnumRegisterWord,IMM32.DLL,AW,6 enumerates the register strings having the specified                InitCommonControlsEx,COMCTL32.DLL,NM,1,Registers specific common control classes from
reading string, style, and register string.                                                            the common control dynamic-link library
ImmEscape,IMM32.DLL,AW,4, accesses capabilities of particular IMEs that are not available              InitializeAcl,ADVAPI32.DLL,NM,3, creates a new ACL structure.
through other IMM APIs. and is used mainly for country-specific operations.                            InitializeCriticalSection,KERNEL32.DLL,NM,1, initializes a critical section object.
ImmGenerateMessage,IMM32.DLL,NM,1,This function enables an input method editor (IME) to                InitializeFlatSB,COMCTL32.DLL,NM,1,Initializes flat scroll bars for a particular window.
generate messages that are sent to the window associated with the input method context                 InitializeProcessForWsWatch,PSAPI.DLL,NM,1, initiates monitoring of the working set of the
(IMC).                                                                                                 specified process. You must call this function before calling the GetWsChanges function.
ImmGetCandidateList,IMM32.DLL,AW,4, retrieves a specified candidate list, copying the list to          InitializeSecurityContext,SECUR32.DLL,AW,12,Initiates the client side, outbound security
the specified buffer.                                                                                  context from a credential handle by using the Negotiate security package.
ImmGetCandidateListCount,IMM32.DLL,AW,2 retrieves the size of the candidate lists.                     InitializeSecurityDescriptor,ADVAPI32.DLL,NM,2, initializes a new security descriptor.
ImmGetCandidateWindow,IMM32.DLL,NM,3, gets information about the candidate list window.                InitializeSid,ADVAPI32.DLL,NM,3 initializes a security identifier (SID).
ImmGetCompositionFont,IMM32.DLL,AW,2 retrieves information about the logical font                      InitiateSystemShutdown,ADVAPI32.DLL,AW,5, displays a dialog box that notifies the user that
currently used to display characters in the composition window.                                        the system is shutting down.
ImmGetCompositionString,IMM32.DLL,AW,4, retrieves information about the composition                    InitSecurityInterface,SECUR32.DLL,AW,0, returns a pointer to an SSPI dispatch table. This
string.                                                                                                function enables clients to use SSPI without binding directly to an implementation of the
ImmGetCompositionWindow,IMM32.DLL,NM,2 retrieves information about the composition                     interface.
window.                                                                                                InjectNtmsCleaner,NTMSAPI.DLL,NM,5, allows a cleaner cartridge to be inserted into the
ImmGetContext,IMM32.DLL,NM,1, retrieves the input context associated with the specified                specified library unit.
window.                                                                                                InjectNtmsMedia,NTMSAPI.DLL,NM,4, allows media to be inserted into the port of the specified
ImmGetConversionList,IMM32.DLL,AW,6, retrieves the conversion result list of characters or             library. If the library is busy, RSM queues InjectNtmsMedia and returns success.
words without generating any IME-related messages.                                                     InSendMessage,USER32.DLL,NM,0 specifies whether the current windowprocedure is
ImmGetConversionStatus,IMM32.DLL,NM,3, gets the current conversion status.                             processing a message that was sent from another threadby a call to the SendMessage
ImmGetDefaultIMEWnd,IMM32.DLL,NM,1, gets the default window handle to the IME class.                   function.
ImmGetDescription,IMM32.DLL,AW,3, copies the description of the IME to the specified buffer.           InsertMenu,USER32.DLL,AW,5, inserts a new menu item into a menu, moving other items
ImmGetGuideLine,IMM32.DLL,AW,4 retrieves information about errors.                                     down the menu.
ImmGetHotKey,IMM32.DLL,NM,4, This function retrieves the value of the input method editor              InsertMenuItem,USER32.DLL,AW,4, inserts a new menu item at the specified position in a
(IME) hot key.                                                                                         menu.
ImmGetIMCCLockCount,IMM32.DLL,NM,1, Handle to the IMC component.                                       InstallColorProfile,MSCMS.DLL,AW,2, installs a given profile for use on a specified machine.
ImmGetIMCCSize,IMM32.DLL,NM,1, Handle to the IMC component.                                            The profile is also copied to the COLOR directory.
ImmGetIMCLockCount,IMM32.DLL,NM,1,This function enables an input method editor (IME) to                InterlockedCompareExchange,KERNEL32.DLL,NM,3 performs an atomic comparison of the
get the lock count of the input method context (IMC).                                                  values specified in the Destination and Comperand parameters and exchange of the values,
ImmGetIMEFileName,IMM32.DLL,AW,3, gets the filename of the IME associated with the                     based on the outcome of the comparison.
specified keyboard layout.                                                                             InterlockedDecrement,KERNEL32.DLL,NM,1 both decrements (decreases byone) the value of
ImmGetImeMenuItems,IMM32.DLL,AW,6, retrieves the menu items that are registered in the                 the specified 32-bit variable and checks theresulting value.
IME menu of a specified input context.                                                                 InterlockedExchange,KERNEL32.DLL,NM,2, atomically exchanges a pair of 32- bit values.
ImmGetOpenStatus,IMM32.DLL,NM,1, checks whether the IME is open or closed.                             InterlockedExchangeAdd,KERNEL32.DLL,NM,2, performs an atomic addition of the Increment
ImmGetProperty,IMM32.DLL,NM,2, gets the property and capabilities of the IME associated                value to the value pointed to by Addend.
with the specified keyboard layout.                                                                    InterlockedIncrement,KERNEL32.DLL,NM,1 both increments (increases by one) the value of
ImmGetRegisterWordStyle,IMM32.DLL,AW,3, gets a list of the styles support by the IME                   the specified 32-bit variable and checks the resulting value.
associated with the specified keyboard layout.                                                         InternetAttemptConnect,WININET.DLL,NM,1,Attempts to make a connection to the Internet.
ImmGetStatusWindowPos,IMM32.DLL,NM,2, gets the position of the status window.                          InternetAutodial,WININET.DLL,NM,2,Causes the modem to automatically dial the default
ImmGetVirtualKey,IMM32.DLL,NM,1 recovers the original virtual-keyvalue associated with a               Internet connection.
key input message that has already beenprocessed by the IME.                                           InternetAutodialHangup,WININET.DLL,NM,1,Disconnects an automatic dial-up connection.
ImmInstallIME,IMM32.DLL,AW,2, installs an IME into the system.
                                                                                             138
InternetCanonicalizeUrl,WININET.DLL,AW,4,Canonicalizes a URL, which includes converting            IsDialogMessage,USER32.DLL,AW,2 determines whether a message isintended for the
unsafe characters and spaces into escape sequences.                                                specified dialog box and, if it is, processes themessage.
InternetCheckConnection,WININET.DLL,AW,3,Allows an application to check if a connection to         IsDlgButtonChecked,USER32.DLL,NM,2 determines whether a button control has a check
the Internet can be established.                                                                   mark next to it or whether a three-state button control is grayed, checked, or neither.
InternetCloseHandle,WININET.DLL,NM,1,Closes a single Internet handle.                              IsEqualGUID,OLE32.DLL,NM,2, GUID to compare to rguid2. rguid2 [in] GUID to compare to
InternetCombineUrl,WININET.DLL,AW,5,Combines a base and relative URL into a single URL.            rguid1.
The resultant URL is canonicalized (see InternetCanonicalizeUrl).                                  IsIconic,USER32.DLL,NM,1, determines whether the specified window is minimized (iconic).
InternetConfirmZoneCrossing,WININET.DLL,AW,4,Checks for changes between secure and                 IsMenu,USER32.DLL,NM,1, determines whether a handle is a menu handle.
nonsecure URLs. Always inform the user when a change occurs in security between two URLs.          IsProcessorFeaturePresent,KERNEL32.DLL,NM,1 determines whether thespecified processor
Typically, an application should allow the user to acknowledge the change through interaction      feature is supported by at least one processoron the current machine.
with a dialog box.                                                                                 IsRectEmpty,USER32.DLL,NM,1, determines whether the specified rectangle is empty.
InternetConnect,WININET.DLL,AW,8,Opens an File Transfer Protocol (FTP), Gopher, or HTTP            IsTextUnicode,ADVAPI32.DLL,NM,3, determines whether a buffer probably contains a form of
session for a given site.                                                                          Unicode text.
InternetCrackUrl,WININET.DLL,AW,4,Cracks a URL into its component parts.                           IsValidAcl,ADVAPI32.DLL,NM,1 validates an access-control list (ACL).
InternetCreateUrl,WININET.DLL,AW,4,Creates a URL from its component parts.                         IsValidCodePage,KERNEL32.DLL,NM,1 determines whether a specified code page isvalid.
InternetDial,WININET.DLL,NM,5,Initiates a connection to the Internet using a modem.                IsValidIid,OLE32.DLL,NM,1,4.2 IsValidIid This function is obsolete. Last updated on
InternetErrorDlg,WININET.DLL,NM,5,Displays a dialog box for the error that is passed to            Wednesday, April 13, 2005 B) 2005
InternetErrorDlg, if an appropriate dialog box exists.                                             IsValidInterface,OLE32.DLL,NM,1,4.2 IsValidInterface This function is obsolete. Last updated
InternetFindNextFile,WININET.DLL,AW,2,Continues a file search started as a result of a             on Wednesday, April 13, 2005 B)
previous call to FtpFindFirstFile or GopherFindFirstFile.                                          IsValidLocale,KERNEL32.DLL,NM,2, applies a validity test to a locale identifier.
InternetGetConnectedState,WININET.DLL,NM,2,Retrieves the connected state of the local              IsValidPtrIn,OLE32.DLL,NM,2,4.2 IsValidPtrIn This function is obsolete. Last updated on
system.                                                                                            Wednesday, April 13, 2005 B) 2005
InternetGetConnectedStateEx,WININET.DLL,NM,4,Retrieves the connected state of the                  IsValidPtrOut,OLE32.DLL,NM,2,4.2 IsValidPtrOut This function is obsolete.
specified Internet connection.                                                                     IsValidSecurityDescriptor,ADVAPI32.DLL,NM,1, determines whether the components of a
InternetGetCookie,WININET.DLL,AW,4,Retrieves the cookie for the specified URL.                     security descriptor are valid.
InternetGetLastResponseInfo,WININET.DLL,AW,3,Retrieves the last error description or server        IsValidSid,ADVAPI32.DLL,NM,1 validates a SID structure by verifying thatthe revision number
response on the thread calling this function.                                                      is within a known range and that the number ofsubauthorities is less than the maximum.
InternetGoOnline,WININET.DLL,NM,3,Prompts the user for permission to initiate connection to        IsValidURL,URLMON.DLL,NM,3, Determines if a specified string is a valid URL.
a URL.                                                                                             IsWindow,USER32.DLL,NM,1, determines whether the specified window handle identifies an
InternetHangUp,WININET.DLL,NM,2,Instructs the modem to disconnect from the Internet.               existing window.
InternetLockRequestFile,WININET.DLL,NM,2,Places a lock on the file that is being used.             IsWindowEnabled,USER32.DLL,NM,1, determines whether the specified window is enabled for
InternetOpen,WININET.DLL,AW,5,Initializes an application's use of the WinINet functions.           mouse and keyboard input.
InternetOpenUrl,WININET.DLL,AW,6,Opens a resource specified by a complete FTP, Gopher,             IsWindowUnicode,USER32.DLL,NM,1, determines whether the specified window is a native
or HTTP URL.                                                                                       Unicode window.
InternetQueryDataAvailable,WININET.DLL,NM,4,Queries the server to determine the amount of          IsWindowVisible,USER32.DLL,NM,1, retrieves the visibility state of the specified window.
data available.                                                                                    IsZoomed,USER32.DLL,NM,1, determines whether a window is maximized.
InternetQueryOption,WININET.DLL,AW,4,Queries an Internet option on the specified handle.           joyGetDevCaps,WINMM.DLL,AW,3, queries a joystick to determine its capabilities.
InternetReadFile,WININET.DLL,NM,4,Reads data from a handle opened by the                           joyGetNumDevs,WINMM.DLL,NM,0, queries the joystick driver for the number of joysticks it
InternetOpenUrl, FtpOpenFile, GopherOpenFile, or HttpOpenRequest function.                         supports.
InternetReadFileEx,WININET.DLL,AW,4,Reads data from a handle opened by the                         joyGetPos,WINMM.DLL,NM,2, queries a joystick for its position and button status
InternetOpenUrl or HttpOpenRequest function.                                                       joyGetPosEx,WINMM.DLL,NM,2, queries a joystick for its position and button status.
InternetSetCookie,WININET.DLL,AW,3,Creates a cookie associated with the specified URL.             joyGetThreshold,WINMM.DLL,NM,2, queries a joystick for its current movement threshold.
InternetSetDialState,WININET.DLL,NM,3,This function is obsolete. Do not use.                       joyReleaseCapture,WINMM.DLL,NM,1, releases the specified captured joystick.
InternetSetFilePointer,WININET.DLL,NM,5,Sets a file position for InternetReadFile. This is a       joySetCapture,WINMM.DLL,NM,4 captures a joystick by causing itsmessages to be sent to the
synchronous call; however, subsequent calls to InternetReadFile might block or return pending      specified window.
if the data is not available from the cache and the server does not support random access.         joySetThreshold,WINMM.DLL,NM,2, sets the movement threshold of a joystick.
InternetSetOption,WININET.DLL,AW,4,Sets an Internet option.                                        keybd_event,USER32.DLL,NM,4, synthesizes a keystroke.
InternetSetOptionEx,WININET.DLL,AW,5,Implemented only as a stub that calls the                     KillTimer,USER32.DLL,NM,2, destroys the specified timer.
InternetSetOption function; InternetSetOptionEx has no functionality of its own. Do not use this   LaunchWizard,MAPI32.DLL,NM,5 Call LaunchWizard to add the MSEMS service.
function at this time.                                                                             LBItemFromPt,COMCTL32.DLL,NM,4, retrieves the index of the item at the specified point in a
InternetSetStatusCallback,WININET.DLL,AW,2,Sets up a callback function that WinINet                list box.
functions can call as progress is made during an operation.                                        LCMapString,KERNEL32.DLL,AW,6, maps one character string to another, performing a
InternetTimeFromSystemTime,WININET.DLL,AW,4,Formats a date and time according to the               specified locale-dependent transformation.
HTTP version 1.0 specification.                                                                    LeaveCriticalPolicySection,USERENV.DLL,NM,1, resumes the background application of
InternetTimeToSystemTime,WININET.DLL,AW,3,Converts an HTTP time/date string to a                   policy. This function closes the handle to the policy section.
SYSTEMTIME structure.                                                                              LeaveCriticalSection,KERNEL32.DLL,NM,1, releases ownership of the specified critical section
InternetUnlockRequestFile,WININET.DLL,NM,1,Unlocks a file that was locked using                    object.
InternetLockRequestFile.                                                                           LHashValOfNameSys,OLEAUT32.DLL,AW,3,Computes a hash value for a name that can then
InternetWriteFile,WININET.DLL,NM,4,Writes data to an open Internet file.                           be passed to ITypeComp::Bind, ITypeComp::BindType, ITypeLib::FindName, or
IntersectClipRect,GDI32.DLL,NM,5 creates a new clipping region fromthe intersection of the         lineAccept,TAPI32.DLL,NM,3, accepts the specified offered call.
current clipping region and the specifiedrectangle.                                                lineAddProvider,TAPI32.DLL,AW,3, installs a new telephony service provider into the telephony
IntersectRect,USER32.DLL,NM,3 calculates the intersection of two source rectangles and             system.
places the coordinates of the intersection rectangle into the destination rectangle.               lineAddToConference,TAPI32.DLL,NM,2, adds the call specified by hConsultCall to the
InvalidateRect,USER32.DLL,NM,3, adds a rectangle to the specified window?s update region.          conference call specified by hConfCall.
InvalidateRgn,USER32.DLL,NM,3, invalidates the client area within the window.                      lineAgentSpecific,TAPI32.DLL,NM,5 allows the application to accessproprietary handler-
InventoryNtmsLibrary,NTMSAPI.DLL,NM,3, queues an inventory of the specified library. If the        specific functions of the agent handlerassociated with the address.
library is busy, RSM queues InventoryNtmsLibrary and returns success.                              lineAnswer,TAPI32.DLL,NM,3, answers the specified offering call.
InvertRect,USER32.DLL,NM,2 inverts a rectangle in a window byperforming a logical NOT              lineBlindTransfer,TAPI32.DLL,AW,3 performs a blind or single-steptransfer of the specified call
operation on the color values for eachpixel in the rectangle?s interior.                           to the specified destinationaddress.
InvertRgn,GDI32.DLL,NM,2, inverts the colors in the specified region.                              lineClose,TAPI32.DLL,NM,1, closes the specified open line device.
ioctlsocket,WS2_32.DLL,NM,3, can be used on any socket in any state.                               lineCompleteCall,TAPI32.DLL,NM,4, specifies how a call that could not be connected normally
ioctlsocket,WSOCK32.DLL,NM,3, can be used on any socket in any state.                              should be completed instead.
IsAccelerator,OLE32.DLL,NM,4,Determines whether the keystroke maps to an accelerator in            lineCompleteTransfer,TAPI32.DLL,NM,4, completes the transfer of the specified call to the
the given accelerator table.                                                                       party connected in the consultation call.
IsAsyncMoniker,URLMON.DLL,NM,1, Tests to determine whether a moniker supports                      lineConfigDialog,TAPI32.DLL,AW,3 causes the provider of the specified line device to display a
asynchronous binding.                                                                              dialog box (attached to hwndOwner of the application) to allow the user to configure parameters
IsBadCodePtr,KERNEL32.DLL,NM,1, determines whether the calling process has read access             related to the line device.
to the memory at the specified address.                                                            lineConfigDialogEdit,TAPI32.DLL,AW,6 causes the provider of the specified line device to
IsBadHugeReadPtr,KERNEL32.DLL,NM,2, verifies that the calling process has read access to           display a dialog box (attached to hwndOwner of the application) to allow the user to configure
the specified range of memory.                                                                     parameters related to the line device.
IsBadHugeWritePtr,KERNEL32.DLL,NM,2, verifies that the calling process has write access to         lineConfigProvider,TAPI32.DLL,NM,2, causes a service provider to display its configuration
the specified range of memory.                                                                     dialog box.
IsBadReadPtr,KERNEL32.DLL,NM,2, verifies that the calling process has read access to the           LineDDA,GDI32.DLL,NM,6 determines which pixels should be highlighted for a line defined by
specified range of memory.                                                                         the specified starting and ending points.
IsBadStringPtr,KERNEL32.DLL,AW,2, verifies that the calling process has read access to a           lineDeallocateCall,TAPI32.DLL,NM,1, deallocates the specified call handle.
range of memory pointed to by a string pointer.                                                    lineDevSpecific,TAPI32.DLL,NM,5, enables service providers to provide access to features not
IsBadWritePtr,KERNEL32.DLL,NM,2, verifies that the calling process has write access to the         offered by other TAPI functions.
specified range of memory.                                                                         lineDevSpecificFeature,TAPI32.DLL,NM,4, enables service providers to provide access to
IsCharAlpha,USER32.DLL,AW,1, determines whether a character is an alphabetic character.            features not offered by other TAPI functions.
IsCharAlphaNumeric,USER32.DLL,AW,1, determines whether a character is either an                    lineDial,TAPI32.DLL,AW,3, dials the specified dialable number on the specified call.
alphabetic or a numeric character.                                                                 lineDrop,TAPI32.DLL,NM,3, drops or disconnects the specified call.
IsCharLower,USER32.DLL,AW,1, determines whether a character is lowercase.                          lineForward,TAPI32.DLL,AW,7 forwards calls destined for the specified address on the
IsCharUpper,USER32.DLL,AW,1, determines whether a character is uppercase.                          specified line, according to the specified forwarding instructions.
IsChild,USER32.DLL,NM,2, tests whether a window is a child window or descendant window of          lineGatherDigits,TAPI32.DLL,AW,7 initiates the buffered gathering of digits on the specified call.
a specified parent window.                                                                         lineGenerateDigits,TAPI32.DLL,AW,4 initiates the generation of thespecified digits on the
IsClipboardFormatAvailable,USER32.DLL,NM,1, determines whether the clipboard contains              specified call as inband tones using thespecified signaling mode.
data in the specified format.                                                                      lineGenerateTone,TAPI32.DLL,NM,5, generates the specified inband tone over the specified
IsColorProfileTagPresent,MSCMS.DLL,NM,3, reports whether a specified International Color           call.
Consortium (ICC) tag is present in the specified color profile.                                    lineGetAddressCaps,TAPI32.DLL,AW,6, queries the specified address on the specified line
IsColorProfileValid,MSCMS.DLL,NM,2, allows an application to determine whether the specified       device to determine its telephony capabilities.
profile is a valid International Color Consortium (ICC) profile that can be used for color         lineGetAddressID,TAPI32.DLL,AW,5 returns the address identifierassociated with an address in
management.                                                                                        a different format on the specifiedline.
IsDBCSLeadByte,KERNEL32.DLL,NM,1 determines whether a character is alead byte / that is,           lineGetAddressStatus,TAPI32.DLL,AW,3, allows an application to query the specified address
the first byte of a character in a double-byte character set (DBCS).                               for its current status.
IsDBCSLeadByteEx,KERNEL32.DLL,NM,2 determines whether a character is alead byte / that             lineGetAgentActivityList,TAPI32.DLL,AW,3 obtains the identities of activities that the application
is, the first byte of a character in a double-byte character set (DBCS).                           can select using lineSetAgentActivity to indicate what function the agent is actually performing
IsDebuggerPresent,KERNEL32.DLL,NM,0, indicates whether the calling process is running              at the moment.
under the context of a debugger.
                                                                                               139
lineGetAgentCaps,TAPI32.DLL,AW,5, obtains the agent-related capabilities supported on the            lineSetNumRings,TAPI32.DLL,NM,3, sets the number of rings that must occur before an
specified line device.                                                                               incoming call is answered.
lineGetAgentGroupList,TAPI32.DLL,AW,3 obtains the identities of agent groups (combination of         lineSetTerminal,TAPI32.DLL,NM,7 enables an application to specifywhich terminal information
queue, supervisor, skill level, and so on) into which the agent currently logged in on the           related to the specified line, address,or call is to be routed.
workstation is permitted to log into on the automatic call distributor.                              lineSetTollList,TAPI32.DLL,AW,4, manipulates the toll list.
lineGetAgentStatus,TAPI32.DLL,AW,3, obtains the agent-related status on the specified                lineSetupConference,TAPI32.DLL,AW,6, sets up a conference call for the addition of the third
address.                                                                                             party.
lineGetAppPriority,TAPI32.DLL,AW,6 allows an application to determine whether or not it is in        lineSetupTransfer,TAPI32.DLL,AW,3, initiates a transfer of the call specified by the hCall
the handoff priority list for a particular media mode or Assisted Telephony request mode and, if     parameter.
so, its position in the priority list.                                                               lineShutdown,TAPI32.DLL,NM,1, shuts down the application's usage of the line abstraction of
lineGetCallInfo,TAPI32.DLL,AW,2, enables an application to obtain fixed information about the        the API.
specified call.                                                                                      lineSwapHold,TAPI32.DLL,NM,2, swaps the specified active call with the specified call on
lineGetCallStatus,TAPI32.DLL,NM,2, returns the current status of the specified call.                 consultation hold.
lineGetConfRelatedCalls,TAPI32.DLL,NM,2 returns a list of call handles that are part of the          LineTo,GDI32.DLL,NM,3, draws a line from the current position up to, but not including, the
same conference call as the specified call.                                                          specified point.
lineGetCountry,TAPI32.DLL,AW,3 fetches the stored dialing rules and other information related        lineTranslateAddress,TAPI32.DLL,AW,7, translates the specified address into another format.
to a specified country, the first country in the country list, or all countries.                     lineUncompleteCall,TAPI32.DLL,NM,2, cancels the specified call completion request on the
lineGetDevCaps,TAPI32.DLL,AW,5, queries a specified line device to determine its telephony           specified line.
capabilities.                                                                                        lineUnhold,TAPI32.DLL,NM,1, retrieves the specified held call.
lineGetDevConfig,TAPI32.DLL,AW,3 returns an "opaque" data structure object, the contents of          lineUnpark,TAPI32.DLL,AW,4, retrieves the call parked at the specified address and returns a
which are specific to the line (service provider) and device class.                                  call handle for it.
lineGetIcon,TAPI32.DLL,AW,3 allows an application to retrieve aservice line device-specific (or      listen,WS2_32.DLL,NM,2,WSAEINVAL                  was not invoked prior to accept.
provider-specific) icon fordisplay to the user.                                                      listen,WSOCK32.DLL,NM,2,WSAEINVAL                   was not invoked prior to accept.
lineGetID,TAPI32.DLL,AW,6 returns a device identifier for thespecified device class associated       LoadAccelerators,USER32.DLL,AW,2, loads the specified accelerator table.
with the selected line, address,or call.                                                             LoadBitmap,USER32.DLL,AW,2, loads the specified bitmap resource from a module?s
lineGetLineDevStatus,TAPI32.DLL,AW,2, enables an application to query the specified open             executable file.
line device for its current status.                                                                  LoadCursor,USER32.DLL,AW,2, loads the specified cursor resource from the executable (.
lineGetMessage,TAPI32.DLL,NM,3 returns the next TAPI message that is queued for delivery             LoadCursorFromFile,USER32.DLL,AW,1, creates a cursor based on data contained in a file.
to an application that is using the Event Handle notification mechanism                              LoadIcon,USER32.DLL,AW,2, can load only icons of these dimensions.
lineGetNewCalls,TAPI32.DLL,NM,4 returns call handles to calls on aspecified line or address          LoadImage,USER32.DLL,AW,6, loads an icon, cursor, or bitmap.
for which the application currently doesnot have handles.                                            LoadKeyboardLayout,USER32.DLL,AW,2, loads a new keyboard layout into the system.
lineGetNumRings,TAPI32.DLL,NM,3 determines the number of rings anincoming call on the                LoadLibrary,KERNEL32.DLL,AW,1, maps the specified executable module into the address
given address should ring prior to answeringthe call.                                                space of the calling process.
lineGetProviderList,TAPI32.DLL,AW,2, returns a list of service providers currently installed in      LoadLibraryEx,KERNEL32.DLL,AW,3, maps a specified executable module into the address
the telephony system.                                                                                space of the calling process.
lineGetRequest,TAPI32.DLL,AW,3, retrieves the next by-proxy request for the specified request        LoadMenu,USER32.DLL,AW,2, loads the specified menu resource