1 |
13 |
louismarie |
#include "synthetiseur.h"
|
2 |
|
|
|
3 |
|
|
/* Autres modules utilisés par le synthétiseur. */
|
4 |
|
|
#include <debogueur.h>
|
5 |
|
|
#include <dialogue.h>
|
6 |
|
|
#include <formateur.h>
|
7 |
|
|
#include <parametres.h>
|
8 |
|
|
#include <adaptateur.h>
|
9 |
|
|
#include <analyseur.h>
|
10 |
|
|
|
11 |
|
|
/* Cette fonction convertit un masque en talbeau de char équivalent. */
|
12 |
|
|
/* La chaine étant allouée dynamiquement, il conviendra de la libérer après utilisation. */
|
13 |
|
|
char * cnv_mask_str(type_mask * m)
|
14 |
|
|
{
|
15 |
|
|
char * res;
|
16 |
|
|
int i;
|
17 |
|
|
type_valeur_mask v;
|
18 |
|
|
if (m==NULL) return NULL;
|
19 |
|
|
res = malloc((m->taille)*sizeof(char));
|
20 |
|
|
if (res==NULL) DIALOGUE("synthetiseur(cnv_mask_str)", 0, F_ERR_MEM);
|
21 |
|
|
v=m->valeur;
|
22 |
|
|
for (i=m->taille-1 ; i>=0 ; i--)
|
23 |
|
|
{
|
24 |
|
|
res[i]= (v & 0xFF);
|
25 |
|
|
v>>=8;
|
26 |
|
|
}
|
27 |
|
|
return res;
|
28 |
|
|
}
|
29 |
|
|
|
30 |
|
|
/* numéro de la colonne où l'on écrit le texte du code source dans la liste d'assemblage. */
|
31 |
|
|
#define COL_TEXT (2*sizeof(type_valeur_mask)+10)
|
32 |
|
|
|
33 |
|
|
/* Cette fonction recopie le flux srce dans dest jusqu'à la ligne fin exclue, sachant que le */
|
34 |
|
|
/* flux source est supposé positionné à la ligne debut. */
|
35 |
|
|
/* Le flux srce sera positionné au début de la ligne fin après l'exécution de la fonction. */
|
36 |
|
|
/* La fonction retourne le numéro de la ligne à laquelle se trouve effectivement le flux. */
|
37 |
|
|
/* Au début de chaque ligne, la fonction écrit son numéro puis \t suivi de COL_TEXT espaces. */
|
38 |
|
|
int recopie(FILE * srce, FILE * dest, int debut, int fin)
|
39 |
|
|
{
|
40 |
|
|
while (debut<fin)
|
41 |
|
|
{
|
42 |
|
|
int c;
|
43 |
|
|
long col;
|
44 |
|
|
fprintf(dest, "%d\t", debut);
|
45 |
|
|
/* On complète la tête de ligne avec des espaces. */
|
46 |
|
|
for (col=0 ; col<COL_TEXT ; col++) fputc(' ', dest);
|
47 |
|
|
while ((c=fgetc(srce))!='\n' && c!=EOF) fputc(c, dest);
|
48 |
|
|
if (c!='\n') return debut; /* Fin du fichier atteinte. */
|
49 |
|
|
fputc(c, dest);
|
50 |
|
|
++debut;
|
51 |
|
|
}
|
52 |
|
|
return debut;
|
53 |
|
|
}
|
54 |
|
|
|
55 |
|
|
/* Recopie la ligne courante de srce dans dest, y compris le \n. */
|
56 |
|
|
void ligne_cp(FILE * srce, FILE * dest)
|
57 |
|
|
{
|
58 |
|
|
int c;
|
59 |
|
|
while ((c=fgetc(srce))!='\n' && c!=EOF) fputc(c, dest);
|
60 |
|
|
if (c=='\n') fputc('\n', dest);
|
61 |
|
|
}
|
62 |
|
|
|
63 |
|
|
/* Cette fonction effectue le traitement de seconde passe des données actuellement dans la */
|
64 |
|
|
/* file de précode. Le nombre d'erreurs est retourné. */
|
65 |
|
|
int synthese()
|
66 |
|
|
{
|
67 |
|
|
int err=0;
|
68 |
|
|
type_precode * pcd;
|
69 |
|
|
|
70 |
|
|
for ( pcd=file_precode ; pcd!=NULL ; pcd=pcd->suivant )
|
71 |
|
|
{
|
72 |
|
|
int i;
|
73 |
|
|
|
74 |
|
|
pco=pcd->pco;
|
75 |
|
|
|
76 |
|
|
for (i=0 ; i<pcd->nbr_func ; i++)
|
77 |
|
|
{
|
78 |
|
|
type_mask * res;
|
79 |
|
|
res = (pcd->func)[i](pcd->param);
|
80 |
|
|
|
81 |
|
|
switch (eval_code)
|
82 |
|
|
{ /* Application du masque généré par la fonction de seconde passe. */
|
83 |
|
|
case EVAL_REUSSIE :
|
84 |
|
|
if (res==NULL || res->taille==0) break;
|
85 |
|
|
if (pcd->mask==NULL || res->taille!=pcd->mask->taille)
|
86 |
|
|
{ /* On a défini un nouveau masque incompatible. */
|
87 |
|
|
DIALOGUE(pcd->fichier_orig,
|
88 |
|
|
pcd->ligne_orig, S_FUN_ERR);
|
89 |
|
|
/* On remplace le précode par une erreur. */
|
90 |
|
|
CLEAR_PRECODE(pcd);
|
91 |
|
|
pcd->erreur=S_FUN_ERR;
|
92 |
|
|
err++;
|
93 |
|
|
break;
|
94 |
|
|
}
|
95 |
|
|
/* Le nouveau masque est ajouté. */
|
96 |
|
|
pcd->mask->valeur|=res->valeur;
|
97 |
|
|
break;
|
98 |
|
|
case EVAL_IMPOSSIBLE : /* En seconde passe, erreur. */
|
99 |
|
|
case EVAL_ERREUR :
|
100 |
|
|
affiche_message(pcd->fichier_orig, pcd->ligne_orig);
|
101 |
|
|
err++;
|
102 |
|
|
/* On remplace le précode par une erreur. */
|
103 |
|
|
CLEAR_PRECODE(pcd);
|
104 |
|
|
pcd->erreur=err_code;
|
105 |
|
|
break;
|
106 |
|
|
default :
|
107 |
|
|
DIALOGUE(pcd->fichier_orig,
|
108 |
|
|
pcd->ligne_orig, S_ADAP_ERR);
|
109 |
|
|
CLEAR_PRECODE(pcd);
|
110 |
|
|
pcd->erreur=S_ADAP_ERR;
|
111 |
|
|
err++;
|
112 |
|
|
break;
|
113 |
|
|
}
|
114 |
|
|
if (res!=NULL) FREE_MASK(res);
|
115 |
|
|
}
|
116 |
|
|
/* On libère l'espace alloué pour le tableau des fonctions de seconde passe. */
|
117 |
|
|
if (pcd->func!=NULL) free(pcd->func);
|
118 |
|
|
pcd->func=NULL;
|
119 |
|
|
pcd->nbr_func=0;
|
120 |
|
|
}
|
121 |
|
|
return err;
|
122 |
|
|
}
|
123 |
|
|
|
124 |
|
|
|
125 |
|
|
/* Cette fonction est utilisée pour écrire dans un flux le code binaire généré et */
|
126 |
|
|
/* actuellement enregistré dans la pile de précode. Il faut au préalable exécuter la seconde */
|
127 |
|
|
/* passe faute de quoi le code sera incomplet. */
|
128 |
|
|
void write_objet(FILE * f_obj)
|
129 |
|
|
{
|
130 |
|
|
type_precode * pcd;
|
131 |
|
|
int i;
|
132 |
|
|
int local_pco=-1;
|
133 |
|
|
long c_head=-5; /* Utilisé pour mémoriser la position de l'entête du bloc courant. */
|
134 |
|
|
long n_head; /* Position du nouvel entête de bloc. */
|
135 |
|
|
int addimp;
|
136 |
|
|
int taille;
|
137 |
|
|
|
138 |
|
|
if (f_obj==NULL) DIALOGUE("synthetiseur(write_objet)", 0, F_FLUX_NULL);
|
139 |
|
|
|
140 |
|
|
for (pcd=file_precode ; pcd!=NULL ; pcd=pcd->suivant)
|
141 |
|
|
{
|
142 |
|
|
if (pcd->erreur==NO_ERR && pcd->mask!=NULL)
|
143 |
|
|
{ /* On ne s'occupe ici que des précodes générant du code. */
|
144 |
|
|
char * code_bin;
|
145 |
|
|
|
146 |
|
|
if (pcd->pco!=local_pco)
|
147 |
|
|
{ /* Ecriture d'un nouvel entête de bloc en complétion du précédent. */
|
148 |
|
|
n_head=ftell(f_obj);
|
149 |
|
|
addimp=pcd->pco;
|
150 |
|
|
if (c_head!=-5) /* Il ne s'agit pas du premier bloc. */
|
151 |
|
|
{ /* Ecriture de la taille du bloc que l'on ferme. */
|
152 |
|
|
/* Calcul de la taille du bloc terminé. */
|
153 |
|
|
taille=n_head-c_head-4;
|
154 |
|
|
/* Ecriture de la taille au bon emplacement. */
|
155 |
|
|
fseek(f_obj, c_head+2, SEEK_SET);
|
156 |
|
|
for (i=1 ; i>=0 ; i--)
|
157 |
|
|
fputc((taille>>(8*i)) & 0xFF, f_obj);
|
158 |
|
|
/* Retour au nouveau bloc. */
|
159 |
|
|
fseek(f_obj, n_head, SEEK_SET);
|
160 |
|
|
}
|
161 |
|
|
/* Ecriture de l'adresse d'implantation. */
|
162 |
|
|
for (i=1 ; i>=0 ; i--) fputc((addimp>>(8*i)) & 0xFF , f_obj);
|
163 |
|
|
/* Ecriture de 0 pour la taille du prochain bloc. */
|
164 |
|
|
for (i=0; i<2; i++) fputc(0, f_obj);
|
165 |
|
|
c_head=n_head;
|
166 |
|
|
local_pco=pcd->pco;
|
167 |
|
|
}
|
168 |
|
|
|
169 |
|
|
/* On écrit le masque du précode courant dans le fichier. */
|
170 |
|
|
code_bin=cnv_mask_str(pcd->mask); /* Conversion du masque. */
|
171 |
|
|
/* Insertion des caractères dans le fichier objet. */
|
172 |
|
|
for (i=0 ; i<pcd->mask->taille ; i++) fputc(code_bin[i], f_obj);
|
173 |
|
|
free(code_bin); /* On libère la chaine allouée. */
|
174 |
|
|
|
175 |
|
|
local_pco+=pcd->mask->taille; /* Avancement du pco. */
|
176 |
|
|
}
|
177 |
|
|
}
|
178 |
|
|
|
179 |
|
|
/* Ecriture de la taille du dernier bloc. */
|
180 |
|
|
n_head=ftell(f_obj);
|
181 |
|
|
/* Calcul de la taille du bloc terminé. */
|
182 |
|
|
taille=n_head-c_head-4;
|
183 |
|
|
/* Ecriture de la taille au bon emplacement. */
|
184 |
|
|
fseek(f_obj, c_head+2, SEEK_SET);
|
185 |
|
|
for (i=1 ; i>=0 ; i--) fputc((taille>>(8*i)) & 0xFF, f_obj);
|
186 |
|
|
/* Retour au nouveau bloc, en fin de fichier. */
|
187 |
|
|
fseek(f_obj, n_head, SEEK_SET);
|
188 |
|
|
}
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
/* Cette fonction est utilisée pour écrire dans un flux la liste d'assemblage correspondant */
|
192 |
|
|
/* aux données enregistrée dans la pile de précode. Il faut au préalable exécuter la seconde */
|
193 |
|
|
/* passe faute de quoi le code sera incomplet. */
|
194 |
|
|
void write_liste(FILE * f_lst, FILE * f_src)
|
195 |
|
|
{
|
196 |
|
|
int ligne=1; /* Ligne courante dans le fichier source. */
|
197 |
|
|
type_precode * pcd_cour=file_precode;
|
198 |
|
|
|
199 |
|
|
if (f_lst==NULL) DIALOGUE("synthetiseur(write_liste)", 0, F_FLUX_NULL);
|
200 |
|
|
|
201 |
|
|
while (pcd_cour!=NULL)
|
202 |
|
|
{
|
203 |
|
|
int lbloc; /* Numéro de ligne de l'instruction que l'on va traiter. */
|
204 |
|
|
int pco_ecrit=0; /* Drapeau de controle de l'écriture du pco. */
|
205 |
|
|
long col=0; /* Colonne courante dans la ligne actuelle du fichier. */
|
206 |
|
|
type_precode * pcd;
|
207 |
|
|
|
208 |
|
|
lbloc=pcd_cour->ligne_orig; /* Ligne courante dans la source. */
|
209 |
|
|
|
210 |
|
|
/* On recopie la portion de code jusqu'à la ligne ayant généré le précode. */
|
211 |
|
|
ligne=recopie(f_src, f_lst, ligne, lbloc);
|
212 |
|
|
|
213 |
|
|
if (ligne!=lbloc)
|
214 |
|
|
{ /* Le fichier source a changé par rapport aux lignes mémorisées. */
|
215 |
|
|
DIALOGUE(NULL, 0, W_SRCE_MOD);
|
216 |
|
|
return;
|
217 |
|
|
}
|
218 |
|
|
|
219 |
|
|
fprintf(f_lst, "%d\t", ligne); /* Ecriture du numéro de la ligne en cours. */
|
220 |
|
|
col=ftell(f_lst); /* On mémorise la colonne de départ. */
|
221 |
|
|
|
222 |
|
|
for (pcd=pcd_cour ; pcd!=NULL && pcd->ligne_orig==lbloc ; pcd=pcd->suivant)
|
223 |
|
|
{ /* On parcourt tous les précodes de la ligne. */
|
224 |
|
|
if (pcd->erreur==NO_ERR && pcd->mask!=NULL)
|
225 |
|
|
{
|
226 |
|
|
char str[3*sizeof(type_taille_mask)+3];
|
227 |
|
|
|
228 |
|
|
if (!pco_ecrit) /* Le pco n'est écrit que sur les lignes */
|
229 |
|
|
{ /* générant du code et ce une seule fois. */
|
230 |
|
|
fprintf(f_lst, "%04X ", pcd->pco);
|
231 |
|
|
pco_ecrit=1;
|
232 |
|
|
}
|
233 |
|
|
|
234 |
|
|
sprintf(str, "%%0%dX", pcd->mask->taille*2);
|
235 |
|
|
fprintf(f_lst, str, pcd->mask->valeur);
|
236 |
|
|
}
|
237 |
|
|
}
|
238 |
|
|
|
239 |
|
|
/* On complète avec des espaces pour aligner le code source. */
|
240 |
|
|
for ( col=ftell(f_lst)-col ; col<COL_TEXT ; col++) fputc(' ', f_lst);
|
241 |
|
|
|
242 |
|
|
ligne_cp(f_src, f_lst); /* Ecriture de la ligne source du code traité. */
|
243 |
|
|
ligne++;
|
244 |
|
|
|
245 |
|
|
while (pcd_cour!=NULL && pcd_cour->ligne_orig==lbloc)
|
246 |
|
|
{ /* Ecriture des éventuelles erreurs du bloc. */
|
247 |
|
|
if (pcd_cour->erreur!=NO_ERR)
|
248 |
|
|
{ /* On affiche le message d'erreur dans la liste d'assemblage. */
|
249 |
|
|
int i;
|
250 |
|
|
err_code=pcd_cour->erreur;
|
251 |
|
|
fputc('\t', f_lst);
|
252 |
|
|
for (i=0; i<COL_TEXT; i++) fputc(' ', f_lst);
|
253 |
|
|
fprintf(f_lst, "%s\n", search_msg());
|
254 |
|
|
}
|
255 |
|
|
pcd_cour=pcd_cour->suivant;
|
256 |
|
|
}
|
257 |
|
|
}
|
258 |
|
|
|
259 |
|
|
/* Recopie de la fin du fichier source dans la liste d'assemblage. */
|
260 |
|
|
while (!feof(f_src))
|
261 |
|
|
{
|
262 |
|
|
int i;
|
263 |
|
|
fprintf(f_lst, "%d\t", ligne++);
|
264 |
|
|
for (i=0; i<COL_TEXT; i++) fputc(' ', f_lst);
|
265 |
|
|
ligne_cp(f_src, f_lst);
|
266 |
|
|
}
|
267 |
|
|
fprintf(f_lst, "\n");
|
268 |
|
|
|
269 |
|
|
write_data(f_lst); /* Ecriture des données complémentaires de l'adaptateur. */
|
270 |
|
|
}
|