OpenCores
URL https://opencores.org/ocsvn/minimips/minimips/trunk

Subversion Repositories minimips

[/] [minimips/] [trunk/] [gasm/] [src/] [preprocesseur.c] - Blame information for rev 15

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 13 louismarie
/*********************************************************************************************
2
 *                                                                                           *
3
 *                                 MODULE PREPROCESSEUR                                      *
4
 *                                                                                           *
5
 *      Ce module a pour but de fournir sur demande les lexemes correspondant au code        *
6
 * du fichiers .ASM avec lequel il a été initialisé.                                         *
7
 *                                                                                           *
8
 *      Il gere aussi l'inclusion de fichiers et l'expansion des macros.                     *
9
 *                                                                                           *
10
 *      Points d'entrée : les fonctions push_lexemes() et pop_lexeme()                       *
11
 *                                                                                           *
12
 *********************************************************************************************/
13
 
14
/* Déclarations des symbols de ce module                                                     */
15
#include "preprocesseur.h"
16
 
17
/* Inclusion de la bibliothèque standard                                                     */
18
#include <stdio.h>
19
#include <string.h>
20
#include <stdlib.h>
21
#include <ctype.h>
22
 
23
/* Inclusion des modules du projet utilisés                                                  */
24
#include <debogueur.h>
25
#include <parametres.h>
26
#include <dialogue.h>
27
#include <formateur.h>
28
 
29
#define SYNTAX_ERROR(CODE)\
30
        {\
31
                char * msg;\
32
                msg=gen_orig_msg();\
33
                DIALOGUE(msg, ligne_courante(), CODE);\
34
                free(msg);\
35
        }
36
 
37
/*********************************************************************************************
38
 *                                                                                           *
39
 * Types spécifiques à ce module                                                             *
40
 *                                                                                           *
41
 *********************************************************************************************/
42
 
43
typedef struct type_pdf_tmp
44
{
45
        FILE * flux;
46
        unsigned int ligne;     /* numéro de la ligne en cours de lecture dans ce flux       */
47
        char * nom_fich;        /* nom du fichier en cours de lecture                        */
48
        char * nom_macro;       /* nom de la macro si c'en est une pour eviter l'autoappel   */
49
        struct type_pdf_tmp * prec;             /* Flux entassé                              */
50
} type_pdf;
51
 
52
typedef struct type_pdm_tmp
53
{
54
        char * nom_macro;               /* Lexeme dont la rencontre entraine une expansion   */
55
        long def_pos;           /* Position dans le fichier de définition                    */
56
        struct type_pdm_tmp * suiv;
57
} type_pdm;
58
 
59
/*********************************************************************************************
60
 *                                                                                           *
61
 * Variables spécifiques à ce module                                                         *
62
 *                                                                                           *
63
 *********************************************************************************************/
64
 
65
/* Le pointeur vers l'élément en cours de lecture de la pile de flux                         */
66
static type_pdf * ptr_pdf=NULL;
67
 
68
/* La file de lexèmes où sont empilés les lexèmes "recrachés" par push_lex apres un pop_lex  */
69
static type_file_lexeme * ptr_pdl=NULL;
70
 
71
/* Pointeur vers la fonction strcmp ou strcasecmp selon la casse_sens                        */
72
static int (*fcmp)()=NULL;
73
#define CAR_EQ(a, b) ( casse_sens ? (a==b) : (tolower(a)==tolower(b)) )
74
 
75
/* Le pointeur vers le début de la pile de macros                                            */
76
static type_pdm * ptr_pdm=NULL;
77
 
78
/* Fichier temporaire, contiendra toutes les définitions de macro du code ASM                */
79
FILE * fich_macro=NULL;
80
 
81
/*********************************************************************************************
82
 *                                                                                           *
83
 * Fonctions non exportées                                                                   *
84
 *                                                                                           *
85
 *********************************************************************************************/
86
 
87
static void empile_flux(char * nom_fich, char * nom_macro);
88
static void depile_flux();
89
static type_pdm * is_macro(char *);
90
static type_lexeme * read_lexeme();
91
static type_lexeme * get_true_lexeme(FILE * fich);
92
static void expanse_macro(type_pdm * ptr);
93
 
