Logique, math´ematiques,informatique
Eric Abouaf
15 juin 2005
Etude d’un interpr´
eteur Forth
Ann´ee Scolaire 2004-2005
R´
esum´
e
Ce document est le rapport d’un mini-projet r´
ealis´
e pour un cours
d’approfondissement. Il s’agit de l’impl´
ementation d’un interpr´
eteur
pour un langage proche du Forth. Le programme est ´
ecrit en C et
les sources sont disponibles `
a la fin de ce document. Une petite
in-troduction au langage Forth sera dispens´
ee afin de comprendre la
probl´
ematique de l’interpreteur.
Table des mati`
eres
1
Introduction
3
1.1
Un mot pour commencer . . . .
3
1.2
Objectif . . . .
3
1.3
Choix du forth
. . . .
3
1.4
Port´
ee . . . .
4
1.5
Organisation du document . . . .
4
2
Introduction au langage Forth
5
2.1
Introduction . . . .
5
2.2
La Pile de donn´
ees . . . .
5
2.3
Notions de mot et de dictionnaire . . . .
6
2.4
Les variables . . . .
6
3
D´
efinition du Micro-forth
7
3.1
Simplifications . . . .
7
3.2
El´
ements repris du forth . . . .
7
4
Impl´
ementation d’un syst`
eme Micro-forth
8
4.1
Choix dans l’impl´
ementation . . . .
8
4.2
El´
ements d’un interpr´
eteur . . . .
8
4.2.1
Structure du dictionnaire . . . .
8
4.2.2
La pile de donn´
ees . . . .
9
4.2.3
La pile de retour . . . .
10
4.2.4
Le buffer d’entr´
ee (input buffer) . . . .
10
4.3
Structure de l’interpr´
eteur . . . .
10
4.3.1
Mots imm´
ediats . . . .
10
4.3.2
Registre IP (instruction pointer) . . . .
11
4.3.3
Fonctionnement interne
. . . .
11
5
Conclusion
12
A Bibliographie
13
1
Introduction
1.1
Un mot pour commencer
Ce document a ´
et´
e r´
ealis´
e pour le cours d’approfondissement ”Logique,
math´
ematiques, informatique” dispens´
e `
a l’Ecole Centrale Paris par Mr.
Pas-cal Laurent en mai-juin 2005.
Vous pouvez l’utiliser ou le distribuer comme vous le souhaitez, mais merci
de conserver l’int´
egralit´
e du document afin qu’il garde son sens. Ce document
n’ayant pas ´
et´
e relu par une personne plus comp´
etente, je ne garantis pas la
v´
eracit´
e de l’ensemble du document.
L’adresse originale de ce travail est : http ://www.neyric.com/comp/forth/
Vous pouvez me contacter pour toute remarque ou question `
a propos de ce
document `
a l’adresse suivante : eric.abouaf@student.ecp.fr
Le langage implant´
e est en grande partie bas´
e sur la d´
efinition du langage
Forth de l’American National Standard for Information Systems datant du
24 Mars 1994. [1] Particuli`
erement les sections 1 `
a 6, (Les sections 7 `
a 17
d´
efinissent des word sets suppl´
ementaires non pris en compte dans micro
forth.) mˆ
eme si le jeu de mots est bien plus limit´
e (pour l’instant !).
1.2
Objectif
Ce document a pour objectif de se familiariser avec la r´
ealisation d’un
interpr´
eteur pour un langage informatique afin de comprendre les concepts
de bases d’un compilateur.
1.3
Choix du forth
J’ai choisit le langage forth pour plusieurs raisons :
– interpr´
eteur tr`
es petit (dictionnaire des core words tr`
es succin),
– portabilit´
e du langage (tr`
es pr`
es du langage machine et pourtant
por-table sur n’importe quelle ”machine virtuelle” forth),
1.4
Port´
ee
Ce document d´
efinit l’impl´
ementation d’un syst`
eme forth minimaliste
ne r´
epondant pas au format d´
efini par l’ANS. Sa vocation est purement
´
educative bien que la plupart des ´
el´
ements pr´
esent´
es peuvent servir de base
`
a la cr´
eation d’une impl´
ementation compl`
ete du langage forth.
Inclusions :
– ce document d´
ecrit le langage ”Micro-forth”,
– ce document d´
ecrit l’impl´
ementation d’un syst`
eme Micro-forth capable
de d´
ecrire le langage Micro-forth. Les deux noms seront confondus par
la suite.
– ce document s’int´
eresse particuli`
erement au coeur du syst`
eme forth et
au mode d’execution.
Exclusions :
– ce document ne vise pas `
a impl´
ementer le langage forth tel que d´
efinit
par l’ANS. Pour plus d’informations, sur le langage forth, je vous dirige
vers le site de l’ANS [1],
– pour toutes les exclusions du langage forth dans Micro-forth, je vous
invite `
a vous rendre partie 3.1 pour une lire la simplification du langage.
1.5
Organisation du document
Ce document va pr´
esenter le cheminement pour parvenir `
a l’impl´
ementation
d’un syst`
eme forth simplifi´
ee. Le but est de montrer quels ´
el´
ements du
lan-gage permettent d’expliquer les choix r´
ealis´
es lors de l’impl´
ementation.
2
Introduction au langage Forth
Si vous ˆ
etes d´
ej`
a familiaris´
e avec le forth, vous pouvez sauter cette partie.
2.1
Introduction
Le Forth est un langage avec une syntaxe assez d´
eroutante mais tr`
es
efficace. C’est un langage fonctionnel qui se base sur une pile de donn´
ee pour
passer les arguments aux fonctions. Ainsi, les fonctions sont repr´
esent´
es par
des simples mots, tout comme les variables, les constantes ou les op´
erateurs
de structures.
2.2
La Pile de donn´
ees
La pile de donn´
ees est une pile LIFO (Last Input First Output) qui stocke
les param`
etres d’appel d’un mot. Exemple :
2 3 + .
Les nombres 2 puis 3 sont empil´
es puis le mot ’+’ enl`
eve ces deux nombres
de la pile de donn´
ees et place le r´
esultat de l’op´
eration au sommet de la pile.
Le plus effectue l’addition puis le ’.’ affiche le r´
esultat. On utilise g´
en´
eralement
une notation bien pratique pour d´
ecrire l’action d’un mot sur la pile :
Mot ( before -- after )
Pour notre exemple pr´
ec´
edent :
+ ( a b -- a+b )
Il existe beaucoup de mots de manipulations de la pile. Citons parmi eux :
– DUP : duplique le sommet de la pile
– DROP : enl`
eve l’´
el´
ement au sommet de la pile
– OVER : duplique l’avant-dernier ´
el´
ement de la pile
– etc...
2.3
Notions de mot et de dictionnaire
L’ensemble des mots forth forme un dictionnaire. Il existe deux types
de mots :
– les mots de base du forth (appell´
es core-words)
– les mots d´
efinis par l’utilisateur
Pour d´
efinir un nouveau mot, on utilise la syntaxe suivante :
: nouveau_mot definition ;
Voici quelques exemples de d´
efinitions :
: carre dup * ; ( a -- a^2)
( Calcul le carre d’un nombre )
: cube dup carre * ; ( a -- a^3)
( Calcul le cube d’un nombre )
Certains mots de base peuvent ´
egalement ˆ
etre d´
efinis `
a l’aide d’autres
mots (swap ´
echange les deux nombres au sommet de la pile, rot effectue une
rotation entre les trois premiers ´
el´
ements) :
: over swap dup rot rot ;
2.4
Les variables
Les variables sont ´
egalement des mots. Lors de leur execution, ces mot
mettent sur la pile l’adresse de l’espace m´
emoire r´
eserv´
e pour cette variable.
Deux mots deviennent alors fondamentaux :
@ "at" ( addr -- value )
Ajoute sur la pile le contenu de addr.
! "store" ( value addr -- )
Ecrit value `
a l’adresse addr.
Voici un petit exemple pour illustrer qui illustre la cr´
eation, l’affectation
et la lecture d’une variable :
variable test
5 test !
test @ .
3
D´
efinition du Micro-forth
3.1
Simplifications
Le but du micro-forth n’est pas de concevoir un nouveau langage r´
evolutionnaire
ni d’´
etudier ses optimisations. L’impl´
ementation souffira donc de nombreuses
pertes de vitesse par rapport au langage forth dans un souci de temps. Voici
une liste exhaustive de toute les simplifications :
– liste des core-words tr`
es simplifi´
ee,
– calculs sur 32 bits uniquement (plus facile pour l’adressage),
– mots du core d´
efini en forth (perte de performance originellement gagn´
e
en jouant sur un jeu d’instructions plus ´
elev´
e, exemple : 1+ correspond
normalement `
a ”inc” alors que 1 + effectue deux instructions pour le
processeur),
– nombre non-sign´
es uniquement,
– interpr´
eteur case-sensitive,
– base 10 pour l’affichage de toutes les valeurs.
3.2
El´
ements repris du forth
La plupart des ´
el´
ements fondamentaux du forth sont repris, en
l’occu-rence :
– la syntaxe,
– les mots de manipulations de pile,
– la pile de retour (cf. 4.2.2),
– le buffer d’entr´
ee,
– la structure du dictionnaire.
Tous ces ´
el´
ements sont accessibles par l’utilisateur et forment ´
egalement
le ”coeur” du syst`
eme forth, `
a l’aide d’un algorithme relativement simple
d´
ecrit dans la prochaine partie.
4
Impl´
ementation d’un syst`
eme Micro-forth
4.1
Choix dans l’impl´
ementation
Voici `
a nouveau quelques simplifications, cette fois-ci dans
l’environne-ment forth :
– aucune variable d’environnement forth,
– aucun ´
el´
ement de stockage (plus tard, rajouter la lecture de fichier).
La sortie standard sera toujours l’´
ecran, et l’entr´
ee standard sera le clavier.
4.2
El´
ements d’un interpr´
eteur
Nous allons d´
etailler dans cette partie toutes les sous-fonctions d’un
in-terpr´
eteur forth. Ensuite, nous ´
etudierons le fonctionnement conjugu´
e de
toutes ces sous-parties.
4.2.1
Structure du dictionnaire
Le dictionnaire contient les d´
efinitions de l’ensemble des mots du
lan-gage. C’est une zone m´
emoire r´
eserv´
ee lors de l’initialisation du syst`
eme. Le
dictionnaire a la structure suivante :
last_def
|
-| Word1 -| Word2 -| Word3 -| Word 4 -| ...
-^
^
^
dp0
fence
dp
Le dictionnaire contient 4 pointeurs essentiels `
a l’´
execution ou `
a la
com-pilation de nouveaux mots :
– dp0 : pointeur vers le d´
ebut du dictionnaire,
– dp : pointeur vers la premi`
ere cellule libre du dictionnaire,
– fence : non utilis´
e par Micro-forth (cf. [2] pour plus d’informations),
– last def : adresse du dernier mot d´
efinit.
Chaque mot a alors la structure suivante :
---<-PFA = Parameter Field Address
| Flags |
name_length
|
---|
Word Name
|
---|
PFA Previous Word
|
---<-CFA = Code Field Address
|
Code Word
|
---|
|
|
Data
|
|
|
---– flags : indique si le mot est de type IMMEDIATE ou non (cf. 4.3),
– name lengh : longueur du nom du mot,
– word name : chaˆıne de charact`
eres repr´
esentant le mot (null-terminated),
– pfa previous word : adresse du champ de param`
etre de la d´
efinition
pr´
ec´
edente (sert au parcours du dictionnaire lors de la recherche d’un
mot),
– code word : indique le mot qui servira `
a traduire data (le mot peut ˆ
etre
un mot du core, une definition, une variable ou une constante),
– data : contient la d´
efinition du mot ou la valeur d’une variable.
Plus pr´
ecisement, dans le cas d’une d´
efinition, le champ data comporte
la liste des cfa des mots qui le composent.
Pour reprendre notre exemple pr´
ec´
edent, le champ data de ”carre” contient
le cfa de dup suivit du cfa de *.
4.2.2
La pile de donn´
ees
La pile de donn´
ees est l’´
el´
ement le plus simple du forth. Nous avons
d´
ej`
a vu son fonctionnement (cf. 2.2). Son impl´
ementation consiste `
a allouer
l’espace n´
ecessaire. Deux poiteurs sont n´
ecessaires pour manipuler cette pile :
– sp0 : pointeur vers le d´
ebut de la pile de donn´
ees,
– sp : poiteur vers le prochain emplacement libre sur la pile.
Le nombre d’´
el´
ements sur la pile peut alors ˆ
etre calcul´
e par (sp-sp0)/4 (on
divise par 4 car tous les ´
el´
ements de la pile font 32 bits).
4.2.3
La pile de retour
La pile de retour est un ´
el´
ement essentiel du coeur de forth. Elle contient
les adresses de retour lors de l’execution de mot. L’utilisteur peut y acc´
eder
par l’interm´
ediaire des mots ¿R et R¿ qui transferent le sommet entre la pile
de donn´
ees et la pile de retour. Cependant, si le syst`
eme trouve une valeur
qui n’est pas une adresse de retour au sommet de la pile, l’interpr´
eteur risque
de planter. Leur utilisation requiert donc de nombreuses pr´
ecautions :
– un programme ne doit pas acc´
eder aux valeurs de la pile de retour par
R¿ s’il n’a pas plac´
e au pr´
ealable une valeur par ¿R,
– un programme ne doit pas acc´
eder aux valeurs de la pile de retour
plac´
ees avant une boucle depuis l’interieur de cette boucle,
– toutes les valeurs stock´
es sur la pile de retour dans une boucle doivent
ˆ
etre ot´
ees avant la fin de la boucle,
– toutes les valeurs plac´
ees par ¿R doivent ˆ
etre retir´
ees avant la fin de
l’execution de l’input buffer.
4.2.4
Le buffer d’entr´
ee (input buffer)
Le buffer d’entr´
ee est un espace servant de stockage `
a la chaˆıne de
cha-ract`
eres entr´
ee par l’utilisateur. Cette chaˆıne sera analys´
ee, d´
ecoup´
ee en mots
qui seront execut´
es. Une variable ¿IN permet de savoir la position du parser
lors de l’interpr´
etation.
4.3
Structure de l’interpr´
eteur
4.3.1
Mots imm´
ediats
Les mots imm´
ediats sont un peu particuliers et servent lors de la
compila-tion de nouveaux mots. Ils modifient le flux de traitement du buffer d’entr´
ee.
Exemple : le mot ” :” est un mot imm´
ediat et execut´
e `
a la compilation. Ce
mot va chercher le prochain mot dans l’input buffer et cr´
ee une entˆ
ete dans
le dictionnaire. Il passe ´
egalement le mode de l’interpr´
eteur de ex´
ecution
`
a compilation du nouveau mot. Un mot imm´
ediat situ´
e `
a l’interieur d’une
d´
efinition ne sera pas compil´
e dans cette d´
efinition. Ce sont de v´
eritables
”agents de contrˆ
ole” de la compilation.
4.3.2
Registre IP (instruction pointer)
Le registre IP contient l’adresse du prochain mot `
a ex´
ecuter. Dans le cas
de notre exemple, le syst`
eme effectuera la tˆ
ache suivante : : carre dup * ; 1.
Place le cfa de carre sur la pile de retour.
2. IP prend la valeur du premier ´
el´
ement sur la pile de retour.
3. Ajout de IP+4 sur la pile de retour.
4. Execution de [IP] (ici dup).
5. D´
epile un ´
el´
ement de la pile de retour dans IP.
6. Execution de [IP] (*).
7. Plus rien sur la pile de retour, donc on rend la main.
4.3.3
Fonctionnement interne
I) R´
ecup`
ere le prochain mot du buffer d’entr´
ee
II) Chercher le mot dans le dictionnaire
1. Si il est trouv´
e
i) Si le mode est COMPILATION:
- Execute le mot s’il est marqu´
e IMMEDIATE
- Sinon, ajouter son cfa `
a la suite de la
d´
efinition du dictionnaire
ii) Si le mode est INTERPRETATION:
- Execute le mot
2. S’il n’est pas trouv´
e
i) Si c’est un nombre
- Ajouter `
a la pile de donn´
ees en INTERPRETATION
- Ajouter `
a la d´
efinition, pr´
ec´
ed´
e du mot (VALUE)
en mode COMPILATION
5
Conclusion
Grˆ
ace `
a une structure ing´
enieuse, le forth est un langage n´
ecessitant tr`
es
peu de ressources. Il est de plus extrement rapide puisqu’une fois compil´
e,
l’ex´
ecution ne fait qu’une s´
erie de ”jump” de plus que le code assembleur
lui-mˆ
eme. Finalement, une fois familiaris´
e avec la structure interne d’un
in-terpr´
eteur forth, on se rend compte que celui-ci fonctionne comme un
en-semble de r`
egles de Markov pour du code executable. En effet, lors de
l’execution d’un mot, on ne fait que remplacer ce mot par sa d´
efinition
jus-qu’`
a tomber sur une succession de mots de base directement executables.
L’interpr´
eteur pr´
esent´
e en annexe n’est pas encore compl`
etement fonctionnel
puisque le vocabulaire de base est tr`
es limit´
e. Cependant, beaucoup de mot
peuvent se d´
efinir `
a l’aide de la pile de retour, comme le do ... loop qui sert
`
a faire les boucles :
: do
compile swap
compile >r
compile >r
here ; immediate
: loop
compile r>
compile 1+
compile r>
compile 2dup
compile >r
compile >r
compile <
compile 0=
compile 0branch
here - ,
compile r>
compile r>
Annexes
A
Bibliographie
[1] http ://www.taygeta.com/forth/dpans.html
[2] http ://forth.free.fr/livres/guide/guide.htm
B
Code Source de Microforth Interpreter
Voici le code source de l’interpreteur.
Il peut ˆ
etre t´
el´
echarg´
e sous forme informatique `
a l’adresse suivante :
http ://www.neyric.com/comp/forth/microforth.tar.gz
: : : : : : : : : : : : : : main . c : : : : : : : : : : : : : : /∗ main . c M i c r o f o r t h i n t e r p r e t e r By E r i c A b o u a f n e y r i c @ v i a . e c p . f r J u n e 1 0 , 2 0 0 5 T h i s f i l e c o n t a i n s t h e main i n i t i a l i s a t i o n s and t h e i n f i n i t e l o o p . ∗/ #i n c l u d e < s t d i o . h> // p r i n t f #i n c l u d e < s t d l i b . h> // e x i t #i n c l u d e ” main . h ” #i n c l u d e ” d i c t i o n n a r y . h ” #i n c l u d e ” s t a c k s . h ” #i n c l u d e ” i n p u t b u f f e r . h ” #i n c l u d e ” p a r s e r . h ” // i n i t ( ) // // F u n c t i o n : P r i n t s i n f o s // A l l o c a t e s s p a c e f o r s t a c k s and d i c t i o n n a r y // A r g u m e n t s : None // R e t u r n : N o t h i n g // void i n i t ( ) { // P r i n t s i n f o s p r i n t f ( ” M i c r o f o r t h i n t e r p r e t e r \n ” ) ; p r i n t f ( ”By E r i c Abouaf \n ” ) ; p r i n t f ( ” n e y r i c @ v i a . e c p . f r \n ” ) ; p r i n t f ( ” June , 2 0 0 5 \ n\n ” ) ; // A l l o c a t e s s p a c e f o r i n p u t b u f f e r , d i c t i o n n a r y , s t a c k s i n i t i n p u t b u f f e r ( ) ; i n i t d i c t i o n n a r y ( ) ; i n i t s t a c k s ( ) ; } // f r e e m e m ( ) // // F u n c t i o n : F r e e s t h e a l l o c a t e d memory // A r g u m e n t s : None // R e t u r n : N o t h i n g // void f r e e m e m ( ){ // F r e e a l l o c a t e d memory f o r d i c t i o n n a r y , i n p u t b u f f e r , s t a c k s f r e e i n p u t b u f f e r ( ) ; f r e e d i c t i o n n a r y ( ) ; f r e e s t a c k s ( ) ; } // main ( ) // // F u n c t i o n : E n t r y p o i n t o f t h e a p p l i c a t i o n // P a r a m e t e r s : None // R e t u r n : 0 ( a l w a y s ) // i n t main ( void ) { // A l l o c a t e s memory i n i t ( ) ; // I n f i n i t e l o o p f o r ( ; ; ) { // P r i n t p r o m p t p r i n t f ( ” OK\n ” ) ; // F i l l s i n p u t b u f f e r f i l l i n p u t b u f f e r ( ) ; // C a l l t h e p a r s e r p a r s e r ( ) ; } // N e v e r c a l l e d , f o r c o m p i l a t i o n return 0 ; } : : : : : : : : : : : : : : main . h : : : : : : : : : : : : : : void f r e e m e m ( ) ; : : : : : : : : : : : : : : d i c t i o n n a r y . c : : : : : : : : : : : : : : /∗ d i c t i o n n a r y . c M i c r o f o r t h i n t e r p r e t e r By E r i c A b o u a f n e y r i c @ v i a . e c p . f r J u n e 1 0 , 2 0 0 5 T h i s f i l e c o n t a i n s t h e main d i c t i o n n a r y v a r i a b l e s a n s a l l o c a t e s p a c e f o r t h e d i c t i o n n a r y . The s t r u c t u r e o f t h e d i c t i o n n a r y i s t h e f o l l o w i n g : l a s t d e f | −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− − − | Word1 | Word2 | Word3 | Word 4 | . . . −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− − − ˆ ˆ ˆ d p 0 f e n c e dp d p 0 : s t a r t o f t h e d i c t i o n n a r y dp : f i r s t c e l l a v a i l a b l e a t t h e e n d o f t h e d i c t i o n n a r y f e n c e : b e f o r e f e n c e , t h e i n t e r p r e t e r c a n n o t FORGET l a s t d e f : A d r e s s o f t h e l a s t d e f i n i t i o n The s t r u c t u r e o f a w o r d w i t h i n t h e d i c t i o n n a r y i s t h e f o l l o w i n g : PFA −−−−−−−−−−−−−−−−−−−−−−−−− | F l a g s | n a m e l e n g t h | −−−−−−−−−−−−−−−−−−−−−−−−− | Word Name | −−−−−−−−−−−−−−−−−−−−−−−−− | P r e v i o u s Word | P o i n t e r t o t h e PFA o f t h e p r e v i o u s w o r d CFA −−−−−−−−−−−−−−−−−−−−−−−−−
| Code Word | EXEC WORD | COLON WORD −−−−−−−−−−−−−−−−−−−−−−−−−
| | | D a t a | | | −−−−−−−−−−−−−−−−−−−−−−−−− ∗/ #i n c l u d e ” d i c t i o n n a r y . h ” #i n c l u d e ” c o r e . h ” #d e f i n e DICO SIZE 8 0 0 0 #d e f i n e EXEC WORD 0 #d e f i n e COLON WORD 1 #d e f i n e IMMEDIATE WORD 32 void ∗ dp0 ; void ∗ dp ; void ∗ f e n c e ; void ∗ l a s t d e f ; // i n i t d i c t i o n n a r y ( ) // // F u n c t i o n : A l l o c a t e s memory f o r t h e d i c t i o n n a r y // and i n i t i a t e d i c t i o n n a r y p o i n t e r s // A r g u m e n t s : None // R e t u r n s : N o t h i n g // void i n i t d i c t i o n n a r y ( ) { // A l l o c a t e s memory // +1 => no d e f i n i t i o n s t a r t i n g b y 0 dp0 = ( void ∗ ) m a l l o c ( DICO SIZE ) + 1 ; // S e t d i c o p o i n t e r s dp = dp0 ; f e n c e = dp0 ; // F i r s t d e f i n i t i o n h a s no p r e v i o u s w o r d l a s t d e f = 0 ; c o r e d e f i n i t i o n s ( ) ; } // c o r e d e f i n i t i o n s ( ) // // F u n c t i o n : C r e a t e s e n t r i e s i n t h e d i c t i o n n a r y // A r g u m e n t s : None // R e t u r n s : N o t h i n g // void c o r e d e f i n i t i o n s ( ) { a d d c o r e w o r d ( ” . ” , &dot , 0 ) ; a d d c o r e w o r d ( ” . s ” , &d o t s , 0 ) ; a d d c o r e w o r d ( ”+” , &p l u s , 0 ) ; a d d c o r e w o r d ( ” w o r d s ” , &words , 0 ) ; a d d c o r e w o r d ( ” q u i t ” , &q u i t , 0 ) ;
a d d c o r e w o r d ( ” : ” , &c o l o n , IMMEDIATE WORD ) ; a d d c o r e w o r d ( ” ; ” , &s e m i c o l o n , IMMEDIATE WORD ) ; a d d c o r e w o r d ( ”dp@” , &dpat , 0 ) ; a d d c o r e w o r d ( ” dup ” , &dup , 0 ) ; a d d c o r e w o r d ( ” ∗ ” , &mult , 0 ) ; } // f r e e d i c t i o n n a r y ( ) // // F u n c t i o n : F r e e s t h e memory a l l o c a t e d f o r t h e d i c t i o n n a r y // A r g u m e n t s : None // R e t u r n s : N o t h i n g // void f r e e d i c t i o n n a r y ( ) { // f r e e s t h e memory o f t h e d i c t i o n n a r y f r e e ( dp0 ) ; } // a d d c o r e w o r d ( ) // // F u n c t i o n : C r e a t e a new e n t r y i n t h e d i c t i o n n a r y // A r g u m e n t s : // − word : s t r i n g o f t h e w o r d
// − f u n c t i o n : a d r e s s o f t h e C f u n c t i o n // − f l a g s : IMMEDIATE o r NULL // R e t u r n s : N o t h i n g
//
void a d d c o r e w o r d ( const char ∗ word , void ∗ f u n c t i o n , unsigned char f l a g s ) {
void ∗ temp dp = dp ; unsigned char temp ;
// Ge t t h e s i z e o f t h e w o r d ( b e t w e e n 1 . . 3 1 )
unsigned char l e n g t h = ( unsigned char ) s t r l e n ( word ) ; unsigned char l e n g t h f l a g s = l e n g t h | f l a g s ;
// W r i t e t h e f i r s t b y t e ( f l a g s + l e n g t h )
memcpy ( dp , &l e n g t h f l a g s , s i z e o f ( unsigned char ) ) ; dp += s i z e o f ( unsigned char ) ;
// W r i t e t h e name o f t h e w o r d
// a d d s t h e z e r o a t t h e e n d f o r s t r c m p memcpy ( dp , ( void ∗ ) word , l e n g t h + 1 ) ; dp += s i z e o f ( char ) ∗ ( l e n g t h + 1 ) ; // W r i t e t h e p f a o f t h e p r e v i o u s w o r d memcpy ( dp , &l a s t d e f , s i z e o f ( void ∗ ) ) ; dp += s i z e o f ( void ∗ ) ;
// W r i t e t h e Code Word , w h i c h i s i n t h i s c a s e o n l y EXEC WORD temp = EXEC WORD;
memcpy ( dp , &temp , s i z e o f ( unsigned char ) ) ; dp += s i z e o f ( unsigned char ) ;
// W r i t e t h e PFA ( A d d r e s s o f t h e e x e c u t i o n f u n c t i o n ) memcpy ( dp , &f u n c t i o n , s i z e o f ( void ∗ ) ) ;
dp += s i z e o f ( void ∗ ) ; // S e t t h e l a s t d e f v a r i a b l e l a s t d e f = temp dp ; } : : : : : : : : : : : : : : d i c t i o n n a r y . h : : : : : : : : : : : : : : // C o n t a i n s d e f i n i t i o n s f o r d i c t i o n n a r y . c void i n i t d i c t i o n n a r y ( ) ; void c o r e d e f i n i t i o n s ( ) ; void f r e e d i c t i o n n a r y ( ) ;
void a d d c o r e w o r d ( const char ∗ word , void ∗ f u n c t i o n , unsigned char f l a g s ) ; : : : : : : : : : : : : : : i n p u t b u f f e r . c : : : : : : : : : : : : : : /∗ i n p u t b u f f e r . c M i c r o f o r t h i n t e r p r e t e r By E r i c A b o u a f n e y r i c @ v i a . e c p . f r J u n e 1 0 , 2 0 0 5 T h i s f i l e c o n t a i n s t h e i n p u t b u f f e r f u n c t i o n s : i n i t , f r e e , and f i l l ∗/ #i n c l u d e ” i n p u t b u f f e r . h ” #d e f i n e INPUTBUFFER SIZE 2 5 6 // I n p u t b u f f e r p o i n t e r char ∗ i n p u t b u f f e r ; // i n i t i n p u t b u f f e r // // F u n c t i o n : A l l o c a t e memory f o r t h e i n p u t b u f f e r // A r g u m e n t s : None // R e t u r n : N o t h i n g // void i n i t i n p u t b u f f e r ( ) { // A l l o c a t e s s p a c e f o r i n p u t b u f f e r
i f ( i n p u t b u f f e r == 0 ) { p r i n t f ( ” i n i t i n p u t b u f f e r : U n a b l e t o a l l o c a t e s p a c e f o r i n p u t b u f f e r \n ” ) ; } } // f r e e i n p u t b u f f e r // // F u n c t i o n : F r e e memory a l l o c a t e d f o r t h e i n p u t b u f f e r // A r g u m e n t s : None // R e t u r n : N o t h i n g // void f r e e i n p u t b u f f e r ( ) { // f r e e s i n p u t b u f f e r f r e e ( ( void ∗ ) i n p u t b u f f e r ) ; } // f i l l i n p u t b u f f e r // // F u n c t i o n : F i l l s t h e i n p u t b u f f e r w i t h d a t a f r o m s t d i n // and p r e v e n t b u f f e r o v e r f l o w . ( b e t t e r t h a n g e t s ) // A r g u m e n t s : None // R e t u r n : N o t h i n g // void f i l l i n p u t b u f f e r ( ) { // F i l l s i n p u t b u f f e r char c = 0 ; unsigned char i = 0 ; while ( c != ’ \n ’ ) { // Ge t c h a r f r o m s t d i n c = g e t c h a r ( ) ; // P r e v e n t b u f f e r o v e r f l o w i f ( i == INPUTBUFFER SIZE−1) c = ’ \n ’ ; // Add t h e l e t t e r t o t h e b u f f e r i n p u t b u f f e r [ i ++] = c ; } i n p u t b u f f e r [ i −1] = 0 ; // i −1 c a u s e we r e m o v e t h e ’ \ n ’ } : : : : : : : : : : : : : : i n p u t b u f f e r . h : : : : : : : : : : : : : : // c o n t a i n s d e f i n i t i o n s f o r i n p u t b u f f e r . c void i n i t i n p u t b u f f e r ( ) ; void f r e e i n p u t b u f f e r ( ) ; void f i l l i n p u t b u f f e r ( ) ; : : : : : : : : : : : : : : p a r s e r . c : : : : : : : : : : : : : : /∗ p a r s e r . c M i c r o f o r t h i n t e r p r e t e r By E r i c A b o u a f n e y r i c @ v i a . e c p . f r J u n e 1 0 , 2 0 0 5 T h i s f i l e p a r s e t h e i n p u t b u f f e r and e x e c u t e t h e f o l l o w i n g : I ) P a r s e n e x t w o r d i n i n p u t b u f f e r I I ) L o o k u p t h e w o r d i n t h e d i c t i o n n a r y 1 . I f f o u n d i ) i f c o m p i l i n g : − E x e c u t e i f t h e w o r d i s m a r k e d IMMEDIATE − E l s e a d d w o r d a t t h e e n d o f t h e d i c t i o n n a r y i i ) i f i n t e r p r e t i n g : − E x e c u t e t h e w o r d 2 . I f n o t f o u n d i ) Try t o c o n v e r t i t t o a number − a d d t o s t a c k i f i n t e r p r e t i n g − a d d t o d i c t i o n n a r y w i t h (VALUE) b e f o r e i n t h e d i c t i o n n a r y i f c o m p i l i n g . i i ) P r i n t an e r r o r m e s s a g e ”Word unknown ”
∗/ #i n c l u d e ” p a r s e r . h ” #d e f i n e MODE COMPILATION 1 #d e f i n e MODE INTERPRET 0 extern char ∗ i n p u t b u f f e r ; extern void ∗ l a s t d e f ; extern void ∗ dp0 ; extern void ∗ dp ; extern void ∗ s p ; extern void ∗ r p ; extern void ∗ r p 0 ; char ∗ i n ;
unsigned char mode = MODE INTERPRET ; // GetNextWord ( ) // // F u n c t i o n : G e t s n e x t w o r d i n i n p u t b u f f e r // A r g u m e n t s : n e x t w o r d => r e s u l t b u f f e r // R e t u r n s : N o t h i n g //
void GetNextWord ( char ∗ n e x t w o r d ) { i n t i = 0 ; // Remove b l a n k s o r t a b s b e f o r e t h e w o r d while ( i n [ 0 ] == ’ ’ | | i n [ 0 ] == ’ \ t ’ ) i n += s i z e o f ( char ) ; // S t o r e t h e w o r d
while ( i n [ 0 ] != ’ ’ && i n [ 0 ] != ’ \ t ’ && i n [ 0 ] != 0 ) { n e x t w o r d [ i ++] = i n [ 0 ] ; i n += s i z e o f ( char ) ; } n e x t w o r d [ i ++] = 0 ; } // t i c k ( ) // // F u n c t i o n : f i n d a w o r d g i v e n i t s name i n t h e d i c t i o n n a r y // A r g u m e n t s : w o r d : s t r i n g o f t h e w o r d // R e t u r n s : p o i n t e r c o n t a i n i n g t h e p f a t o t h e w o r d //
void ∗ t i c k ( unsigned char ∗ word ) { // Take t h e l a s t d e f i n i t i o n void ∗ d e f i n i t i o n = l a s t d e f ; void ∗ p f a = 0 ; unsigned char b o o l e a n = 0 ; // W h i l e we d i d n ’ t f i n d t h e w o r d and no more d e f i n i t i o n while ( b o o l e a n == 0 && d e f i n i t i o n != 0 ) {
void ∗ n a m e p t r = d e f i n i t i o n +s i z e o f ( unsigned char ) ; // Compare t h e name
i f ( s t r c m p ( word , ( unsigned char ∗ ) n a m e p t r ) == 0 ) {
p f a = d e f i n i t i o n ; b o o l e a n = 1 ; }
e l s e // I f d i f f e r e n t , g o t o p r e v i o u s d e f i n i t i o n
memcpy ( &d e f i n i t i o n , n a m e p t r+ s t r l e n ( ( unsigned char ∗ ) n a m e p t r ) + 1 , s i z e o f ( void ∗ ) ) ; } return ( void ∗ ) p f a ; } // p f a 2 c f a ( ) // // F u n c t i o n : c o n v e r t a p f a t o a c f a // A r g u m e n t s : p f a o f t h e w o r d // R e t u r n s : p o i n t e r c o n t a i n i n g t h e c f a o f t h e w o r d // void ∗ p f a 2 c f a ( void ∗ p f a ) {
void ∗ c f a ; unsigned char l e n g t h ; i f ( p f a == 0 ) return 0 ; // S k i p l e n g t h b y t e c f a = p f a + s i z e o f ( unsigned char ) ; // S k i p name
memcpy(& l e n g t h , p f a , s i z e o f ( unsigned char ) ) ; l e n g t h = l e n g t h & 3 1 ; c f a += ( l e n g t h +1)∗ s i z e o f ( char ) ; // S k i p s p r e v i o u s p f a c f a += s i z e o f ( void ∗ ) ; return c f a ; } // i s n u m e r i c ( ) // // F u n c t i o n : T e s t i f a s t r i n g i s n u m e r i c a l // A r g u m e n t s : s t r i n g // R e t u r n s : 0 i f n u m e r i c a l , e l s e 1 . //
char i s n u m e r i c ( unsigned char ∗ s t r ) {
unsigned char ∗ temp = s t r ; while ( temp [ 0 ] != 0 ) { i f ( temp [ 0 ] < ’ 0 ’ | | temp [ 0 ] > ’ 9 ’ ) return 1 ; temp++; } return 0 ; } // p a r s e r ( ) // // F u n c t i o n : S e e t o p o f t h e f i l e // A r g u m e n t s : None // R e t u r n : N o t h i n g // void p a r s e r ( ) { // To s t o r e t h e n e x t w o r d char n e x t w o r d [ 3 2 ] ; void ∗ c f a ; i n t l e n g t h = s t r l e n ( i n p u t b u f f e r ) ; // Makes i n t h e b e g g i n i n g o f i n p u t b u f f e r i n = i n p u t b u f f e r ; // C o n t i n u e s u n t i l t h e i n p u t b u f f e r g e t s e m p t y while ( i n != i n p u t b u f f e r+l e n g t h ∗ s i z e o f ( char ) ) { GetNextWord ( n e x t w o r d ) ; // I f w o r d i s n o t e m p t y . . . i f ( n e x t w o r d [ 0 ] != 0 ) { // T i c k f i n d t h e p f a o f t h e w o r d unsigned char f i r s t b y t e = 0 ; void ∗ t e m p p f a = t i c k ( n e x t w o r d ) ; c f a = p f a 2 c f a ( t e m p p f a ) ; i f ( c f a != 0 ) {
memcpy ( &f i r s t b y t e , t e m p p f a , s i z e o f ( unsigned char ) ) ; // & 32 => F i l t e r f o r t h e 3 r d b i t d o r e a l w o r d ( c f a , f i r s t b y t e & 3 2 ) ; } // E l s e c f a == 0 e l s e { // Try t o c o n v e r t t o a n u m e r i c a l v a l u e i f ( i s n u m e r i c ( n e x t w o r d ) == 0 )
{
long number = a t o i (& n e x t w o r d ) ; i f ( mode == 0 ) // INTERPRETATION {
// Add t h e number on s t a c k memcpy ( sp ,& number , s i z e o f ( long ) ) ; s p += s i z e o f ( long ) ; } e l s e { // Add t h e CFA o f v a l u e void ∗ v a l u e = ( void ∗ ) 1 ;
memcpy ( dp ,& v a l u e , s i z e o f ( void ∗ ) ) ; dp += s i z e o f ( void ∗ ) ;
// Add t h e v a l u e
memcpy ( dp ,& number , s i z e o f ( long ) ) ; dp += s i z e o f ( long ) ; } } e l s e // Word unknown p r i n t f ( ”%s : U n d e f i n e d word \n ” , n e x t w o r d ) ; } // e l s e c f a == 0 } // I f w o r d n o t e m p t y } // w h i l e i n . . . } // d o r e a l w o r d ( ) // // F u n c t i o n : S e e t o p o f t h e f i l e // A r g u m e n t s : c f a o f t h e w o r d t o e x e c u t e o r c o m p i l e // f l a g s ( i m m e d i a t e w o r d o r n o t ) // R e t u r n : N o t h i n g //
void d o r e a l w o r d ( void ∗ c f a , unsigned char f l a g s ) { i f ( mode == 1 ) // COMPILATION { // IMMEDIATE WORD i f ( f l a g s == 3 2 ) i n t e r p r e t ( c f a ) ; e l s e { // We j u s t a d d t h e c f a a t t h e e n d o f t h e d i c t i o n n a r y memcpy ( dp , &c f a , s i z e o f ( void ∗ ) ) ;
dp += s i z e o f ( void ∗ ) ; } } e l s e // INTERPRETEATION i n t e r p r e t ( c f a ) ; } // i n t e r p r e t ( ) // // F u n c t i o n : E x e c u t e a w o r d g i v e n i t s c f a // A r g u m e n t s : c f a // R e t u r n : N o t h i n g // void i n t e r p r e t ( void ∗ c f a ) { unsigned char t y p e ; void ( ∗ f p ) ( ) ;
void ∗ c f a d a t a = c f a + s i z e o f ( unsigned char ) ; memcpy(& t y p e , c f a , s i z e o f ( unsigned char ) ) ;
i f ( t y p e == 0 ) // EXEC WORD {
// R e t r i e v e e x e c a d d r e s s
memcpy ( &f p , c f a d a t a , s i z e o f ( void ∗ ) ) ; // E x e c u t e a d d r e s s f p ( ) ; } e l s e i f ( t y p e == 1 ) // COLON WORD { // Add t h e c f a on t o p o f t h e r e t u r n s t a c k memcpy ( rp , &c f a d a t a , s i z e o f ( void ∗ ) ) ; r p += s i z e o f ( void ∗ ) ;
// E x e c u t e t h e s t a c k e x e c u t e ( ) ; } e l s e p r i n t f ( ” C o r r u p t e d memory i n d i c t i o n n a r y . \ n ” ) ; } // e x e c u t e ( ) // // F u n c t i o n : E x e c u t e t h e r e t u r n s t a c k ( i f f o r t h −d e f i n e d w o r d ) // A r g u m e n t s : None // R e t u r n : N o t h i n g // void e x e c u t e ( ) { void ∗ c f a ; void ∗ i p ; long temp ; while ( r p != r p 0 ) { // U n s t a c k an e l e m e n t r p −= s i z e o f ( void ∗ ) ;
memcpy ( rp , &c f a , s i z e o f ( void ∗ ) ) ; i p = c f a ; // p r i n t f (”% d ” , c f a ) ; memcpy(&temp , i p , s i z e o f ( long ) ) ; while ( temp != 0 ) { i f ( temp == 1 ) // 1 i s t h e CFA i n d i c a t i n g a v a l u e { i p += s i z e o f ( long ∗ ) ; // Add t h e v a l u e on t h e s t a c k memcpy ( sp , i p , s i z e o f ( long ) ) ; s p += s i z e o f ( long ) ; } e l s e { void ∗ n e w c f a ;
memcpy ( &n e w c f a , i p , s i z e o f ( void ∗ ) ) ; i n t e r p r e t ( n e w c f a ) ; } // Go t o n e x t i n s t r u c t i o n i p += s i z e o f ( long ∗ ) ; memcpy(&temp , i p , s i z e o f ( long ) ) ; } } } : : : : : : : : : : : : : : p a r s e r . h : : : : : : : : : : : : : : // D e f i n i t i o n s f o r p a r s e r . c
void GetNextWord ( char ∗ n e x t w o r d ) ; void p a r s e r ( ) ;
void d o r e a l w o r d ( void ∗ c f a , unsigned char f l a g s ) ; void i n t e r p r e t ( void ∗ c f a ) ; void e x e c u t e ( ) ; : : : : : : : : : : : : : : s t a c k s . c : : : : : : : : : : : : : : /∗ s t a c k s . c M i c r o f o r t h i n t e r p r e t e r By E r i c A b o u a f n e y r i c @ v i a . e c p . f r J u n e 1 0 , 2 0 0 5 C o n t a i n s t h e i n i t and f r e e f u n c t i o n s f o r d a t a and r e t u r n s t a c k s .
∗/ #i n c l u d e ” s t a c k s . h ” #d e f i n e DATASTACK SIZE 3 0 0 0 #d e f i n e RETURNSTACK SIZE 3 0 0 0 // P o i n t e r s f o r t h e r e t u r n s t a c k void ∗ r p 0 ; void ∗ r p ; // P o i n t e r s f o r t h e d a t a s t a c k void ∗ s p 0 ; void ∗ s p ; // i n i t s t a c k s ( ) // // F u n c t i o n : A l l o c a t e s p a c e f o r d a t a and r e t u r n s t a c k s // A r g u m e n t s : None // R e t u r n : N o t h i n g // void i n i t s t a c k s ( ) { // A l l o c a t e s s p a c e f o r d a t a s t a c k s p 0 = ( void ∗ ) m a l l o c (DATASTACK SIZE ) ; i f ( s p 0 == 0 ) { p r i n t f ( ” i n i t s t a c k s : U n a b l e t o a l l o c a t e s p a c e f o r d a t a s t a c k \n ” ) ; } s p = s p 0 ; // A l l o c a t e s s p a c e f o r r e t u r n s t a c k r p 0 = ( void ∗ ) m a l l o c (RETURNSTACK SIZE ) ; i f ( r p 0 == 0 ) { p r i n t f ( ” i n i t s t a c k s : U n a b l e t o a l l o c a t e s p a c e f o r r e t u r n s t a c k \n ” ) ; } r p = r p 0 ; } // f r e e s t a c k s ( ) // // F u n c t i o n : F r e e memory a l l o c a t e d f o r t h e s t a c k s // A r g u m e n t s : None // R e t u r n : N o t h i n g // void f r e e s t a c k s ( ) { // F r e e s t a c k s f r e e ( ( void ∗ ) r p 0 ) ; f r e e ( ( void ∗ ) s p 0 ) ; } : : : : : : : : : : : : : : s t a c k s . h : : : : : : : : : : : : : : // d e f i n i t i o n s f o r s t a c k s . c void i n i t s t a c k s ( ) ; void f r e e s t a c k s ( ) ; : : : : : : : : : : : : : : c o r e . c : : : : : : : : : : : : : : /∗ c o r e . c M i c r o f o r t h i n t e r p r e t e r By E r i c A b o u a f n e y r i c @ v i a . e c p . f r J u n e 1 1 , 2 0 0 5 T h i s f i l e c o n t a i n s some c o r e w o r d d e f i n i t i o n s . A l l t h e f u n c t i o n s a r e meant t o b e a d d e d t o t h e d i c t i o n n a r y t h r o u g h a d d c o r e w o r d ( ) ∗/
#i n c l u d e ” c o r e . h ” #i n c l u d e ” p a r s e r . h ” #i n c l u d e ” main . h ” extern void ∗ s p ; extern void ∗ dp ; extern void ∗ s p 0 ; extern void ∗ l a s t d e f ; extern unsigned char mode ; // d u p void dup ( ) { i f ( s p == s p 0 ) p r i n t f ( ” dup : e r r o r , empty s t a c k \n ” ) ; e l s e {
memcpy ( sp , sp−s i z e o f ( long ) , s i z e o f ( long ) ) ; s p += s i z e o f ( long ) ; } } // DP@ void d p a t ( ) {
memcpy ( sp , &dp , s i z e o f ( void ∗ ) ) ; s p += s i z e o f ( void ∗ ) ; } // : ( i m m e d i a t e w o r d ) void c o l o n ( ) { char n e x t w o r d [ 3 2 ] ; unsigned char l e n g t h ; unsigned char temp ; void ∗ temp dp = dp ; // S w i t c h t o c o m p i l a t i o n mode mode = 1 ; // GetNextWord i n i n p u t b u f f e r GetNextWord ( n e x t w o r d ) ; l e n g t h = ( unsigned char ) s t r l e n ( n e x t w o r d ) ; // w r i t e w o r d h e a d e r
memcpy ( dp , &l e n g t h , s i z e o f ( unsigned char ) ) ; dp += s i z e o f ( unsigned char ) ;
// w r i t e t h e name
memcpy ( dp , ( void ∗ ) n e x t w o r d , l e n g t h + 1 ) ; dp += s i z e o f ( char ) ∗ ( l e n g t h + 1 ) ;
// W r i t e t h e p f a o f t h e p r e v i o u s w o r d memcpy ( dp , &l a s t d e f , s i z e o f ( void ∗ ) ) ; dp += s i z e o f ( void ∗ ) ;
// W r i t e i n f o a b o u t a c o l o n w o r d temp = 1 ;
memcpy ( dp , &temp , s i z e o f ( unsigned char ) ) ; dp += s i z e o f ( unsigned char ) ; // U p d a t e l a s t d e f l a s t d e f = temp dp ; } // ; ( i m m e d i a t e w o r d ) void s e m i c o l o n ( ) { void ∗ temp = 0 ; // S w i t c h t o i n t e r p r e t a t i o n mode mode = 0 ; // W r i t e t h e e n d o f t h e w o r d ( 0 ) memcpy ( dp , &temp , s i z e o f ( void ∗ ) ) ; dp += s i z e o f ( void ∗ ) ;
} // q u i t void q u i t ( )
{ p r i n t f ( ” \ nGoodbye ! \ n\n ” ) ; f r e e m e m ( ) ; e x i t ( 0 ) ; } // . void d o t ( ) { i f ( s p == s p 0 ) p r i n t f ( ” . : e r r o r , empty s t a c k \n ” ) ; e l s e { long temp ; s p −= s i z e o f ( long ) ; memcpy(&temp , sp , s i z e o f ( long ) ) ; p r i n t f ( ”%d ” , temp ) ; } } // + void p l u s ( ) { i f ( s p <= s p 0+s i z e o f ( long ) ) p r i n t f ( ” +: e r r o r , empty s t a c k \n ” ) ; e l s e { long x1 , x2 ; s p −= s i z e o f ( long ) ; memcpy(&x1 , sp , s i z e o f ( long ) ) ; s p −= s i z e o f ( long ) ; memcpy(&x2 , sp , s i z e o f ( long ) ) ; x1 += x2 ;
memcpy ( sp , &x1 , s i z e o f ( long ) ) ; s p += s i z e o f ( long ) ; } } // ∗ void mult ( ) { i f ( s p <= s p 0+s i z e o f ( long ) ) p r i n t f ( ” +: e r r o r , empty s t a c k \n ” ) ; e l s e { long x1 , x2 ; s p −= s i z e o f ( long ) ; memcpy(&x1 , sp , s i z e o f ( long ) ) ; s p −= s i z e o f ( long ) ; memcpy(&x2 , sp , s i z e o f ( long ) ) ; x1 = x1 ∗ x2 ;
memcpy ( sp , &x1 , s i z e o f ( long ) ) ; s p += s i z e o f ( long ) ; } } // . s void d o t s ( ) { void ∗ temp = s p 0 ; p r i n t f ( ”<%d> ” , ( sp−s p 0 ) / s i z e o f ( long ) ) ; while ( temp != s p ) { long numero ;
memcpy(&numero , temp , s i z e o f ( long ) ) ; p r i n t f ( ”%d ” , numero ) ; temp += s i z e o f ( long ) ; } } // w o r d s void w o r d s ( ) { void ∗ d e f i n i t i o n = l a s t d e f ; // W h i l e we d i d n ’ t f i n d no more d e f i n i t i o n while ( d e f i n i t i o n != 0 ) {
void ∗ n a m e p t r = d e f i n i t i o n +s i z e o f ( unsigned char ) ; p r i n t f ( ”%s ” , ( unsigned char ∗ ) n a m e p t r ) ;
// P r e v i o u s d e f i n i t i o n a d d r e s s i s a t n a m e p t r+ l e n g t h o f ( name )
memcpy ( &d e f i n i t i o n , n a m e p t r+ s t r l e n ( ( unsigned char ∗ ) n a m e p t r ) + 1 , s i z e o f ( void ∗ ) ) ; } p r i n t f ( ” \n ” ) ; } : : : : : : : : : : : : : : c o r e . h : : : : : : : : : : : : : : // C o n t a i n s d e c l a r a t i o n s o f c o r e . c void dup ( ) ; void mult ( ) ; void d p a t ( ) ; void c o l o n ( ) ; void s e m i c o l o n ( ) ; void q u i t ( ) ; void d o t ( ) ; void d o t s ( ) ; void p l u s ( ) ; void w o r d s ( ) ; : : : : : : : : : : : : : : M a k e f i l e : : : : : : : : : : : : : : m i c r o f o r t h : main . c d i c t i o n n a r y . c i n p u t b u f f e r . c s t a c k s . c p a r s e r . c c o r e . c g c c −o main . o −c main . c
g c c −o d i c t i o n n a r y . o −c d i c t i o n n a r y . c g c c −o c o r e . o −c c o r e . c g c c −o p a r s e r . o −c p a r s e r . c g c c −o i n p u t b u f f e r . o −c i n p u t b u f f e r . c g c c −o s t a c k s . o −c s t a c k s . c g c c −o m i c r o f o r t h main . o d i c t i o n n a r y . o i n p u t b u f f e r . o s t a c k s . o p a r s e r . o c o r e . o c l e a n : rm − r f ∗ . o rm m i c r o f o r t h