94
void empile_flux(char * nom_fich, char * nom_macro)
95
{
96
        type_pdf * ptr;
97
        char errmsg[]="preprocesseur(empile_flux)";
98
 
99
        /* Vérifications anti-inclusions circulaires de macros et de fichiers */
100
        ptr=ptr_pdf;
101
        while(ptr!=NULL)
102
        {
103
                if (nom_fich)
104
                        if (strcmp(nom_fich, ptr->nom_fich)==0)
105
                        {
106
                                SYNTAX_ERROR(S_CIRCULAR_FILE)
107
                                return;
108
                        }
109
                if (nom_macro)
110
                        if (ptr->nom_macro && (*fcmp)(nom_macro, ptr->nom_macro)==0)
111
                        {
112
                                SYNTAX_ERROR(S_CIRCULAR_MACRO)
113
                                return;
114
                        }
115
                ptr=ptr->prec;
116
        }
117
 
118
        /* Allocation de la structure */
119
        ptr=(type_pdf *) malloc(sizeof(type_pdf));
120
        if (!ptr) DIALOGUE(errmsg, 0, F_ERR_MEM);
121
 
122
        /* Initialisation des champs */
123
        ptr->flux=NULL;
124
        ptr->ligne=1;
125
        ptr->nom_fich=NULL;
126
        ptr->nom_macro=NULL;
127
        ptr->prec=NULL;
128
 
129
        /* Ouverture du fichier */
130
        if (nom_fich)
131
        {
132
                ptr->flux=fopen(nom_fich, "rb");
133
                if (!ptr->flux)
134
                {
135
                        char * msg;
136
                        msg=gen_orig_msg();
137
                        DIALOGUE(msg, ptr_pdf->ligne, S_FICH_NON_TROUVE);
138
                        free(msg);
139
                        free(ptr);
140
                        return;
141
                }
142
 
143
        /* Recopie des chaines transmises en parametres */
144
                ptr->nom_fich=(char *) malloc(strlen(nom_fich));
145
                if (!ptr->nom_fich) DIALOGUE(errmsg, 0, F_ERR_MEM);
146
                strcpy(ptr->nom_fich, nom_fich);
147
        }
148
        if (nom_macro)
149
        {
150
                ptr->nom_macro=(char *) malloc(strlen(nom_macro));
151
                if (!ptr->nom_macro) DIALOGUE(errmsg, 0, F_ERR_MEM);
152
                strcpy(ptr->nom_macro, nom_macro);
153
        }
154
 
155
        /* Empilement */
156
        ptr->prec=ptr_pdf;
157
        ptr_pdf=ptr;
158
}
159
 
160
void depile_flux()
161
{
162
        type_pdf * ptr_sav;
163
        ptr_sav=ptr_pdf->prec;
164
        fclose(ptr_pdf->flux);
165
        if (ptr_pdf->nom_macro)
166
                free(ptr_pdf->nom_macro);
167
        else
168
                free(ptr_pdf->nom_fich);
169
        free(ptr_pdf);
170
        ptr_pdf=ptr_sav;
171
}
172
 
173
/* Cette fonction cherche et retourne la position d'une macro dans la table.                 */
174
type_pdm * is_macro(char * lex_alpha)
175
{
176
        type_pdm * ptr_mac;
177
        for(    ptr_mac=ptr_pdm;
178
                ptr_mac && (*fcmp)(ptr_mac->nom_macro, lex_alpha);
179
                ptr_mac=ptr_mac->suiv)
180
                ;
181
        return ptr_mac;
182
}
183
 
184
/* Cette fonction renvoie le prochain lexeme valide disponible dans la pile de flux,         *
185
 * ou NULL, mais uniquement si plus auncun flux n'est ouvert (analyse terminée).             *
186
 * Elle s'occupe d'empiler les flux en cas d'inclusion, les dépile quand elle intercepte un  *
187
 * lexème EOF (qu'elle ne renvoie jamais). Enfin, elle détecte les macros et leur défs.      */
188
type_lexeme * read_lexeme()
189
{
190
        type_lexeme * ptr_lex;
191
        static int germac=1;            /* Permet de ne pas expansionner                     *
192
                                         * certains bouts de code...                         */
193
        static int last_is_NL=0;        /* On considère les NL en fin de ligne,              *
194
                                         * pas en début de ligne suivante...                 */
195
 
196
        /* Aucun fichier ouvert => NULL                                                      */
197
        if (ptr_pdf==NULL) return NULL;
198
 
199
        if (last_is_NL)
200
        {
201
                last_is_NL=0;
202
                ptr_pdf->ligne++;
203
        }
204
 
205
        /* Retourne un lexème en filtrant les erreurs du formateurs                          */
206
        ptr_lex=get_true_lexeme(ptr_pdf->flux);
207
 
208
        /* Traitement des macros et sous-typage                                              */
209
        if (TYPE_IS(ptr_lex, ALPHA))    /* si macro expansion, sinon sous-typage             */
210
        {
211
                int i;
212
                char * p_regle, * p_alpha;
213
                type_pdm * ptr_mac;
214
                if (germac && (ptr_mac=is_macro(ptr_lex->valeur.alpha))!=NULL)
215
                {
216
                        FREE_LEX(ptr_lex);
217
                        expanse_macro(ptr_mac);
218
                        ptr_lex=read_lexeme();
219
                }
220
                else                            /* Test si c'est sous-typable                */
221
                for(i=0; i<nbr_sous_types && regle_typage[i].chaine; i++)
222
                {
223
                        p_regle=regle_typage[i].chaine;
224
                        p_alpha=ptr_lex->valeur.alpha;
225
                        while((*p_regle)!='\0')
226
                        {
227
                                if ((*p_regle)=='?')    /* Remplacmt par un caractère        */
228
                                {                       /* les 2 car suiv sont les bornes    */
229
                                        if ((*p_alpha)<*(++p_regle) || (*p_alpha)>*(++p_regle))
230
                                                break;
231
                                }
232
                                else if (!CAR_EQ(*p_regle, *p_alpha)) break;
233
                                p_regle++;
234
                                p_alpha++;
235
                        }
236
                        /* Si le lexème match la règle, on sous-type...                      */
237
                        if ((*p_regle)=='\0' && (*p_alpha)=='\0')
238
                        {
239
                                /* La valeur du lexème n'est pas modifiée                    */
240
                                ptr_lex->type = POS_MPV(regle_typage[i].code);
241
                                break;
242
                        }
243
                }
244
        }
245
 
246
        else
247
 
248
        /* Traitment des directives, des sauts de ligne et des fin de flux                   */
249
        if (TYPE_IS(ptr_lex, OP))       /* Traitements spéciaux                              */
250
                switch(ptr_lex->valeur.op)
251
                {
252
                        case NL:        /* Fin de ligne                                      */
253
                                last_is_NL=1;
254
                                break;
255
                        case EOF:       /* Fin de fichier : on ne retourne pas de lexemes    */
256
                                FREE_LEX(ptr_lex)
257
                                depile_flux();
258
                                ptr_lex=read_lexeme();
259
                                break;
260
                        case DIR:       /* Directive de Préprocesseur                        */
261
                        {
262
                                type_lexeme * ptr_sauv_lex;
263
                                int pas_dir=1;  /* Drapeau soupconneux                       */
264
                                ptr_sauv_lex=ptr_lex;
265
                                germac=0;
266
                                ptr_lex=read_lexeme();
267
                                if (TYPE_IS(ptr_lex, ALPHA))
268
                                {
269
                                        if (define_str &&
270
                                                (*fcmp)(ptr_lex->valeur.alpha, define_str)==0)
271
                                        {       /* Ajout d'1 macro                           */
272
                                                pas_dir=0;
273
                                                FREE_LEX(ptr_lex);
274
                                                ptr_lex=read_lexeme();
275
                                                if (!TYPE_IS(ptr_lex, ALPHA))
276
                                                        SYNTAX_ERROR(S_NOM_MAC_INVALID)
277
                                                else
278
                                                        ajoute_macro(ptr_lex->valeur.alpha
279
                                                                        , ptr_pdf->flux);
280
                                        }
281
                                        else if (include_str &&
282
                                                (*fcmp)(ptr_lex->valeur.alpha,include_str)==0)
283
                                        {       /* Empliement d'un fichier                   */
284
                                                pas_dir=0;
285
                                                FREE_LEX(ptr_lex);
286
                                                ptr_lex=read_lexeme();
287
                                                if (!TYPE_IS(ptr_lex, ALPHA))
288
                                                        SYNTAX_ERROR(S_NOM_INCFICH_INVALID)
289
                                                else
290
                                                        empile_flux(ptr_lex->valeur.alpha
291
                                                                ,NULL);
292
                                        }
293
                                        else if (undef_str &&
294
                                                (*fcmp)(ptr_lex->valeur.alpha,undef_str)==0)
295
                                        {       /* Empliement d'un fichier                   */
296
                                                pas_dir=0;
297
                                                FREE_LEX(ptr_lex);
298
                                                ptr_lex=read_lexeme();
299
                                                if (!TYPE_IS(ptr_lex, ALPHA))
300
                                                        SYNTAX_ERROR(S_NOM_MAC_INVALID)
301
                                                else
302
                                                        suppress_macro(ptr_lex->valeur.alpha);
303
                                        }
304
                                }
305
                                germac=1;
306
                                if (pas_dir) /* Si, en fait, ce n'était pas une dir          */
307
                                {
308
                                        push_lexeme(ptr_lex);   /* on sauve le lexème testé  */
309
                                        ptr_lex=ptr_sauv_lex;   /* on renvoie le lexème DIR  */
310
                                }
311
                                else
312
                                {
313
                                        FREE_LEX(ptr_sauv_lex);
314
                                        FREE_LEX(ptr_lex);
315
                                        ptr_lex=read_lexeme();
316
                                }
317
                        }
318
                }
319
 
320
        return ptr_lex;
321
}
322
 
323
/* Cette fonction sert d'interface entre le préprocesseur et le formateur.                   *
324
 * Elle se charge d'afficher ses messages d'erreur et de lire le lexème suivant quand ce     *
325
 * dernier renvoie NULL.                                                                     */
326
type_lexeme * get_true_lexeme(FILE * fich)
327
{
328
        type_lexeme * p;
329
        p=get_lexeme(fich);
330
        if (p==NULL)
331
        {
332
                SYNTAX_ERROR(err_code)
333
                p=get_true_lexeme(fich);
334
        }
335
        return p;
336
}
337
 
338
/* Vide le flux jusqu'a la prochaine accolade ouvrante comprise,                             *
339
 * Elle renvoie 0 si tout s'est bien passé, 1 si EOF est rencontré                           */
340
int next_ACO(FILE * flux)
341
{
342
        int drap=0;
343
        type_lexeme * p;
344
        do
345
        {
346
                p=get_true_lexeme(flux);
347
                if (TYPE_IS(p, OP))
348
                {
349
                        if (p->valeur.op==EOF)
350
                        {
351
                                FREE_LEX(p)
352
                                err_code=S_DEF_MACRO_EOF;
353
                                return 1;
354
                        }
355
                        if (p->valeur.op==ACO) drap=1;
356
                }
357
                FREE_LEX(p);
358
        }
359
        while(!drap);
360
        return 0;
361
}
362
 
363
/* Retourne le lexème suivant du flux, ou NULL s'il s'agit d'une accolade fermante ou d'EOF. *
364
 * Il faut alors testé la variable err_code pour savoir s'il s'agit d'un e erreur ou pas.    */
365
type_lexeme * read_all_but_ACF(FILE * flux)
366
{
367
        type_lexeme * p;
368
        p=get_true_lexeme(flux);
369
        if (TYPE_IS(p,OP))
370
        {
371
                if (p->valeur.op==EOF)
372
                {
373
                        FREE_LEX(p)
374
                        err_code=S_DEF_MACRO_EOF;
375
                        return NULL;
376
                }
377
                if (p->valeur.op==ACF)
378
                {
379
                        FREE_LEX(p)
380
                        err_code=NO_ERR;
381
                        return NULL;
382
                }
383
        }
384
        return p;
385
}
386
 
387
/* Fonction assurant le controle de la validité de la définition de la macro, son expansion  *
388
 * dans un nouveau buffer qu'elle empile avant de rendre la main.                            */
389
void expanse_macro(type_pdm * ptr_mac)
390
#define FREE_TABLE\
391
        while(table)\
392
        {\
393
                parcourt_table=table->suiv;\
394
                FREE_LEX(table->nom_param);\
395
                if (table->val_param) FREE_LEX(table->val_param)\
396
                free(table);\
397
                table=parcourt_table;\
398
        }
399
{
400
        /* Structure servant au stockage temporaire des paramètres formels de la macro.      */
401
        typedef struct type_file_param_tmp
402
        {
403
                type_lexeme * nom_param;
404
                type_lexeme * val_param;
405
                struct type_file_param_tmp * suiv;
406
        } type_file_param;
407
 
408
        type_file_param * table=NULL, * parcourt_table=NULL, * ptr_new=NULL;
409
        type_lexeme * ptr_lex=NULL, * ptr_lex_asm=NULL;
410
        FILE * ftemp;
411
 
412
        /* Positionnement au début de la définition de la macro                              */
413
        fseek(fich_macro, ptr_mac->def_pos, SEEK_SET);
414
 
415
        /* Recherche du début du bloc de paramètres                                          */
416
        if (next_ACO(fich_macro))
417
        {
418
                SYNTAX_ERROR(err_code)
419
                return;
420
        }
421
 
422
        /* Lecture des paramètres et placement dans la table jusqu'à l'accolade fermante     */
423
        while((ptr_lex=read_all_but_ACF(fich_macro))!=NULL)
424
        {
425
                /* Placement à la fin de la table                                            */
426
                ptr_new=(type_file_param *) malloc(sizeof(type_file_param));
427
                if (!ptr_new) DIALOGUE("preprocesseur(expanse_macro)", 0, F_ERR_MEM);
428
                ptr_new->nom_param=ptr_lex;
429
                ptr_new->val_param=NULL;
430
                ptr_new->suiv=NULL;
431
                if (parcourt_table)
432
                        parcourt_table=parcourt_table->suiv=ptr_new;
433
                else
434
                        table=parcourt_table=ptr_new;
435
                /* Attention, pas de FREE_LEX car placement dans la table                    */
436
        }
437
        if (err_code!=NO_ERR)
438
        {
439
                SYNTAX_ERROR(err_code)
440
                FREE_TABLE
441
                return;
442
        }
443
 
444
        /* Recherche du début du bloc de syntaxe                                             */
445
        if (next_ACO(fich_macro))
446
        {
447
                SYNTAX_ERROR(err_code)
448
                return;
449
        }
450
 
451
        /* Parcourt la syntaxe macro, la valide, mémorise la valeur des paramètres           */
452
        while((ptr_lex=read_all_but_ACF(fich_macro))!=NULL)
453
        {
454
                /* Parcourt de l'utilisation de la macro                                     */
455
                ptr_lex_asm=get_true_lexeme(ptr_pdf->flux);
456
                /* Recherche s'il s'agit d'un paramètre                                      */
457
                for(    parcourt_table=table;
458
                        parcourt_table!=NULL
459
                        && !id_lexeme(parcourt_table->nom_param, ptr_lex, casse_sens);
460
                        parcourt_table=parcourt_table->suiv);
461
                /* Si c'est le cas, on mémorise sa valeur                                    */
462
                if (parcourt_table) parcourt_table->val_param=ptr_lex_asm;
463
                else
464
                {
465
                        if (!id_lexeme(ptr_lex, ptr_lex_asm, casse_sens))
466
                        {
467
                                err_code=S_MAC_NO_MATCH;
468
                                FREE_LEX(ptr_lex)
469
                                FREE_LEX(ptr_lex_asm)
470
                                break;  /* La syntaxe n'est pas respectée                    */
471
                        }
472
                        FREE_LEX(ptr_lex_asm)
473
                }
474
                FREE_LEX(ptr_lex)
475
        }
476
        if (err_code!=NO_ERR)
477
        {
478
                SYNTAX_ERROR(err_code)
479
                FREE_TABLE
480
                return;
481
        }
482
 
483
        /* On controle que tous les paramètres ont une valeur, à présent                     */
484
        for(    parcourt_table=table;
485
                parcourt_table;
486
                parcourt_table=parcourt_table->suiv)
487
                if (parcourt_table->val_param==NULL)
488
                {
489
                        SYNTAX_ERROR(S_MAC_TROP_PARAM)
490
                        FREE_TABLE
491
                        return;
492
                }
493
 
494
        /* Positionnement au début de la séquence de remplacement                            */
495
        if (next_ACO(fich_macro))
496
        {
497
                SYNTAX_ERROR(err_code)
498
                FREE_TABLE
499
                return;
500
        }
501
 
502
        /* On expanse dans un buffer temporaire                                              */
503
        ftemp=tmpfile();
504
 
505
        /* Recopie de cette séquence en remplaçant les paramètres                            */
506
        while((ptr_lex=read_all_but_ACF(fich_macro))!=NULL)
507
        {
508
                /* Est-ce un paramètre ?                                                     */
509
                for(    parcourt_table=table;
510
                        parcourt_table
511
                        && !id_lexeme(parcourt_table->nom_param, ptr_lex, casse_sens);
512
                        parcourt_table=parcourt_table->suiv);
513
                if (parcourt_table==NULL)       /* Si ce n'en est pas un                     */
514
                        fprint_lexeme(ftemp, ptr_lex);
515
                else
516
                        fprint_lexeme(ftemp, parcourt_table->val_param);
517
                fputc(' ', ftemp);
518
                FREE_LEX(ptr_lex);
519
        }
520
 
521
        /* Nous n'avons à présent plus besoin de la table...                                 */
522
        FREE_TABLE
523
        if (err_code!=NO_ERR)
524
        {
525
                fclose(ftemp);
526
                SYNTAX_ERROR(err_code)
527
                return;
528
        }
529
 
530
        /* Ouf ! Expansion réussie...                                                        */
531
        empile_flux(NULL, ptr_mac->nom_macro);
532
        ptr_pdf->flux=ftemp;
533
        rewind(ftemp);
534
}
535
 
536
/*********************************************************************************************
537
 *                                                                                           *
538
 * Fonctions exportées                                                                       *
539
 *                                                                                           *
540
 *********************************************************************************************/
541
 
542
/* Cette fonction empile le fichier spécifié après avoir testé son existence.                *
543
 * Elle prépare l'exécution du préprocesseur à travers pop_lexeme.                           *
544
 * Elle renvoie 0 si le fichier a bien été empilé, 1 sinon.                                  */
545
int init_preprocesseur(char * fichinit)
546
{
547
        FILE * ftest;
548
        char errmsg[]="preprocesseur(init_preprocesseur)";
549
        int i;
550
 
551
        /* Pointeur sur la fonction de comparaison adéquate                                  */
552
        fcmp=casse_sens ? (void *) &strcmp : (void *) &strcasecmp;
553
 
554
        /* On test l'existence des directives                                                */
555
        if (include_str!=NULL && active_list)
556
        {
557
                DIALOGUE(NULL, 0, W_NO_LIST_INC)
558
                active_list=0;  /* Liste d'assemblage non prévue pour fonctionner en cas     */
559
                                /* inclusions de fichiers.                                   */
560
        }
561
 
562
        /* Controle de validité des regles de sous-typage une fois pour toutes.              *
563
         * La règle invalide est supprimée.                                                  */
564
        for(i=0; i<nbr_sous_types; i++)
565
        {
566
                char * ptr=regle_typage[i].chaine;
567
                while(*ptr++!='\0')
568
                        if (*ptr=='?' || *ptr=='*')
569
                        {
570
                                if (*++ptr=='\0' || *++ptr=='\0')
571
                                {
572
                                        DIALOGUE(NULL, 0, W_REGLE_TYPAGE)
573
                                        free(regle_typage[i].chaine);
574
                                        regle_typage[i].chaine=NULL;
575
                                }
576
                        }
577
        }
578
 
579
        /* On crée un fichier temporaire pour la définition des macros,                      *
580
         * s'il n'existe pas déjà.                                                           */
581
        if (fich_macro==NULL) fich_macro=tmpfile();
582
 
583
        /* On empile le fichier source de départ                                             */
584
        if (fichinit[0]=='\0')  /* Empilement de stdin en l'absence de fichier source        */
585
        {
586
                type_pdf * ptr;
587
 
588
                /* Allocation de la structure                                                */
589
                ptr=(type_pdf *) malloc(sizeof(type_pdf));
590
                if (!ptr) DIALOGUE(errmsg, 0, F_ERR_MEM);
591
 
592
                /* Initialisation des champs                                                 */
593
                ptr->flux=stdin;
594
                ptr->ligne=1;
595
                ptr->nom_macro=NULL;
596
                ptr->prec=NULL;
597
 
598
                /* Recopie des chaines transmises en parametres                              */
599
                ptr->nom_fich=(char *) malloc(6);
600
                if (!ptr->nom_fich) DIALOGUE(errmsg, 0, F_ERR_MEM);
601
                strcpy(ptr->nom_fich, "stdin");
602
 
603
                /* Empilement                                                                */
604
                ptr->prec=ptr_pdf;
605
                ptr_pdf=ptr;
606
 
607
                if (active_list)
608
                {
609
                        DIALOGUE(NULL, 0, W_NO_LIST_STDIN);
610
                        active_list=0;  /* Liste d'assemblage non prévue pour fonctionner    *
611
                                         * en cas d'utilisation du stdin.                    */
612
                }
613
        }
614
        else
615
        {
616
                if ((ftest=fopen(fichinit, "rb"))==NULL) return 1;
617
                fclose(ftest);
618
                empile_flux(fichinit, NULL);
619
        }
620
        return 0;
621
}
622
 
623
/* Cette fonction libère de la mémoire toutes les allocations du préprocesseur               */
624
void clear_preprocesseur()
625
{
626
        while(ptr_pdf) depile_flux();
627
        while(ptr_pdl) FREE_LEX(pop_lexeme());
628
        while(ptr_pdm)
629
        {
630
                type_pdm * p;
631
                p=ptr_pdm->suiv;
632
                free(ptr_pdm->nom_macro);
633
                free(ptr_pdm);
634
                ptr_pdm=p;
635
        }
636
}
637
 
638
/* Cette fonction renvoie le prochain lexeme valide disponible. Elle regarde d'abord dans la *
639
 * pile de lexèmes. Si celle-ci est vide elle le prend dans la pile de flux, en appelant     *
640
 * read_lexeme().                                                                            *
641
 * Un ptr NULL est renvoyé uniquement si plus auncun flux n'est ouvert (analyse terminée).   */
642
type_lexeme * pop_lexeme()
643
{
644
        if (ptr_pdl==NULL) /* Pas de lexemes stockés                                         */
645
        {
646
                return read_lexeme();
647
        }
648
        else    /* On dépile le lexème du tampon                                             */
649
        {
650
                type_file_lexeme * ptr_sav;
651
                type_lexeme * ptr_lex;
652
 
653
                ptr_sav = ptr_pdl->suivant;
654
                ptr_lex = ptr_pdl->lexeme;
655
                free(ptr_pdl);
656
                ptr_pdl=ptr_sav;
657
                return ptr_lex;
658
        }
659
}
660
 
661
/* Sauvegarde des lexèmes qui ont déjà été extraits des flux                                */
662
void push_lexeme(type_lexeme * ptr_recrach)
663
{
664
        type_file_lexeme * ptr_sav;
665
 
666
        ptr_sav = ptr_pdl;
667
        ptr_pdl = (type_file_lexeme *) malloc(sizeof(type_file_lexeme));
668
        if (!ptr_pdl) DIALOGUE("preprocesseur(push_lexeme)", 0, F_ERR_MEM);
669
        ptr_pdl->suivant=ptr_sav;
670
        ptr_pdl->lexeme=ptr_recrach;
671
}
672
 
673
/* Retourne la ligne où a été lu le dernier lexème ou 0 si pas de fichiers ouverts          */
674
int ligne_courante()
675
{
676
        type_pdf * p=ptr_pdf;
677
        while(p && p->nom_macro) p=p->prec;
678
        if (p==NULL) return 0;
679
        return p->ligne;
680
}
681
 
682
/* Indique les noms successifs des fichiers d'origine du lexème.                            *
683
 * Ne pas oublier de faire free sur le pointeur renvoyé !!!                                 */
684
char * gen_orig_msg()
685
{
686
        char * text;
687
        type_pdf * ptr;
688
        int t_src=0, t_dest=MAX_LONG_ALPHA, t_sep;
689
 
690
        t_sep=strlen(sep_fich_inclus);
691
        text=(char *) malloc(t_dest);
692
        text[0]=0;
693
        for(ptr=ptr_pdf; ptr; ptr=ptr->prec)
694
        {
695
                if (ptr->nom_macro) continue;
696
                t_src+=strlen(ptr->nom_fich)+t_sep;
697
                if (t_src >= t_dest)
698
                {
699
                        t_dest=t_src+1;
700
                        text=(char *) realloc(text, t_dest);
701
                }
702
                strcat(text, ptr->nom_fich);
703
                if (ptr->prec) strcat(text, sep_fich_inclus);
704
        }
705
        return text;
706
}
707
 
708
/* La macro est supprimée de la table, mais pas du buffer contenant sa définition.           */
709
void suppress_macro(char * nom_macro)
710
{
711
        type_pdm * ptr_mac, * ptr_mac_prec;
712
 
713
        ptr_mac_prec=NULL;      /* On sauvegarde le maillon où il faudra raccrocher les      *
714
                                 * macros en aval du maillon à supprimer.                    */
715
        for(    ptr_mac=ptr_pdm;
716
                ptr_mac && (*fcmp)(ptr_mac->nom_macro, nom_macro);
717
                ptr_mac=ptr_mac->suiv)
718
                ptr_mac_prec=ptr_mac;
719
 
720
        if (ptr_mac)
721
        {
722
                type_pdm * psav;
723
                psav=ptr_mac->suiv;
724
                free(ptr_mac->nom_macro);
725
                free(ptr_mac);
726
                if (ptr_mac_prec)
727
                        ptr_mac_prec->suiv=psav;
728
                else
729
                        ptr_pdm=psav;
730
        }
731
        else
732
                SYNTAX_ERROR(W_UNDEF_NOMAC)
733
}
734
 
735
/* Ajoute une macro à la pile des macros                                                    */
736
void ajoute_macro(char * nom_macro, FILE * flux_def)
737
{
738
        int c,i;
739
        long pos;
740
        char * org_msg = "preprocesseur(ajoute_macro)";
741
 
742
        if (is_macro(nom_macro))        /* Cas d'une redéfinition                           */
743
        {
744
                SYNTAX_ERROR(W_REDEF_MAC)
745
                suppress_macro(nom_macro);
746
        }
747
 
748
        fseek(fich_macro, 0L, SEEK_END);
749
        pos=ftell(fich_macro);
750
 
751
        /* Recopie de la définition de la macro                                             */
752
        for(i=0; i<3; c==ACF ? i++ : i)
753
        {
754
                if ((c=fgetc(flux_def))==EOF)
755
                {
756
                        if (feof(flux_def))
757
                                SYNTAX_ERROR(S_DEF_MACRO_EOF)
758
                        else
759
                                DIALOGUE(org_msg, 0, F_ERR_LECT);
760
                        break;
761
                }
762
                fputc(c, fich_macro);
763
                if (c==NL && flux_def==ptr_pdf->flux) ptr_pdf->ligne++;
764
        }
765
 
766
        /* Si la copie s'est bien passée...                                                 */
767
        if (i==3)
768
        {
769
                type_pdm * ptr;
770
                ptr=(type_pdm *) malloc(sizeof(type_pdm));
771
                if (!ptr) DIALOGUE(org_msg, 0, F_ERR_MEM);
772
                ptr->nom_macro=(char *) malloc(strlen(nom_macro));
773
                strcpy(ptr->nom_macro,nom_macro);
774
                ptr->def_pos=pos;
775
                ptr->suiv=NULL;
776
                if (ptr_pdm)    /* Ajout à la fin de la pile                                */
777
                {
778
                        type_pdm * ptr_fin;
779
                        ptr_fin=ptr_pdm;
780
                        while (ptr_fin->suiv) ptr_fin=ptr_fin->suiv;
781
                        ptr_fin->suiv=ptr;
782
                }
783
                else
784
                        ptr_pdm=ptr;
785
        }
786
}
787
 
788
/* Petite fonction utile pour consulter (dans le stderr) la liste des macros disponibles    */
789
void liste_table_macro(FILE * f)
790
{
791
        type_pdm * p;
792
        type_lexeme * ptr_lex;
793
        if (ptr_pdm)
794
                err_code=B_MACRO_DISPO;
795
        else
796
                err_code=B_NO_MACRO;
797
        fprintf(f, "-- %s\n", search_msg());
798
 
799
        for(p=ptr_pdm; p!=NULL; p=p->suiv)
800
        {
801
                fprintf(f,"-- \t%s ",p->nom_macro);
802
                fseek(fich_macro, p->def_pos, SEEK_SET);
803
                /* Ecriture de la syntaxe                                                   */
804
                if (next_ACO(fich_macro) || next_ACO(fich_macro))
805
                {
806
                        SYNTAX_ERROR(err_code)
807
                        continue;
808
                }
809
                while((ptr_lex=read_all_but_ACF(fich_macro))!=NULL)
810
                {
811
                        fprint_lexeme(f, ptr_lex);
812
                        FREE_LEX(ptr_lex)
813
                }
814
                if (err_code!=NO_ERR)
815
                {
816
                        SYNTAX_ERROR(err_code)
817
                        continue;
818
                }
819
                fprintf(f, "\t\t");
820
                /* Ecriture de la séquence de remplacement                                  */
821
                if (next_ACO(fich_macro))
822
                {
823
                        SYNTAX_ERROR(err_code)
824
                        continue;
825
                }
826
                while((ptr_lex=read_all_but_ACF(fich_macro))!=NULL)
827
                {
828
                        fprint_lexeme(f, ptr_lex);
829
                        fputc(' ', f);
830
                        FREE_LEX(ptr_lex)
831
                }
832
                if (err_code!=NO_ERR)
833
                {
834
                        SYNTAX_ERROR(err_code)
835
                        continue;
836
                }
837
                fprintf(f, "\n");
838
        }
839
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.