source: vital-to8-sdk/c6809/c6809.c

Last change on this file was 1, checked in by svn, 5 years ago

Import initial

File size: 146.3 KB
RevLine 
[1]1/*
2 *  C6809 - Compilateur macro-assembler pour Thomson (MacroAssembler-like)
3 *
4 *  Programme principal
5 *
6 *  Copyright (C) mars 2010 François Mouret
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation; either version 2 of the License, or
11 *  (at your option) any later version.
12 *
13 *  This program is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *  GNU General Public License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with this program; if not, write to the Free Software
20 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22 
23#include <stdio.h>
24#include <stdlib.h>
25#include <ctype.h>
26#include <string.h>
27
28#ifndef TRUE
29#   define TRUE 1
30#endif
31
32#ifndef FALSE
33#   define FALSE 0
34#endif
35
36#ifndef NULL
37#   define NULL 0
38#endif
39
40
41/***********************************************************************
42 *
43 *     Variables globales
44 *
45 ***********************************************************************/
46
47#define CHAR127 '|'       /* Caractère de remplacement pour CHR$(127) */
48#define ARGV_MAX_SIZE 300
49#define LINE_MAX_SIZE 75  /* Taille maximum de la ligne à afficher */
50#define ARG_MAX_SIZE  40  /* Taille maximum d'un argument */
51#define ASM_MAX_SIZE 29000 /* Taille maximum en octets pour un fichier ASM */
52
53/* Correspondance caractères 'Occidental ISO-8859' */
54unsigned char acc_table[] = {
55    0xE7, /* ç */
56    0xE1, /* á */
57    0xE2, /* â */
58    0xE4, /* ä */
59    0xE0, /* à */
60    0xE9, /* é */
61    0xEA, /* ê */
62    0xEB, /* ë */
63    0xE8, /* è */
64    0xEE, /* î */
65    0xEF, /* ï */
66    0xF4, /* ô */
67    0xF6, /* ö */
68    0xFB, /* û */
69    0xFC, /* ü */
70    0xF9  /* ù */
71} ;
72
73FILE *fp_lst = NULL ;       /* Pour listing d'assemblage */
74FILE *fp_asm = NULL ;       /* Pour sauvegarde au format ASM */
75char linebuffer[LINE_MAX_SIZE+2] ; /* Buffer de ligne */
76char *line ;          /* Pointeur de ligne */
77char *filebuffer ;    /* Buffer de source */
78char *source ;        /* Pointeur de source */
79char arg[ARG_MAX_SIZE+2] ;        /* Buffer d'argument */
80char labelname[ARG_MAX_SIZE+2] ;  /* Buffer du nom d'étiquette */
81
82
83/* -------------------------------------------------------------------
84 * Pour scan du source
85 */
86enum{
87    SOFT_ASSEMBLER,
88    SOFT_MACROASSEMBLER,
89    SOFT_UPDATE
90} ;
91enum{
92    TO_COMPUTER,
93    TO7_COMPUTER,
94    MO_COMPUTER
95} ;
96enum{
97    OPT_NO, /* Pas de code objet */
98    OPT_OP, /* Optimisation */
99    OPT_SS, /* Lignes séparées (sans effet) */
100    OPT_WE, /* Attente à l'erreur (sans effet) */
101    OPT_WL, /* Affiche les lignes à l'assemblage */
102    OPT_WS, /* Affiche les symboles à l'assemblage */
103    OPT_SIZEOF
104} ;
105struct {
106    int opt[OPT_SIZEOF] ; /* Table des options initiales (passage d'argument) */
107    int computer ;   /* Type de machine sélectionnée */
108    int soft ;       /* Type d'assembleur sélectionné */
109    int symb_order ; /* Ordre d'affichage des symboles */
110    int err_order ;  /* Ordre d'affichage des erreurs */
111    int limit ;      /* Taille limite d'une ligne */
112} scan ;
113
114
115/*-------------------------------------------------------------------
116 * Pour assemblage du source
117 */
118enum{
119    SCANPASS,  /* Pass de scan */
120    MACROPASS, /* Pass de macro */
121    PASS1,     /* Pass 1 d'assemblage */
122    PASS2      /* Pass 2 d'assemblage */
123} ;
124enum {
125    UNLOCKED,
126    IF_LOCK,
127    MACRO_LOCK,
128    COMMENT_LOCK = 4
129} ;
130
131struct {
132    char *source ; /* Pointeur courant sur le source */
133    int line ;     /* Numéro de ligne courante */
134    int pass ;     /* Numéro du pass d'assemblage */
135    int locked ;   /* Bloque l'enregistrement des codes machine */
136    int exit ;     /* Demande l'arrêt de l'assemblage si directive 'END' */
137    int size ;             /* Taille de l'assemblage */
138    unsigned char code[5] ; /* Buffer d'assemblage */
139    unsigned char dp ;     /* Valeur du DP */
140    unsigned short pc ;    /* Valeur du PC */
141    unsigned short exec ;  /* Valeur de l'adresse d'exécution */
142    int regcode ;          /* Code du registre éventuel (délivré par ScanLine()) */
143    int opt[OPT_SIZEOF] ;  /* Table des options courantes */
144} run ;
145
146
147/*-------------------------------------------------------------------
148 * Pour évaluation d'opérande
149 */
150struct {
151    int priority ;         /* Priorité de l'opérateur */
152    char sign ;            /* Signe de l'opérateur */
153    signed short operand ; /* Valeur opérande */
154    int type ;             /* SET_VALUE/EQU_VALUE/LABEL_VALUE/MACRO_VALUE
155                            * renvoyé par DoSymbol() (et donc Eval())*/
156    int pass ;             /* Pass de la dernière évaluation */
157} eval ;
158
159
160/*-------------------------------------------------------------------
161 * Pour assemblage conditionnel
162 */
163enum {
164    IF_TRUE,
165    IF_TRUE_ELSE,
166    IF_FALSE,
167    IF_FALSE_ELSE,
168    IF_STOP
169} ;
170struct {
171    int count ;   /* Compteur de degrés d'assemblage conditionnel */
172    int buf[17] ; /* Buffer des degrés d'assemblage conditionnel */
173} ifc ;
174
175
176/*-------------------------------------------------------------------
177 * Pour macro
178 */
179struct {
180    int count ; /* Identificateur de macro */
181    int level ; /* Degré d'appel de macro */
182} macro ;
183
184
185/*-------------------------------------------------------------------
186 * Pour marquage 'info'
187 */
188struct {
189    struct {
190        int count ; /* Nombre de cycles de base (-1 si pas) */
191        int plus ;  /* Nombre de cycles ajoutés (-1 si pas) */
192        int total ; /* Total du nombre de cycles */
193    } cycle ;
194    int size ; /* Taille du code assemblé parcouru */
195} info ;
196
197
198/*-------------------------------------------------------------------
199 * Pour marquage 'check'
200 */
201int check[4][2] ;
202
203
204/*-------------------------------------------------------------------
205 * Pour INCLUD
206 */
207struct INCLIST {
208     struct INCLIST *prev ; /* Pointeur sur l'INCLUD précédent */
209     int  drive ;    /* Numéro de lecteur */
210     char name[13] ; /* Nom du fichier : xxxxxxxx.xxx */
211     int  line  ;    /* Numéro de ligne de l'INCLUD */
212     int  count ;    /* Compteur d'INCLUD */
213     char *start ;   /* Pointeur sur début du code d'INCLUD */
214     char *end ;     /* Pointeur sur fin du code d'INCLUD */
215} ;
216
217struct INCLIST *first_includ ;
218
219/*-------------------------------------------------------------------
220 * Liste des codes d'erreur
221 */
222enum {
223    NO_ERROR,      /* Pas d'erreur */
224    ERR_ERROR,     /* Erreur */
225/* Erreurs affichées sans condition */
226    ERR_DUPLICATE_MAIN,
227    ERR_DUPLICATE_NAME,
228    ERR_FILE_NOT_FOUND,
229    ERR_ILLEGAL_CHAR,
230    ERR_IO_ERROR,
231    ERR_MISSING_MAIN,
232    ERR_WRONG_MARK,
233    ERR_EMBEDDED_MACRO,
234    ____BREAK_ERROR,
235/* Erreurs affichées seulement au pass 2 de l'assemblage avec
236 * affichage de la ligne du source */
237    ERR_BAD_ELSE,
238    ERR_BAD_FILE_FORMAT,
239    ERR_BAD_FILE_NAME,
240    ERR_BAD_LABEL,
241    ERR_BAD_MACRO_NAME,
242    ERR_BAD_OPERAND,
243    ERR_BAD_OPCODE,
244    ERR_BAD_PARAM,
245    ERR_DIVISION_BY_ZERO,
246    ERR_ENDM_WITHOUT_MACRO,
247    ERR_EXPRESSION_ERROR,
248    ERR_IF_OUT_OF_RANGE,
249    ERR_ILLEGAL_INCLUDE,
250    ERR_ILLEGAL_LABEL,
251    ERR_ILLEGAL_OPERAND,
252    ERR_INCLUDE_OUT_OF_RANGE,
253    ERR_LABEL_NAME_TOO_LONG,
254    ERR_MACRO_ERROR,
255    ERR_MACRO_INTO_IF_RANGE,
256    ERR_MACRO_OUT_OF_RANGE,
257    ERR_MISSING_ENDC,
258    ERR_MISSING_IF,
259    ERR_MISSING_INFORMATION,
260    ERR_MISSING_LABEL,
261    ERR_MISSING_OPERAND,
262    ERR_MULTIPLY_DEFINED_SYMBOL,
263    ERR_OPERAND_IS_MACRO,
264    ERR_SYMBOL_ERROR,
265    ERR_UNDEFINED_MACRO,
266/* Erreurs affichées seulement au pass 2 de l'assemblage mais
267 * sans afficher la ligne du source
268 * Pour certaines, l'erreur n'est pas affichée en 'return'
269 * pour que le pass 1 ne récupère pas une erreur dans le cas où
270 * l'étiquette se trouve après le branchement, alors que le pass
271 * 2 n'en récupèrera aucune si l'étiquette a été répertoriée au
272 * pass 1 */
273    ____NO_LINE_ERROR,
274    ERR_LINE_TOO_LONG,
275    ERR_0_BIT,
276    ERR_5_BITS,
277    ERR_8_BITS,
278    ERR_BINARY_NOT_LINEAR,
279    ERR_BRANCH_OUT_OF_RANGE,
280    ERR_CHECK_ERROR,
281    ERR_DP_ERROR,
282    ERR_OPERAND_OUT_OF_RANGE,
283    ERR_FORCE_TO_DP,
284    ERR_LONE_SYMBOL,
285    ERR_MISSING_END_STATEMENT,
286    ERR_MISSING_ENDM,
287    ERR_MISSING_SLASH,
288    ERR_REGISTER_ERROR
289} ;
290
291
292/*
293 * Capitalise un caractère
294 */
295unsigned char upper_case(char c)
296{
297    if((c >= 'a') && (c <= 'z'))
298        c &= 0xDF ;
299    return c ;
300}
301
302/*
303 * Capitalise une chaîne de caractères
304 */
305void upper_string(char *p)
306{
307    while(*p != '\0')
308    {
309        if((*p >= 'a') && (*p <= 'z'))
310            *p &= 0xDF ;
311        p++ ;
312    }
313}
314
315
316/***********************************************************************
317 *
318 * Analyse et copie d'une ligne du source pour scan/assemblage
319 *
320 ***********************************************************************/
321
322#define COLON_300 300
323#define COLON_40  40
324
325/* Stocke la ligne suivante
326 * - Les tabulations sont transformées en série d'espace
327 * - La validité des caractères accentués est vérifiée
328 * - La taille de la ligne est vérifiée
329 */
330int GetLine(void)
331{
332    int i ;
333    int space ;
334    int error = NO_ERROR ;
335    int size = 0 ;
336
337    run.source = source ;
338    line = linebuffer ;
339    *line = '\0' ;
340
341    while ((size < LINE_MAX_SIZE-1)
342        && (*source != 0x00)
343        && (*source != 0x0A)
344        && (*source != 0x0D))
345    {
346        /* Caractère de tabulation */
347        if(*source == 0x09)
348        {
349            space = 7 - (size % 7) ;
350            for(i=0;i<space;i++)
351                *(line++) = 0x20 ;
352            size += space ;
353        }
354        else
355        /* Caractères accentués */
356        if ((unsigned char)*source > 0x7F)
357        {
358            i = 0 ;
359            while((i<16) && ((unsigned char)*source != acc_table[i])) i++ ;
360            if (i == 16)
361                error = ERR_ILLEGAL_CHAR ;
362            *(line++) = *source ;
363            size++ ;
364        }
365        else
366        /* Caractères de commande */
367        if ((unsigned char)*source < 0x20)
368            error = ERR_ILLEGAL_CHAR ;
369        else {
370            *(line++) = *source ;
371            size++ ; }
372        source++ ;
373    }
374
375    /* Clôt la ligne */
376    *(line++) = '\0' ;
377
378    /* Notifie le dépassement */
379    if(size > scan.limit)
380        error = ERR_LINE_TOO_LONG ;
381
382    /* Va jusqu'au bout de la ligne */
383    while ((*source != 0x00)
384        && (*source != 0x0A)
385        && (*source != 0x0D)) {
386           size++ ;
387           source++ ; }
388    switch(*source)
389    {
390        case 0x0A : if (*(source+1) == 0x0D) source++ ; break ;
391        case 0x0D : if (*(source+1) == 0x0A) source++ ; break ;
392    }
393    source++ ;
394
395    /* Elimine les caractères inutiles de fin de ligne */
396    while (((unsigned char)*(--line) <= 0x20)
397        && (size > 0)) {
398        *(line) = 0x00 ;
399        size-- ; }
400
401    /* Initialise les paramètres de lignes */
402    run.line++ ;
403    line = linebuffer ;
404
405    return error ;
406}
407
408
409/***********************************************************************
410 *
411 * Traitement des erreurs
412 *
413 ***********************************************************************/
414
415/* La liste err_table est dans l'ordre pour l'affichage par code d'erreur */
416#define ETSTRINGSIZE 24
417const struct {
418    char string[ETSTRINGSIZE] ; /* Message de l'erreur */
419    int code ;                  /* Code de l'erreur */
420  } err_table[] = {
421  /* Erreurs de scan prioritaires */
422    { "Missing (main)"          , ERR_MISSING_MAIN            },
423    { "Duplicate (main)"        , ERR_DUPLICATE_MAIN          },
424    { "Duplicate Name"          , ERR_DUPLICATE_NAME          },
425    { "Line Too Long"           , ERR_LINE_TOO_LONG           },
426    { "Illegal Char"            , ERR_ILLEGAL_CHAR            },
427    { "Wrong Mark"              , ERR_WRONG_MARK              },
428  /* Erreurs d'assemblage prioritaires (PASS1) */
429    { "File Not Found"          , ERR_FILE_NOT_FOUND          },
430    { "I/O Error"               , ERR_IO_ERROR                },
431    { "Missing Endm"            , ERR_MISSING_ENDM            },
432    { "Bad File Format"         , ERR_BAD_FILE_FORMAT         },
433    { "Bad File Name"           , ERR_BAD_FILE_NAME           },
434    { "Include Out Of Range"    , ERR_INCLUDE_OUT_OF_RANGE    },
435  /* Erreurs d'optimisation */
436    { "0 bit"                   , ERR_0_BIT                   },
437    { "5 bits"                  , ERR_5_BITS                  },
438    { "8 bits"                  , ERR_8_BITS                  },
439    { "Lone Symbol"             , ERR_LONE_SYMBOL             },
440    { "Force To DP"             , ERR_FORCE_TO_DP             },
441  /* Erreurs courantes */
442    { "Expression Error"        , ERR_EXPRESSION_ERROR        },
443    { "Branch Out Of Range"     , ERR_BRANCH_OUT_OF_RANGE     },
444    { "Bad Operand"             , ERR_BAD_OPERAND             },
445    { "Bad Label"               , ERR_BAD_LABEL               },
446    { "Bad Opcode"              , ERR_BAD_OPCODE              },
447    { "Missing Operand"         , ERR_MISSING_OPERAND         },
448    { "Multiply Defined Symbol" , ERR_MULTIPLY_DEFINED_SYMBOL },
449    { "Operand Out Of Range"    , ERR_OPERAND_OUT_OF_RANGE    },
450    { "Symbol Error"            , ERR_SYMBOL_ERROR            },
451    { "DP Error"                , ERR_DP_ERROR                },
452    { "Division By Zero"        , ERR_DIVISION_BY_ZERO        },
453  /* Erreur de condition */
454    { "If Out Of Range"         , ERR_IF_OUT_OF_RANGE         },
455    { "Missing If"              , ERR_MISSING_IF              },
456    { "Missing Endc"            , ERR_MISSING_ENDC            },
457    { "Bad Else"                , ERR_BAD_ELSE                },
458  /* Erreur de macro */
459    { "Illegal Include"         , ERR_ILLEGAL_INCLUDE         },
460    { "Bad Macro Name"          , ERR_BAD_MACRO_NAME          },
461    { "Macro Error"             , ERR_MACRO_ERROR             },
462    { "Macro Into If Range"     , ERR_MACRO_INTO_IF_RANGE     },
463    { "Macro Out Of Range"      , ERR_MACRO_OUT_OF_RANGE      },
464  /* Erreur peu courantes */
465    { "Bad Param"               , ERR_BAD_PARAM               },
466    { "Check Error"             , ERR_CHECK_ERROR             },
467    { "Embedded Macro"          , ERR_EMBEDDED_MACRO          },
468    { "Missing Information"     , ERR_MISSING_INFORMATION     },
469    { "Missing Label"           , ERR_MISSING_LABEL           },
470    { "Illegal Label"           , ERR_ILLEGAL_LABEL           },
471    { "Label Name Too Long"     , ERR_LABEL_NAME_TOO_LONG     },
472    { "Illegal Operand"         , ERR_ILLEGAL_OPERAND         },
473    { "Operand Is Macro"        , ERR_OPERAND_IS_MACRO        },
474    { "Register Error"          , ERR_REGISTER_ERROR          },
475    { "Binary Not Linear"       , ERR_BINARY_NOT_LINEAR       },
476    { "DP Error"                , ERR_DP_ERROR                },
477    { "Endm Without Macro"      , ERR_ENDM_WITHOUT_MACRO      },
478    { "Undefined Macro"         , ERR_UNDEFINED_MACRO         },
479    { "Missing Slash"           , ERR_MISSING_SLASH           },
480    { "Missing End Statement"   , ERR_MISSING_END_STATEMENT   }
481} ;
482#define ETSIZE (int)sizeof(err_table)/(int)sizeof(err_table[0])
483
484struct ERRLIST {
485    struct ERRLIST *next ; /* Pointeur sur section suivante */
486    int error ;    /* Numéro de l'erreur */
487    int line ;     /* Numéro de la ligne */
488    char *source ; /* Ponteur sur la ligne du source */
489} ;
490
491struct ERRLIST *first_error ;
492
493/*
494 * Initialise le chaînage des erreurs
495 *
496 * Le premier élément de la liste (pointé par first_error) ne contient
497 * qu'un pointeur 'next', et le numéro de sa ligne est à 0
498 * Ainsi, le pointeur first_error est invariable
499 */
500void InitErrorChain(void)
501{
502    first_error = malloc(sizeof(struct ERRLIST)) ;
503    first_error->line = 0 ;
504    first_error->next = NULL ;
505}
506
507/*
508 * Libère la mémoire pour le chaînage des erreurs
509 */
510void FreeErrorChain(void)
511{
512    struct ERRLIST *current_error ;
513
514    while ((current_error = first_error))
515    {
516        first_error = first_error->next ;
517        free(current_error) ;
518    }
519}
520
521/*
522 * Limite la taille de la ligne à afficher
523 */
524void MakeLimitedLine(char *formatstring)
525{
526    int size = LINE_MAX_SIZE - (int)strlen(formatstring) ;
527    if (size > 0)
528        strncat(formatstring,linebuffer,LINE_MAX_SIZE - (int)strlen(formatstring)) ;
529    formatstring[LINE_MAX_SIZE] = '>' ;
530    formatstring[LINE_MAX_SIZE+1] = '>' ;
531    formatstring[LINE_MAX_SIZE+2] = '\0' ;
532}
533
534/*
535 * Affiche une erreur pour la liste de fin d'assemblage
536 */
537void PrintErrorListLine(struct ERRLIST *rlist)
538{
539    char formatstring[LINE_MAX_SIZE+3] ;
540    char fmt[10] ;
541
542    sprintf(fmt,"%%%ds %% 7d ",ETSTRINGSIZE) ;
543    sprintf(formatstring,fmt,
544                         err_table[rlist->error].string,
545                         rlist->line) ;
546    source = rlist->source ;
547    GetLine() ;
548    MakeLimitedLine(formatstring) ;
549    fprintf(fp_lst,"%s\n",formatstring) ;
550}
551
552/*
553 * Affiche/Enregistre les erreurs pour l'assemblage
554 */
555int PrintError(int code)
556{
557    int i ;
558    struct ERRLIST *current_error ;
559    struct ERRLIST *found_error ;
560    struct ERRLIST *new_error ;
561    char formatstring[LINE_MAX_SIZE+3] ;
562    char filestring[15] ;
563
564    if ((code != NO_ERROR)
565     && (code != ERR_ERROR))
566    {
567        /* Recherche la position de l'erreur */
568        i = 0 ;
569        while((i<ETSIZE) && (code != err_table[i].code)) i++ ;
570        code = i ;
571
572        /* Filtrage d'affichage
573         * L'erreur doit être affichée à tous les coups ou seulement au
574         * pass 2
575         */
576        if ((run.pass == SCANPASS)
577         || (err_table[code].code < ____BREAK_ERROR)
578        || ((err_table[code].code > ____BREAK_ERROR) && (run.pass == PASS2)))
579        {
580            /* Affiche/Enregistre l'erreur */
581            filestring[0] = '\0' ;
582            if ((first_includ != NULL)
583             && (first_includ->count != 0))
584                sprintf(filestring,"%d:%s",
585                                   first_includ->drive,
586                                   first_includ->name) ;
587            sprintf(formatstring,"(%d)%s %s",
588                                 run.line,
589                                 filestring,
590                                 err_table[code].string) ;
591            fprintf(fp_lst,"%s\n",formatstring) ;
592            printf("%s\n",formatstring) ;
593
594            /* Affiche éventuellement la ligne du source */
595            sprintf(formatstring, "% 7d ", run.line) ;
596            MakeLimitedLine(formatstring) ;
597            if (err_table[code].code < ____NO_LINE_ERROR)
598                fprintf(fp_lst,"%s\n",formatstring) ;
599            if (run.opt[OPT_WL] == FALSE)
600                printf("%s\n",formatstring) ;
601
602            /* Collecte les erreurs pour fin d'assemblage
603               Le programme en profite pour ranger les erreurs dans
604               l'ordre croissant des numéros de lignes */
605            current_error = first_error ;
606            do {
607               found_error   = current_error ;
608               current_error = current_error->next ;
609            } while((current_error != NULL)
610                 && (current_error->line <= run.line)) ;
611            new_error = malloc(sizeof(struct ERRLIST)) ;
612            found_error->next = new_error ;
613            new_error->next   = current_error ;
614            new_error->error  = code ;
615            new_error->line   = run.line ;
616            new_error->source = run.source ;
617        }
618        code = ERR_ERROR ;
619    }
620    return code ;
621}
622
623enum{
624    INITIAL_ORDER,
625    ERROR_ORDER,
626    TYPE_ORDER,
627    TIME_ORDER
628} ;
629
630/*
631 * Enregistre les erreurs de fin d'assemblage
632 */
633void PrintErrorList(void)
634{
635    int i = 0 ;
636    struct ERRLIST *current_error ;
637
638    current_error = first_error ;
639    while((current_error = current_error->next) != NULL)
640        i++ ;
641    printf("\n%06d Total Errors\n",i) ;
642    fprintf(fp_lst, "\n%06d Total Errors\n",i) ;
643
644    if (i != 0)
645    {
646        current_error = first_error ;
647        switch(scan.err_order)
648        {
649            case INITIAL_ORDER :
650                current_error = first_error ;
651                while((current_error = current_error->next) != NULL)
652                    PrintErrorListLine(current_error) ;
653                break ;
654            case ERROR_ORDER :
655                for(i=0;i<ETSIZE;i++)
656                {
657                    current_error = first_error ;
658                    while((current_error = current_error->next) != NULL)
659                        if (current_error->error == i)
660                            PrintErrorListLine(current_error) ;
661                }
662                break ;
663        }
664    }
665}
666
667
668/***********************************************************************
669 *
670 * Lecture d'un argument
671 *
672 ***********************************************************************/
673
674/*
675 * Teste si caractère alphabétique
676 */
677int is_alpha(unsigned char c)
678{
679    switch(scan.soft)
680    {
681        case SOFT_ASSEMBLER :
682            return ((upper_case(c) >= 'A') && (upper_case(c) <= 'Z')) ? TRUE : FALSE ;
683            break ;
684        default :
685            return (((upper_case(c) >= 'A') && (upper_case(c) <= 'Z'))
686                  || (c == '_')) ? TRUE : FALSE ;
687            break ;
688    }
689    return FALSE ;
690}
691
692/*
693 * Teste si caractère numérique
694 */
695int is_numeric(unsigned char c)
696{
697    return ((c >= '0') && (c <= '9')) ? TRUE : FALSE ;
698}
699
700/* Les valeurs de registres sont dans l'ordre pour TFR/EXG */
701enum {
702    REG_D = 0x00,
703    REG_X,
704    REG_Y,
705    REG_U,
706    REG_S,
707    REG_PC,
708    REG_A = 0x08,
709    REG_B,
710    REG_CC,
711    REG_DP,
712    REG_PCR = 0x0F,
713    NUMERIC_CHAR,
714    ALPHA_CHAR,
715    SIGN_CHAR
716} ;
717
718/* Le bit ISREG set à déterminer s'il s'agit d'un registre hors PCR */
719enum {
720    END_CHAR,
721    ISREG = 0x8000,
722    REGS_PCR = 0x0004,
723    REGS_CCDPPC = 0x8005,
724    REGS_ABD,
725    REGS_XYUS
726} ;
727
728int ScanLine(void)
729{
730    int i ;
731    char *p ;
732    char regbuf[4] ;
733   
734    const struct {
735         char name[4] ; /* Nom du registre */
736         int code ;     /* Code du registre */
737         int group ;    /* Code du groupe du registre */
738      } Regs_T[11] = {
739        {   "A", REG_A  , REGS_ABD    },
740        {   "B", REG_B  , REGS_ABD    },
741        {   "D", REG_D  , REGS_ABD    },
742        {   "X", REG_X  , REGS_XYUS   },
743        {   "Y", REG_Y  , REGS_XYUS   },
744        {   "U", REG_U  , REGS_XYUS   },
745        {   "S", REG_S  , REGS_XYUS   },
746        {  "CC", REG_CC , REGS_CCDPPC },
747        {  "DP", REG_DP , REGS_CCDPPC },
748        {  "PC", REG_PC , REGS_CCDPPC },
749        { "PCR", REG_PCR, REGS_PCR    }
750    } ;
751#define RTSIZE (int)sizeof(Regs_T)/(int)sizeof(Regs_T[0])
752
753    *arg = '\0' ;
754    if (*line <= ' ') return END_CHAR ;
755
756    /* Capture d'au moins un caractère jusqu'à fin élément */
757    p = arg ;
758    i = 0 ;
759    if ((is_alpha(*line) == TRUE) || (is_numeric(*line) == TRUE))
760    {
761        while (((is_alpha(*line) == TRUE) || (is_numeric(*line) == TRUE)) && (i < 41))
762        {
763            *(p++) = *(line++) ;
764            i++ ;
765        }
766        while ((is_alpha(*line) == TRUE) || (is_numeric(*line) == TRUE))
767            line++ ;
768    }
769    else *(p++) = *(line++) ;
770
771    *p = '\0' ;
772
773    /* Si alphabétique */
774    if (is_alpha(*arg) == TRUE)
775    {
776        if ((int)strlen(arg) < 4)
777        {
778            regbuf[0] = '\0' ;
779            strcat(regbuf,arg) ;
780            upper_string(regbuf) ;
781            for(i=0;i<RTSIZE;i++)
782                if (!strcmp(regbuf,Regs_T[i].name)) {
783                    run.regcode = Regs_T[i].code ;
784                    return (Regs_T[i].group) ; }
785        }
786        return ALPHA_CHAR ;
787    }
788
789    /* Si numérique */
790    if (is_numeric(*arg) == TRUE) return NUMERIC_CHAR ;
791
792    /* Sinon, signe */
793    return SIGN_CHAR ;
794}
795
796
797/***********************************************************************
798 *
799 * Enregistrement de la ligne de code dans le listing
800 *
801 ***********************************************************************/
802
803#define CODE_STRING_SIZE 18
804
805enum{
806    PRINT_EMPTY,
807    PRINT_LINE,
808    PRINT_NO_CODE,
809    PRINT_BYTES,
810    PRINT_BYTES_ONLY,
811    PRINT_WORDS,
812    PRINT_WORDS_ONLY,
813    PRINT_PC,
814    PRINT_LIKE_END,
815    PRINT_LIKE_DP,
816    PRINT_ONE_FOR_ONE,
817    PRINT_TWO_FOR_TWO,
818    PRINT_TWO_FOR_THREE,
819    PRINT_THREE_FOR_THREE,
820    PRINT_THREE_FOR_FOUR
821} ;
822
823/*
824 * Enregistre la ligne de code
825 */
826int RecordLine(int drawmode)
827{
828    int i ;
829    int size ;
830    char opcodestring[5] ;
831    char bytestring[6] ;
832    char codestring[CODE_STRING_SIZE+2] ;
833    char cyclestring[6] ;
834    char formatstring[LINE_MAX_SIZE+3] ;
835    char fmt[20] ;
836
837    if (run.pass != PASS2) return NO_ERROR ;
838
839    if (run.locked) drawmode = PRINT_NO_CODE ;
840
841    /* Prépare la chaîne de l'opcode */
842    if (run.code[0])
843        sprintf(opcodestring,"%02X%02X",run.code[0],run.code[1]) ;
844    else
845        sprintf(opcodestring,"%02X  ",run.code[1]) ;
846
847    /* Prépare la chaîne des cycles */
848    cyclestring[0] = '\0' ;
849    if ((drawmode != PRINT_NO_CODE) && (info.cycle.count != -1))
850    {
851        if (info.cycle.plus != -1)
852            sprintf(cyclestring,"%d+%d",
853                                info.cycle.count,
854                                info.cycle.plus) ;
855        else
856            sprintf(cyclestring,"%d",info.cycle.count) ;
857    }
858
859    formatstring[0] = '\0' ;
860    codestring[0] = '\0' ;
861   
862    switch(drawmode)
863    {
864        case PRINT_EMPTY :
865        case PRINT_NO_CODE :
866            break ;
867        case PRINT_BYTES :
868        case PRINT_BYTES_ONLY :
869        case PRINT_WORDS :
870        case PRINT_WORDS_ONLY :
871            size = ((drawmode == PRINT_BYTES) || (drawmode == PRINT_BYTES_ONLY)) ? 1 : 2 ;
872            sprintf(codestring,"%04X ",run.pc) ;
873            for(i=0;i<run.size;i+=size)
874            {
875                if (i != 0) strcat(codestring," ") ;
876                if (size == 1)
877                    sprintf(bytestring,"%02X",run.code[i+1]) ;
878                else
879                    sprintf(bytestring,"%02X%02X",run.code[i+1],run.code[i+2]) ;
880                strcat(codestring,bytestring) ;
881            }
882            break ;
883        case PRINT_PC :
884            sprintf(codestring,"%04X",run.pc) ;
885            break ;
886        case PRINT_LIKE_END :
887            sprintf(codestring,"%10s%04X","",(unsigned short)eval.operand) ;
888            break ;
889        case PRINT_LIKE_DP :
890            sprintf(codestring,"%10s%02X","",run.dp) ;
891            break ;
892        case PRINT_ONE_FOR_ONE :
893            sprintf(codestring,"%04X %s",
894                run.pc,
895                opcodestring) ;
896            break ;
897        case PRINT_TWO_FOR_TWO :
898            sprintf(codestring,"%04X %s %02X",
899                run.pc,
900                opcodestring,
901                run.code[2]) ;
902            break ;
903        case PRINT_TWO_FOR_THREE :
904            sprintf(codestring,"%04X %s %02X%02X",
905                run.pc,
906                opcodestring,
907                run.code[2],
908                run.code[3]) ;
909            break ;
910        case PRINT_THREE_FOR_THREE :
911            sprintf(codestring,"%04X %s %02X %02X",
912                run.pc,
913                opcodestring,
914                run.code[2],
915                run.code[3]) ;
916            break ;
917        case PRINT_THREE_FOR_FOUR :
918            sprintf(codestring,"%04X %s %02X %02X%02X",
919                run.pc,
920                opcodestring,
921                run.code[2],
922                run.code[3],
923                run.code[4]) ;
924            break ;
925    }
926   
927    switch(drawmode)
928    {
929        case PRINT_EMPTY :
930            sprintf(formatstring,"% 7d",run.line) ;
931            break ;
932        case PRINT_BYTES_ONLY :
933        case PRINT_WORDS_ONLY :
934            sprintf(formatstring,"%14s %s","",codestring) ;
935            break ;
936        default :
937            sprintf(fmt,"%% 7d  %%-5s %%-%ds ",CODE_STRING_SIZE) ;
938            sprintf(formatstring,fmt,run.line,cyclestring,codestring) ;
939            MakeLimitedLine(formatstring) ;
940            break ;
941    }
942
943    fprintf(fp_lst,"%s\n",formatstring) ;
944
945    /* Affiche la ligne de code dans la fenêtre si WL */
946    if (run.opt[OPT_WL] == TRUE)
947        printf("%s\n",formatstring) ;
948
949    return NO_ERROR ;
950}
951
952
953/***********************************************************************
954 *
955 * Opérations disque pour le fichier binaire
956 *
957 ***********************************************************************/
958
959FILE *fp_bin ;
960
961enum{
962    BIN_FILE,
963    LINEAR_FILE,
964    HYBRID_FILE,
965    DATA_FILE
966} ;
967
968struct {
969    char flag ; /* Flag on/off binaire */
970    size_t size ; /* Taille du hunk */
971    size_t addr ; /* Adresse du hunk */
972    char *data;   /* Buffer de hunk */
973    int type ; /* Type de fichier : BIN_FILE/LINEAR_FILE/DATA_FILE */
974    long int pos ; /* Position du header précédent */
975} bin ;
976
977/*
978 * Sauve le header de fichier binaire
979 */
980void SaveBinHeader(char flag, size_t size, size_t addr)
981{
982    fputc (flag, fp_bin) ;
983    fputc (size >> 8, fp_bin) ;
984    fputc (size, fp_bin) ;
985    fputc (addr >> 8, fp_bin) ;
986    fputc (addr, fp_bin) ;
987}
988
989/*
990 * Sauve éventuellement le bloc courant
991 */
992void SaveBinBlock(void)
993{
994    if (bin.size != 0)
995    {
996        switch (bin.type)
997        {
998            case DATA_FILE :
999                if ((size_t)run.pc != (bin.addr + bin.size))
1000                    PrintError (ERR_BINARY_NOT_LINEAR) ;
1001                break;
1002
1003            case LINEAR_FILE :
1004              /*                if (bin.size > 0xFFFF) */
1005                if ((size_t)run.pc != (bin.addr + bin.size))
1006                    PrintError (ERR_BINARY_NOT_LINEAR) ;
1007                SaveBinHeader (bin.flag, bin.size, bin.addr) ;
1008                break;
1009
1010            default :
1011                SaveBinHeader (bin.flag, bin.size, bin.addr) ;
1012                break;
1013        }
1014        fwrite (bin.data, sizeof(char), bin.size, fp_bin) ;
1015    }
1016}
1017
1018
1019/*
1020 * Sauve une donnée binaire
1021 */
1022void SaveBinChar(unsigned char c)
1023{
1024    if ((run.pass == PASS2)
1025     && (run.locked == UNLOCKED)
1026     && (run.opt[OPT_NO] == FALSE))
1027    {
1028        if (((size_t)run.pc != (bin.addr + bin.size))
1029         || ((bin.type == BIN_FILE) && (bin.size == 0x0080))
1030         || (bin.size == 0xffff)
1031         || (bin.size == 0x0000))
1032        {
1033            /* Sauve éventuellement le bloc courant */
1034            SaveBinBlock() ;
1035
1036            /* Initialise le bloc suivant */
1037            bin.flag = 0x00 ;
1038            bin.size = 0x0000 ;
1039            bin.addr = run.pc ;
1040        }
1041        bin.data[bin.size++] = c ;
1042    }
1043    run.pc++ ;
1044    info.size++ ;
1045    check[1][1]++ ;
1046}
1047
1048/*
1049 * Ferme le fichier binaire
1050 */
1051void CloseBin(void)
1052{
1053    /* Sauve éventuellement le bloc courant */
1054    SaveBinBlock() ;
1055
1056    /* Sauve éventuellement le bloc de clôture */
1057    if (bin.type != DATA_FILE)
1058        SaveBinHeader((char)0xFF,0x00,run.exec) ;
1059    if (bin.data != NULL)
1060    {
1061        free (bin.data);
1062        bin.data = NULL;
1063    }
1064    fclose(fp_bin) ;
1065}
1066
1067/*
1068 * Ouvre le fichier binaire
1069 */
1070int OpenBin(char *name)
1071{
1072     bin.data = NULL;
1073     bin.size = 0x0000 ;
1074    if ((fp_bin = fopen(name,"wb")) == NULL)
1075        return PrintError(ERR_IO_ERROR) ;
1076    bin.data = (char *)malloc(65536);
1077
1078    return NO_ERROR ;
1079}
1080
1081
1082/***********************************************************************
1083 *
1084 * Traitement des symboles
1085 *
1086 ***********************************************************************/
1087
1088enum{
1089    ARG_VALUE,
1090    READ_VALUE,
1091    SET_VALUE,
1092    EQU_VALUE,
1093    LABEL_VALUE,
1094    MACRO_VALUE
1095} ;
1096
1097struct SYMBLIST {
1098    struct SYMBLIST *next ;
1099    char name[ARG_MAX_SIZE+2] ; /* Nom du symbole */
1100    unsigned short value ; /* Valeur du symbole */
1101    int error ; /* NO_ERROR/ERR_EXPRESSION_ERROR/ERR_MULTIPLY_DEFINED_SYMBOL */
1102    int type ;  /* SET_VALUE/EQU_VALUE/LABEL_VALUE/MACRO_VALUE */
1103    int time ;  /* Compteur d'apparition */
1104    int pass ;  /* Numéro de pass de la dernière définition */
1105} ;
1106
1107struct SYMBLIST *first_symbol ;
1108
1109/*
1110 * Initialise le chaînage des symboles
1111 *
1112 * Le premier élément de la liste (pointé par first_symbol) ne contient
1113 * éventuellement qu'un pointeur 'next', et le premier caractère de son
1114 * nom est '\0'
1115 * Ainsi, le pointeur first_symbol est invariable
1116 */
1117void InitSymbolChain(void)
1118{
1119    first_symbol = malloc(sizeof(struct SYMBLIST)) ;
1120    first_symbol->next = NULL ;
1121    first_symbol->name[0] = '\0' ;
1122}
1123
1124/*
1125 * Libère la mémoire pour le chaînage des symboles
1126 */
1127void FreeSymbolChain(void)
1128{
1129    struct SYMBLIST *current_symbol ;
1130    while ((current_symbol = first_symbol))
1131    {
1132        first_symbol = first_symbol->next ;
1133        free(current_symbol) ;
1134    }
1135}
1136
1137/* Compare deux noms de symboles
1138 * Le programme renvoie 5 valeurs :
1139 * -2 = le 1er nom est inférieur (majuscule != minuscule)
1140 * -1 = le 1er nom est inférieur (majuscule = minuscule)
1141 *  0 = les deux noms sont égaux
1142 *  1 = le 1er nom est supérieur (majuscule = minuscule)
1143 *  2 = le 1er nom est supérieur (majuscule != minuscule)
1144 */
1145int CompareSymbolNames(char *string1, char *string2)
1146{
1147    int i = 0, j = 0 ;
1148
1149    while((*(string1+i) != '\0')
1150       && (*(string2+i) != '\0')
1151       && (*(string1+i) == *(string2+i)))
1152        i++ ;
1153
1154    j = i ;
1155    while((*(string1+j) != '\0')
1156       && (*(string2+j) != '\0')
1157       && (upper_case(*(string1+j)) == upper_case(*(string2+j))))
1158        j++ ;
1159
1160    if (upper_case(*(string1+j)) < upper_case(*(string2+j))) return -1 ;
1161    if (upper_case(*(string1+j)) > upper_case(*(string2+j))) return 1 ;
1162    if (*(string1+i) < *(string2+i)) return -2 ;
1163    if (*(string1+i) > *(string2+i)) return 2 ;
1164    return 0 ;
1165}
1166
1167/*
1168 * - Ajoute éventuellement un symbole à la liste
1169 * - Met éventuellement le symbole à jour
1170 * - Lit le symbole
1171 */
1172int DoSymbol(char *name, unsigned short value, int type)
1173{
1174    int match = 0 ;
1175    struct SYMBLIST *prev_symbol   = NULL ;
1176    struct SYMBLIST *insert_symbol = NULL ;
1177    struct SYMBLIST *found_symbol  = NULL ;
1178    struct SYMBLIST *new_symbol    = NULL ;
1179
1180    /* Recherche le symbole dans la liste
1181     * Le programme en profite pour ranger les symboles dans l'ordre
1182     * alphabétique sans distinction entre majuscule et minuscule */
1183    insert_symbol = NULL ;
1184    found_symbol = first_symbol ;
1185    do {
1186        if (insert_symbol == NULL)
1187            prev_symbol = found_symbol ;
1188        if ((found_symbol = found_symbol->next) != NULL)
1189        {
1190            match = CompareSymbolNames(name,found_symbol->name) ;
1191            if ((match == -1) || (match == 0))
1192                insert_symbol = found_symbol ;
1193        }
1194    } while((found_symbol != NULL) && (match > 0)) ;
1195
1196    /* Si trouvé */
1197    if ((found_symbol != NULL) && (match == 0))
1198    {
1199        /* Actualise le pass si argument de commande */
1200        if (found_symbol->type == ARG_VALUE)
1201            found_symbol->pass = run.pass ;
1202
1203        if (type == READ_VALUE)
1204        {
1205            eval.type = (found_symbol->type == ARG_VALUE) ? EQU_VALUE : found_symbol->type ;
1206            eval.operand = found_symbol->value ;
1207            if (found_symbol->pass < run.pass)
1208                eval.pass = found_symbol->pass ;
1209            switch(run.pass)
1210            {
1211                case PASS1 :
1212                    found_symbol->time++ ;
1213                    break ;
1214                case PASS2 :
1215                    if ((found_symbol->time == 0)
1216                      && (run.opt[OPT_OP] == TRUE))
1217                        PrintError(ERR_LONE_SYMBOL) ;
1218                    if (found_symbol->error != NO_ERROR)
1219                        return PrintError(found_symbol->error) ;
1220                    break ;
1221            }
1222        }
1223        else
1224        {
1225            switch(run.pass)
1226            {
1227                case PASS1 :
1228                    /* Mise à jour si symbole non défini */
1229                    if ((found_symbol->pass) == MACROPASS)
1230                    {
1231                        found_symbol->pass  = PASS1 ;
1232                        found_symbol->type  = type ;
1233                        found_symbol->error = NO_ERROR ;
1234                        found_symbol->value = value ;
1235                    }
1236                    /* Si symboles de même valeur et de même nature ou SET,
1237                     * mise à jour de la valeur, sinon répertorie une erreur */
1238                    if (((found_symbol->type == SET_VALUE)
1239                      || (found_symbol->value == value))
1240                     && (found_symbol->type == type))
1241                        found_symbol->value = value ;
1242                    else
1243                        found_symbol->error = ERR_MULTIPLY_DEFINED_SYMBOL ;
1244                    break ;
1245                case PASS2 :
1246                    /* Mise à jour du pass */
1247                    if ((found_symbol->pass) == PASS1)
1248                        found_symbol->pass = PASS2 ;
1249                    /* Mise à jour si SET */
1250                    if (found_symbol->type == SET_VALUE)
1251                        found_symbol->value = value ;
1252                    /* Affiche éventuellement l'erreur */
1253                    if (found_symbol->error != NO_ERROR)
1254                        return PrintError(found_symbol->error) ;
1255                    break ;
1256            }
1257        }
1258    }
1259
1260    /* Si pas trouvé */
1261    else
1262    {
1263        if ((run.pass == PASS1)
1264         || (type == ARG_VALUE))
1265        {
1266            /* Positionne l'enregistrement dans la liste */
1267            new_symbol = malloc(sizeof(struct SYMBLIST)) ;
1268            if (insert_symbol == NULL)
1269                insert_symbol = prev_symbol ;
1270            else
1271            if (CompareSymbolNames(name,insert_symbol->name) < 0)
1272                insert_symbol = prev_symbol ;
1273            /* Enregistre le symbole */
1274            new_symbol->next = insert_symbol->next ;
1275            insert_symbol->next = new_symbol ;
1276            new_symbol->name[0] = '\0' ;
1277            strcat(new_symbol->name,name) ;
1278            new_symbol->value = value ;
1279            new_symbol->error = NO_ERROR ;
1280            new_symbol->type = type ;
1281            new_symbol->time = 0 ;
1282            new_symbol->pass = PASS1 ;
1283            if (type == READ_VALUE)
1284            {           
1285                new_symbol->type = EQU_VALUE ;
1286                new_symbol->pass = MACROPASS ;
1287                new_symbol->time++ ;
1288                new_symbol->error = ERR_EXPRESSION_ERROR ;
1289            }
1290            eval.pass = new_symbol->pass ;
1291            eval.type = EQU_VALUE ;
1292        }
1293        else
1294            return PrintError(ERR_SYMBOL_ERROR) ;
1295    }
1296
1297    return NO_ERROR ;
1298}
1299
1300/*
1301 * Enregistre une ligne de symbole de fin d'assemblage
1302 */
1303void PrintSymbolLine(struct SYMBLIST *slist)
1304{
1305    const struct {
1306        char string[9] ; /* Message de l'erreur */
1307        int type ;       /* Code de l'erreur */
1308      } ErrorTable[3] = {
1309        { "        ",  NO_ERROR                    },
1310        { "Unknown ",  ERR_EXPRESSION_ERROR        },
1311        { "Multiply",  ERR_MULTIPLY_DEFINED_SYMBOL }
1312    } ;
1313
1314    const struct {
1315        char string[6] ; /* Message du type de valeur */
1316        int type ;       /* Type de la valeur */
1317      } TypeTable[6] = {
1318        { "Arg  ",  ARG_VALUE   },
1319        { "Equ  ",  EQU_VALUE   },
1320        { "Set  ",  SET_VALUE   },
1321        { "Label",  LABEL_VALUE },
1322        { "Macro",  MACRO_VALUE }
1323    } ;
1324
1325    int error = 0 ;
1326    int type = 0 ;
1327    char errorstring[LINE_MAX_SIZE+2] ;
1328
1329    while(slist->error != ErrorTable[error].type) error++ ;
1330    while(slist->type != TypeTable[type].type) type++ ;
1331
1332    sprintf(errorstring, "% 6dx %s %s %04X %s",
1333                         slist->time,
1334                         ErrorTable[error].string,
1335                         TypeTable[type].string,
1336                         (unsigned short)slist->value,
1337                         slist->name) ;
1338    fprintf(fp_lst, "%s\n", errorstring) ;
1339    /* Affiche la ligne si WS */
1340    if (run.opt[OPT_WS] == TRUE)
1341        printf("%s\n", errorstring) ;
1342}
1343
1344
1345/*
1346 * Enregistre les symboles de fin d'assemblage
1347 */
1348void PrintSymbolList(void)
1349{
1350    int ErrorOrderList[] = {
1351        ERR_EXPRESSION_ERROR,
1352        ERR_MULTIPLY_DEFINED_SYMBOL,
1353        NO_ERROR
1354    } ;
1355    int TypeOrderList[]  = {
1356        ARG_VALUE,
1357        EQU_VALUE,
1358        SET_VALUE,
1359        LABEL_VALUE,
1360        MACRO_VALUE
1361    } ;
1362    int i = 0 ;
1363    int time = 0, nexttime = 0, prevtime = 0 ;
1364    struct SYMBLIST *current_symbol ;
1365
1366    /* Compte les symboles */
1367    current_symbol = first_symbol ;
1368    while((current_symbol = current_symbol->next) != NULL) i++ ;
1369
1370    /* Affiche si au moins un symbole */
1371    if (i)
1372    {
1373        printf("\n%06d Total Symbols\n",i) ;
1374        fprintf(fp_lst, "\n%06d Total Symbols\n",i) ;
1375
1376        switch(scan.symb_order)
1377        {
1378            case INITIAL_ORDER :
1379                current_symbol = first_symbol ;
1380                while((current_symbol = current_symbol->next) != NULL)
1381                    PrintSymbolLine(current_symbol) ;
1382                break ;
1383            case ERROR_ORDER :
1384                for(i=0;i<3;i++)
1385                {
1386                    current_symbol = first_symbol ;
1387                    while((current_symbol = current_symbol->next) != NULL)
1388                        if (current_symbol->error == ErrorOrderList[i])
1389                            PrintSymbolLine(current_symbol) ;
1390                }
1391                break ;
1392            case TYPE_ORDER :
1393                for(i=0;i<5;i++)
1394                {
1395                    current_symbol = first_symbol ;
1396                    while((current_symbol = current_symbol->next) != NULL)
1397                        if (current_symbol->type == TypeOrderList[i])
1398                            PrintSymbolLine(current_symbol) ;
1399                }
1400                break ;
1401            case TIME_ORDER :
1402                do
1403                {
1404                    prevtime = nexttime ;
1405                    nexttime = 0x7FFFFFFF ;
1406                    current_symbol = first_symbol ;
1407                    while((current_symbol = current_symbol->next) != NULL)
1408                    {
1409                        if ((current_symbol->time > time)
1410                         && (current_symbol->time < nexttime))
1411                            nexttime = current_symbol->time ;
1412                        if (current_symbol->time == time)
1413                            PrintSymbolLine(current_symbol) ;
1414                    }
1415                    time = nexttime ;
1416                } while(nexttime != prevtime) ;
1417                break ;
1418        }
1419        fprintf(fp_lst,"\n") ;
1420    }
1421}
1422
1423
1424/***********************************************************************
1425 *
1426 *  Evaluateur d'opérande
1427 *
1428 ***********************************************************************/
1429
1430struct EVALLIST {
1431    struct EVALLIST *prev ; /* Pointeur sur section précédente */
1432    char sign ;    /* Signe opérateur */
1433    int priority ; /* Priorité de l'opérateur */
1434    int operand ;  /* Valeur opérande */
1435} ;
1436
1437struct EVALLIST *current_eval = NULL ;
1438
1439/*
1440 * Ajoute un chaînage à l'évaluation
1441 *
1442 * Le premier élément de la liste
1443 * ne contient éventuellement qu'un
1444 * pointeur 'next', et sa priorité
1445 * de calcul est à 0
1446 */
1447void NewEvalChain(char sign, int priority, short operand)
1448{
1449    struct EVALLIST *prev_eval ;
1450    prev_eval = current_eval ;
1451    current_eval = malloc(sizeof(struct EVALLIST)) ;
1452    current_eval->prev     = prev_eval ;
1453    current_eval->sign     = sign ;
1454    current_eval->priority = priority ;
1455    current_eval->operand  = operand ;
1456}
1457
1458/*
1459 * Libère un maillon du chaînage d'évaluation
1460 */
1461void DeleteEvalChain(void)
1462{
1463    struct EVALLIST *prev_eval ;
1464    prev_eval = current_eval->prev ;
1465    free(current_eval) ;
1466    current_eval = prev_eval ;
1467}
1468
1469/*
1470 * Libère le chaînage d'évaluation
1471 */
1472int FreeEvalChain(int error)
1473{
1474    while(current_eval != NULL)
1475        DeleteEvalChain() ;
1476    return error ;
1477}
1478
1479/*
1480 * Lecture d'une valeur d'opérande
1481 */
1482int ReadValue(void)
1483{
1484    int i ;
1485    unsigned char c ;
1486    char base, prefix_base, suffix_base ;
1487    char *p ;
1488    char sign = 0 ;
1489
1490    eval.operand = 0 ;
1491
1492    do
1493    {
1494        do
1495        {
1496            sign = '\0' ;
1497            /* Cas spécial de '.NOT.' */
1498            if (*line == '.')
1499            {
1500                p = line++ ;
1501                i = ScanLine() ;
1502                upper_string(arg) ;
1503                if ((i == ALPHA_CHAR)
1504                 && (!strcmp("NOT",arg))
1505                 && (*line == '.'))
1506                {
1507                    if (scan.soft != SOFT_ASSEMBLER)
1508                        return PrintError(ERR_EXPRESSION_ERROR) ;
1509                    line++ ;
1510                    sign = ':' ;
1511                }
1512                else line = p ;
1513            }
1514            else
1515
1516            /* Repérage des opérateurs de signe */
1517            if ((*line == '+')
1518             || (*line == '-')
1519             || (*line == ':'))
1520            {
1521                sign = *(line++) ;
1522                if ((sign == ':') && (scan.soft == SOFT_ASSEMBLER))
1523                    return PrintError(ERR_EXPRESSION_ERROR) ;
1524            }
1525            /* Enregistre éventuellement le signe */
1526            if (sign)
1527                NewEvalChain(sign,0x80,0) ;
1528        } while(sign) ;
1529
1530        sign = 0 ;
1531        if (*line == '(')
1532        {
1533            /* Enregistre la parenthèse ouvrante */
1534            line++ ;
1535            NewEvalChain('\0',0,0) ;
1536            sign = '(' ;
1537        }
1538    } while(sign) ;
1539
1540    /* Récupération d'une valeur numérique :
1541     *                 (0-9, $, %, @ ou &)nombre(U, Q, O, T ou H)
1542     * Les bases préfixées et suffixées peuvent être déterminées
1543     * toutes deux, mais il y a erreur si elles ne correspondent
1544     * pas.
1545     */
1546   
1547    if ((is_numeric(*line) == TRUE)
1548      || (*line == '&')
1549      || (*line == '@')
1550      || (*line == '%')
1551      || (*line == '$'))
1552    {
1553       prefix_base = 0 ;
1554       if (ScanLine() == SIGN_CHAR)
1555       {
1556           switch(*arg)
1557           {
1558               case '%': prefix_base =  2 ; break ;
1559               case '@': prefix_base =  8 ; break ;
1560               case '&': prefix_base = 10 ; break ;
1561               case '$': prefix_base = 16 ; break ;
1562           }
1563           ScanLine() ;
1564       }
1565       suffix_base = 0 ;
1566       switch (upper_case(*(arg + (int)strlen(arg) - 1)))
1567       {
1568           case 'U': suffix_base = 2  ; break ;
1569           case 'Q':
1570           case 'O': suffix_base = 8  ; break ;
1571           case 'T': suffix_base = 10 ; break ;
1572           case 'H': suffix_base = 16 ; break ;
1573       }
1574
1575       /* Le rapport préfixe/suffixe est valide si au
1576        * moins l'un des deux est indéfini ou s'ils
1577        * sont égaux */
1578       if ((prefix_base != 0)
1579        && (suffix_base != 0)
1580        && (suffix_base != prefix_base))
1581           return PrintError(ERR_EXPRESSION_ERROR) ;
1582       /* Base 10 si ni préfixe ni suffixe définis */
1583       if ((base = (prefix_base | suffix_base)) == 0) base = 10 ;
1584       /* Rejette le binaire pour ASSEMBLER */
1585       /* Erreur si pas d'opérande */
1586       if (((base == 2) && (scan.soft == SOFT_ASSEMBLER))
1587        || (((int)strlen(arg)-((suffix_base != 0) ? 1 : 0)) == 0))
1588           return PrintError(ERR_EXPRESSION_ERROR) ;
1589
1590       for(i=0;i<(int)strlen(arg)-((suffix_base != 0) ? 1 : 0);i++)
1591       {
1592           if ((arg[i] > '9') && (arg[i] < 'A'))
1593               return PrintError(ERR_EXPRESSION_ERROR) ;
1594           c = (arg[i] < 'A') ? arg[i] -'0' : upper_case(arg[i]) -'A' + 10 ;
1595           if (c >= base) return PrintError(ERR_EXPRESSION_ERROR) ;
1596           eval.operand = (eval.operand * base) + c ;
1597       }
1598    }
1599
1600    /* Récupération de la valeur du pointeur de programme
1601     *                 '.' ou '*' */
1602    else
1603    if ((*line == '.') || (*line == '*'))
1604    {
1605        eval.operand = run.pc ;
1606        line++ ;
1607    }
1608
1609    /* Récupération d'une valeur ASCII
1610     *                 '[caractère]['caractère]
1611     * Une apostrophe sèche donne 0x0D
1612     * Doublet de déclaration seulement pour MACROASSEMBLER
1613     */
1614    else
1615    if (*line == '\'')
1616    {
1617        eval.operand = 0 ;
1618        for(i=0;i<2;i++)
1619        {
1620            if (*line == '\'')
1621            {
1622                line++ ;
1623                c = *line ;
1624                if (((i == 1) && (scan.soft == SOFT_ASSEMBLER))
1625                 || (c > 0x7F))
1626                    return PrintError(ERR_EXPRESSION_ERROR) ;
1627                if ((c == 0x00) || (c == 0x20)) c = 0x0D ;
1628                else {
1629                    if (c == CHAR127) c = 0x20 ;
1630                    line++ ; }
1631                eval.operand = (eval.operand << 8) | c ;
1632            }
1633        }
1634    }
1635    else
1636
1637    /* Récupèration d'une valeur de symbole */
1638    if (is_alpha(*line) == TRUE)
1639    {
1640        ScanLine() ;
1641        if (scan.soft == SOFT_ASSEMBLER) upper_string(arg) ;
1642        if (DoSymbol (arg, 0, READ_VALUE) != NO_ERROR)
1643            return ERR_ERROR ;
1644        if (eval.type == MACRO_VALUE)
1645            return PrintError(ERR_OPERAND_IS_MACRO) ;
1646    }
1647
1648    /* Pas de récupération possible */
1649    else
1650        return PrintError(ERR_MISSING_OPERAND) ;
1651
1652    return NO_ERROR ;
1653}
1654
1655
1656/*
1657 * Lecture d'un signe opérateur
1658 */
1659
1660int ReadOperator(void)
1661{
1662    /* Pour NEQ, l'opérateur "|" est arbitraire, celui-ci n'existant
1663     * dans aucun des deux assembleurs sur Thomson
1664     * Il sert seulement à faciliter le repérage de l'opérateur
1665     * '.NOT.' est repéré mais rejeté
1666     */
1667    const struct {
1668        char string[4] ; /* Nom ASSEMBLER de l'opérateur */
1669        char sign ;      /* Signe de l'opérateur */
1670        int priority ;   /* Priorité de l'opérateur */
1671        int compatibility ; /* Compatibilté du signe avec ASSEMBLER */
1672      } AlphaOperator[12] = {
1673        { "   " , '<' , 5, TRUE  },
1674        { "EQU" , '=' , 1, TRUE  },
1675        { "DIV" , '/' , 5, TRUE  },
1676        { "AND" , '&' , 4, TRUE  },
1677        { "   " , '+' , 2, TRUE  },
1678        { "   " , '-' , 2, TRUE  },
1679        { "   " , '*' , 5, TRUE  },
1680        { "OR"  , '!' , 3, TRUE  },
1681        { "NEQ" , '|' , 1, FALSE },  /* Pas MACROASSEMBLER */
1682        { "NOT" , ':' , 0, FALSE },  /* Rejeté !!! */
1683        { "MOD" , '%' , 5, FALSE },
1684        { "XOR" , '^' , 3, FALSE }
1685    } ;
1686
1687    int i = 0 ;
1688
1689    if (ScanLine() != SIGN_CHAR)
1690        return PrintError(ERR_EXPRESSION_ERROR) ;
1691    if (*arg == '.')
1692    {
1693        if ((scan.soft != SOFT_ASSEMBLER)
1694         || (ScanLine() != ALPHA_CHAR))
1695            return PrintError(ERR_EXPRESSION_ERROR) ;
1696        upper_string(arg) ;
1697        i = 0 ;
1698        while ((i < 12) && (strcmp(AlphaOperator[i].string,arg))) i++ ;
1699        if ((i == 12) || (*line != '.'))
1700            return PrintError(ERR_EXPRESSION_ERROR) ;
1701        eval.sign = AlphaOperator[i].sign ;
1702        line++ ;
1703    }
1704    else
1705    {
1706        i = 0 ;
1707        while ((i < 12) && (*arg != AlphaOperator[i].sign)) i++ ;
1708        if ((i == 12)
1709         || (*arg == '|')
1710         || ((AlphaOperator[i].compatibility == FALSE)
1711          && (scan.soft == SOFT_ASSEMBLER)))
1712            return PrintError(ERR_EXPRESSION_ERROR) ;
1713        eval.sign = *arg ;
1714    }
1715
1716    /* Rejette 'NOT' */
1717    if (eval.sign == ':')
1718        return PrintError(ERR_EXPRESSION_ERROR) ;
1719
1720    eval.priority = AlphaOperator[i].priority ;
1721
1722    return NO_ERROR ;
1723}
1724
1725/*
1726 * Programme calculateur
1727 */
1728int CalculateEval(void)
1729{
1730    unsigned short n1 = current_eval->operand,
1731                   n2 = eval.operand ;
1732
1733    switch(current_eval->sign)
1734    {
1735        case '+' : n1 += n2 ; break ;
1736        case '-' : n1 -= n2 ; break ;
1737        case '&' : n1 &= n2 ; break ;
1738        case '!' : n1 |= n2 ; break ;
1739        case '^' : n1 ^= n2 ; break ;
1740        case '=' : n1 = (n1 == n2) ? 0xFFFF : 0x0000 ;
1741                   break ;
1742        case '|' : n1 = (n1 != n2) ? 0xFFFF : 0x0000 ;
1743                   break ;
1744        case '*' : n1 *= n2 ; break ;
1745        case '/' : if (n2 == 0)
1746                       return PrintError(ERR_DIVISION_BY_ZERO) ;
1747                   else n1 /= n2 ;
1748                   break ;
1749        case '%' : if (n2 == 0)
1750                       return PrintError(ERR_DIVISION_BY_ZERO) ;
1751                   else n1 %= n2 ;
1752                   break ;
1753        case '<' : if ((signed short)n2 >= 0) n1 <<= n2 ; else n1 >>= (signed short)(-n2) ;
1754                   break ;
1755    }
1756    eval.operand = n1 ;
1757    return NO_ERROR ;
1758}
1759
1760
1761
1762/*
1763 * Evaluation de l'opérande
1764 */
1765int Eval(void)
1766{
1767    struct EVALLIST *prev_eval = NULL ;
1768    int again = FALSE ;
1769
1770    eval.pass = run.pass ;
1771
1772    current_eval = malloc(sizeof(struct EVALLIST)) ;
1773    current_eval->prev     = NULL ;
1774    current_eval->sign     = '\0' ;
1775    current_eval->priority = 0 ;
1776    current_eval->operand  = 0 ;
1777
1778    do
1779    {
1780        /* Récupère l'argument d'opérande */
1781        if (ReadValue() == ERR_ERROR)
1782            return FreeEvalChain(ERR_ERROR) ;
1783
1784        do
1785        {
1786            again = FALSE ;
1787
1788            /* Applique les opérateurs de signe */
1789            while(current_eval->priority == 0x80)
1790            {
1791                switch(current_eval->sign)
1792                {
1793                    case '+' : break ;
1794                    case '-' : eval.operand = -eval.operand ; break ;
1795                    case ':' : eval.operand = ~eval.operand ; break ;
1796                }
1797                DeleteEvalChain() ;
1798            }
1799
1800            /* Exécute les parenthèses fermantes */
1801            if (*line == ')')
1802            {
1803               line++ ;
1804                /* Calcule le contenu des parenthèses*/
1805                while(current_eval->priority != 0)
1806                {
1807                    if (CalculateEval() != NO_ERROR)
1808                        return FreeEvalChain(ERR_ERROR) ;
1809                    eval.sign     = 0 ;
1810                    eval.priority = current_eval->priority ;
1811                    DeleteEvalChain() ;
1812                }
1813                if (current_eval->prev == NULL)
1814                    FreeEvalChain(PrintError(ERR_EXPRESSION_ERROR)) ;
1815                DeleteEvalChain() ;
1816                again = TRUE ;
1817            }
1818        } while(again == TRUE) ;
1819
1820        again = FALSE ;
1821        /* Récupère opérateur si pas fin d'opérande */
1822        if ((*line != '\0')
1823         && (*line != ' ')
1824         && (*line != CHAR127)
1825         && (*line != ',')
1826         && (*line != ']'))
1827        {
1828            /* Récupère l'opérateur */
1829            if (ReadOperator() == ERR_ERROR)
1830                return FreeEvalChain(ERR_ERROR) ;
1831            /* Effectue le calcul sur les priorités fortes */
1832            if ((current_eval->priority != 0)
1833             && (eval.priority <= current_eval->priority))
1834            {
1835                while(((prev_eval = current_eval->prev) != NULL)
1836                    && (current_eval->priority != 0)
1837                    && (eval.priority <= current_eval->priority))
1838                {
1839                    if (CalculateEval() != NO_ERROR)
1840                        return FreeEvalChain(ERR_ERROR) ;
1841                    DeleteEvalChain() ;
1842                }
1843            }
1844            NewEvalChain(eval.sign,eval.priority,eval.operand) ;
1845            again = TRUE ;
1846        }
1847    } while(again == TRUE) ;
1848
1849    /* Finit les calculs en fermant les sections */
1850    while(current_eval->prev != NULL)
1851    {
1852        /* Erreur si parenthèse ouverte */
1853        if (current_eval->priority == 0)
1854            return FreeEvalChain(PrintError(ERR_EXPRESSION_ERROR)) ;
1855        /* Effectue le calcul */
1856        if (CalculateEval() != NO_ERROR)
1857            return FreeEvalChain(ERR_ERROR) ;
1858        DeleteEvalChain() ;
1859    }
1860    return FreeEvalChain(NO_ERROR) ;
1861}
1862
1863
1864/***********************************************************************
1865 *
1866 * Assemblage des instructions
1867 *
1868 ***********************************************************************/
1869 
1870/*-------------------------------------------------------------------
1871 * Assemblage opérande pour tout type
1872 * Assemblage opérande pour tout type sauf immédiat
1873 * Assemblage opérande pour LEAx
1874 */
1875int Ass_AllType(int immediate, int lea)
1876{
1877    int extended_mode = FALSE ;
1878    int direct_mode   = FALSE ;
1879    int indirect_mode = FALSE ;
1880
1881    unsigned char c = 0 ;
1882    int regs ;
1883    int mode ;
1884    int recordtype = PRINT_NO_CODE ;
1885
1886    run.code[2] = 0x00 ;
1887    run.size = 2 ;
1888
1889    /* Adressage immédiat */
1890
1891    mode = 0 ;
1892    if (*line == '#')
1893    {
1894        info.cycle.count -= 2 ;
1895        line++ ;
1896        if (immediate == FALSE) return PrintError(ERR_EXPRESSION_ERROR) ;
1897        if(Eval() != NO_ERROR) return ERR_ERROR ;
1898        c = run.code[1] & 0x0F ;
1899        if (c == 0x03) mode = 16 ;
1900        else if ((c < 0x0C) && (c != 0x07)) mode = 8 ;
1901        else if ((c & 0x01) == 0) mode = 16 ;
1902        else return PrintError(ERR_BAD_OPERAND) ;
1903        switch(mode)
1904        {
1905            case 8 :
1906                run.size = 2 ;
1907                run.code[2] = eval.operand & 0xFF ;
1908                if ((eval.operand < -256) || (eval.operand > 255))
1909                    PrintError(ERR_OPERAND_OUT_OF_RANGE) ;
1910                return RecordLine(PRINT_TWO_FOR_TWO) ;
1911                break ;
1912            case 16 :
1913                run.size = 3 ;
1914                run.code[2] = eval.operand >> 8 ;
1915                run.code[3] = eval.operand & 0xFF ;
1916                return RecordLine(PRINT_TWO_FOR_THREE) ;
1917                break ;
1918           
1919            default :
1920                return PrintError(ERR_BAD_OPERAND) ;
1921                break ;
1922         }
1923    }
1924
1925    if (*line == '<') direct_mode = TRUE ;
1926    if (*line == '>') extended_mode = TRUE ;
1927    if ((direct_mode == TRUE) || (extended_mode == TRUE)) line++ ;
1928
1929    if (*line == '[')
1930    {
1931        indirect_mode = TRUE ;
1932        line++ ;
1933    }
1934
1935    if (run.code[1] & 0x80) run.code[1] |= 0x10 ;
1936
1937    /* Adressage indexé avec registre 8 bits   c,z */
1938
1939    if (((upper_case(*line) == 'A')
1940      || (upper_case(*line) == 'B')
1941      || (upper_case(*line) == 'D'))
1942     && (*(line+1) == ','))
1943    {
1944        run.size = 2 ;
1945        if(lea == FALSE) run.code[1] += (immediate == TRUE) ? 0x10 : 0x60 ;
1946
1947        if((direct_mode == TRUE) || (extended_mode == TRUE))
1948            return PrintError(ERR_BAD_OPERAND) ;
1949
1950        switch(upper_case(*line))
1951        {
1952            case 'A' : run.code[2] = 0x86 ; info.cycle.plus = 1 ; break ;
1953            case 'B' : run.code[2] = 0x85 ; info.cycle.plus = 1 ; break ;
1954            case 'D' : run.code[2] = 0x8B ; info.cycle.plus = 4 ; break ;
1955        }
1956        line += 2 ;
1957        if (ScanLine() != REGS_XYUS)
1958            return PrintError(ERR_BAD_OPERAND) ;
1959        run.code[2] |= (run.regcode - 1) << 5 ;
1960        recordtype = PRINT_TWO_FOR_TWO ;
1961    }
1962
1963    /* Adressage indexé sans offset  ,z  ,z+  ,z++  ,-z'  ,--z */
1964
1965    else
1966    if (*line == ',')
1967    {
1968        run.size = 2 ;
1969        if(lea == FALSE) run.code[1] += (immediate == TRUE) ? 0x10 : 0x60 ;
1970        line++ ;
1971
1972        if (*line == '-')
1973        {
1974            info.cycle.plus = 2 ;
1975            run.code[2] = 0x82 ;
1976            line++ ;
1977            if (*line == '-')
1978            {
1979                info.cycle.plus = 3 ;
1980                run.code[2] = 0x83 ;
1981                line++ ;
1982            }
1983            if (ScanLine() != REGS_XYUS)
1984                return PrintError(ERR_BAD_OPERAND) ;
1985        }
1986        else
1987        if (ScanLine() == REGS_XYUS)
1988        {
1989            info.cycle.plus = 0 ;
1990            run.code[2] = 0x84 ;
1991            if (*line == '+')
1992            {
1993                info.cycle.plus = 2 ;
1994                run.code[2] = 0x80 ;
1995                line++ ;
1996                if (*line == '+')
1997                {
1998                    info.cycle.plus = 3 ;
1999                    run.code[2] = 0x81 ;
2000                    line++ ;
2001                }
2002            }
2003        }
2004        else
2005            return PrintError(ERR_BAD_OPERAND) ;
2006
2007        run.size = 2 ;
2008        run.code[2] |= (run.regcode - 1) << 5 ;
2009        if ((((run.code[2] & 0x9F) == 0x82) || ((run.code[2] & 0x9F) == 0x80))
2010         && (indirect_mode == TRUE))
2011            return PrintError(ERR_BAD_OPERAND) ;
2012
2013        recordtype = PRINT_TWO_FOR_TWO ;
2014    }
2015
2016    /* Adressage indexé avec offset  $xx,z  $xx,PCR */
2017
2018    else
2019    {
2020        if (Eval() != NO_ERROR) return ERR_ERROR ;
2021
2022        if(*line == ',')
2023        {
2024            if (lea == FALSE) run.code[1] += (immediate == TRUE) ? 0x10 : 0x60 ;
2025            line++ ;
2026            regs = ScanLine() ;
2027
2028            /* Adressage indexé avec offset et PCR   $xx,PCR */
2029            if (regs == REGS_PCR)
2030            {
2031                eval.operand -= run.pc + 3 ;
2032                mode = ((eval.operand >= -128) && (eval.operand <= 127)) ? 8 : 16 ;
2033                if (eval.pass < run.pass) mode = 16 ;   /* 16 bits si non répertorié */
2034                if (extended_mode == TRUE) mode = 16 ;  /* 16 bits si étendu forcé */
2035                if (direct_mode == TRUE) mode = 8 ;     /* 8 bits si direct forcé */
2036                switch(mode)
2037                {
2038                    case 8 :
2039                        info.cycle.plus = 1 ;
2040                        run.size = 3 ;
2041                        run.code[2] = 0x8C ;
2042                        run.code[3] = eval.operand & 0xFF ;
2043                        if ((eval.operand < -128) || (eval.operand > 127))
2044                            PrintError(ERR_OPERAND_OUT_OF_RANGE) ;
2045                        recordtype = PRINT_THREE_FOR_THREE ;
2046                        break ;
2047                    case 16 :
2048                        eval.operand-- ;
2049                        info.cycle.plus = 5 ;
2050                        run.size = 4 ;
2051                        run.code[2] = 0x8D ;
2052                        run.code[3] = (eval.operand >> 8) & 0xFF ;
2053                        run.code[4] = eval.operand & 0xFF ;
2054                        if (((eval.operand + 1 >= -128) && (eval.operand <= 127))
2055                          && (run.opt[OPT_OP] == TRUE))
2056                            PrintError(ERR_8_BITS) ;
2057                        recordtype = PRINT_THREE_FOR_FOUR ;
2058                        break ;
2059                }
2060            }
2061
2062            /* Adressage indexé avec offset  $xx,z */
2063            else
2064            if (regs == REGS_XYUS)
2065            {
2066                mode = 16 ;
2067                if ((eval.operand >= -128) && (eval.operand <= 127)) mode = 8 ;
2068                if ((eval.operand >= -16)  && (eval.operand <= 15))  mode = 5 ;
2069                if (eval.pass < run.pass)  mode = 16 ;  /* 16 bits si non répertorié */
2070                if (extended_mode == TRUE) mode = 16 ;  /* 16 bits si étendu forcé */
2071                if (direct_mode == TRUE)   mode = 8 ;   /* 8 bits si direct forcé */
2072                if ((mode == 5) && (indirect_mode == TRUE)) mode = 8 ;
2073                switch(mode)
2074                {
2075                    case 5 :
2076                        info.cycle.plus = 1 ;
2077                        run.size = 2 ;
2078                        run.code[2] = 0x00 | (eval.operand & 0x1F) ;
2079                        recordtype = PRINT_TWO_FOR_TWO ;
2080                        break ;
2081                    case 8 :
2082                        info.cycle.plus = 1 ;
2083                        run.size = 3 ;
2084                        run.code[2] = 0x88 ;
2085                        run.code[3] = eval.operand & 0xFF ;
2086                        if ((eval.operand < -128) || (eval.operand > 127))
2087                            PrintError(ERR_OPERAND_OUT_OF_RANGE) ;
2088                        recordtype = PRINT_THREE_FOR_THREE ;
2089                        break ;
2090                    case 16 :
2091                        info.cycle.plus = 4 ;
2092                        run.size = 4 ;
2093                        run.code[2] = 0x89 ;
2094                        run.code[3] = (eval.operand >>  8) & 0xFF ;
2095                        run.code[4] = eval.operand & 0xFF ;
2096                        recordtype = PRINT_THREE_FOR_FOUR ;
2097                        break ;
2098                }
2099                if ((run.opt[OPT_OP] == TRUE))
2100                {
2101                    if ((eval.operand == 0)
2102                     && (mode > 0)
2103                     && (indirect_mode == FALSE))
2104                        PrintError(ERR_0_BIT) ;
2105                    else
2106                    if ((eval.operand >= -16)
2107                     && (eval.operand <= 15)
2108                     && (mode > 5)
2109                     && (indirect_mode == FALSE))
2110                        PrintError(ERR_5_BITS) ;
2111                    else
2112                    if ((eval.operand >= -128)
2113                     && (eval.operand <= 127)
2114                     && (mode > 8))
2115                        PrintError(ERR_8_BITS) ;
2116                }
2117                run.code[2] |= (run.regcode - 1) << 5 ;
2118            }
2119            else return PrintError(ERR_BAD_OPERAND) ;
2120        }
2121        else
2122        {
2123            /* Adressage direct et étendu */
2124            if (lea == TRUE)
2125                return PrintError(ERR_BAD_OPERAND) ;
2126
2127            mode = 16 ;
2128            if (((eval.operand >> 8) & 0xFF) == run.dp) mode = 8 ; /* 8 bits si MSB = DP */
2129            if (indirect_mode == TRUE) mode = 16 ;  /* 16 bits si mode indirect */
2130            if (eval.pass < run.pass)  mode = 16 ;  /* 16 bits si non répertorié */
2131            if (extended_mode == TRUE) mode = 16 ;  /* 16 bits si étendu forcé */
2132            if (direct_mode == TRUE)   mode = 8  ;  /* 8 bits si direct forcé */
2133            switch(mode)
2134            {
2135                case 8 :
2136                    run.size = 2 ;
2137                    run.code[2] = eval.operand & 0xFF ;
2138                    if (indirect_mode == TRUE)
2139                        return PrintError(ERR_BAD_OPERAND) ;
2140                    if (((eval.operand >> 8) & 0xFF) != run.dp)
2141                        PrintError(ERR_DP_ERROR) ;
2142                    recordtype = PRINT_TWO_FOR_TWO ;
2143                    break ;
2144                case 16 :
2145                    if (indirect_mode == FALSE)
2146                    {
2147                        info.cycle.count++ ;
2148                        run.size = 3 ;
2149                        run.code[1] |= (immediate == TRUE) ? 0x30 : 0x70 ;
2150                        run.code[2] = (eval.operand >> 8) & 0xFF ;
2151                        run.code[3] = eval.operand & 0xFF ;
2152                        if ((((eval.operand >> 8) & 0xFF) == run.dp)
2153                          && (run.opt[OPT_OP] == TRUE))
2154                            PrintError(ERR_FORCE_TO_DP) ;
2155                        recordtype = PRINT_TWO_FOR_THREE ;
2156                    } else {
2157                        run.size = 4 ;
2158                        if (lea == FALSE) run.code[1] += (immediate == TRUE) ? 0x10 : 0x60 ;
2159                        run.code[2] = 0x9F ;
2160                        run.code[3] = (eval.operand >> 8) & 0xFF ;
2161                        run.code[4] = eval.operand & 0xFF ;
2162                        recordtype = PRINT_THREE_FOR_FOUR ;
2163                    }
2164                    break ;
2165            }
2166        }
2167    }
2168
2169    /* Vérifie la présence d'un ']' pour le mode indirect */
2170    if (indirect_mode == TRUE)
2171    {
2172        info.cycle.plus += (info.cycle.plus == -1) ? 4 : 3 ;
2173        run.code[2] |= 0x10 ;
2174        if(*line != ']')
2175            return PrintError(ERR_BAD_OPERAND) ;
2176        line++ ;
2177    }
2178    return RecordLine(recordtype) ;
2179}
2180
2181/*
2182 * Assemblage opérande pour tout type
2183 */
2184int Ass_All (void)
2185{
2186    return Ass_AllType (TRUE, FALSE) ;
2187}
2188
2189/*
2190 * Assemblage opérande pour tout type sauf immédiat
2191 */
2192int Ass_NotImmed (void)
2193{
2194    return Ass_AllType (FALSE, FALSE) ;
2195}
2196
2197/*
2198 * Assemblage opérande pour LEAx
2199 */
2200int Ass_Lea (void)
2201{
2202    return Ass_AllType (FALSE, TRUE) ;
2203}
2204
2205/*-------------------------------------------------------------------
2206 * Assemblage opérande pour immédiat
2207 */
2208int Ass_Immediate(void)
2209{
2210    run.size = 2 ;
2211    if (*line != '#')
2212        return PrintError(ERR_BAD_OPERAND) ;
2213    line++ ;
2214    if (Eval()) return ERR_ERROR ;
2215    if ((eval.operand < -256) || (eval.operand > 255))
2216        PrintError(ERR_OPERAND_OUT_OF_RANGE) ;
2217    run.code[2] = eval.operand ;
2218    return RecordLine(PRINT_TWO_FOR_TWO) ;
2219}
2220
2221/*-------------------------------------------------------------------
2222 * Assemblage opérande pour TFR/EXG
2223 */
2224int Ass_Transfer(void)
2225{
2226    run.size = 2 ;
2227    /* Premier registre */
2228    if ((ScanLine() & ISREG) == 0)
2229        return PrintError(ERR_BAD_OPERAND) ;
2230    run.code[2] = run.regcode << 4 ;
2231    /* Passe la virgule */
2232    if (*line++ != ',')
2233        return PrintError(ERR_BAD_OPERAND) ;
2234    /* Deuxième registre */
2235    if ((ScanLine() & ISREG) == 0)
2236        return PrintError(ERR_BAD_OPERAND) ;
2237    run.code[2] |= run.regcode ;
2238    /* Vérifie si erreur de registre
2239     * Les bits 3 et 7 sont les bits de taille des registres
2240     * Par masquage, on doit donc obtenir ou 0x88 ou 0x00 */
2241    if (((run.code[2] & 0x88) != 0x00)
2242     && ((run.code[2] & 0x88) != 0x88))
2243        PrintError(ERR_REGISTER_ERROR) ;
2244    return RecordLine(PRINT_TWO_FOR_TWO) ;
2245}
2246
2247/*-------------------------------------------------------------------
2248 * Assemblage opérande pour PSHx/PULx
2249 */
2250int Ass_Stack(int exclude)
2251{
2252    unsigned char StackTable[10] = {
2253        0x06,   /* D  = 0x00 */
2254        0x10,   /* X  = 0x01 */
2255        0x20,   /* Y  = 0x02 */
2256        0x40,   /* U  = 0x03 */
2257        0x40,   /* S  = 0x04 */
2258        0x80,   /* PC = 0x05 */
2259        0x02,   /* A  = 0x08 */
2260        0x04,   /* B  = 0x09 */
2261        0x01,   /* CC = 0x0A */
2262        0x08    /* DP = 0x0B */
2263    } ;
2264
2265    int reg = 0;
2266
2267    info.cycle.plus = 0 ;
2268    run.code[2] = 0 ;
2269    run.size = 2 ;
2270    do
2271    {
2272        /* Erreur si pas registre */
2273        if ((ScanLine() & ISREG) == 0)
2274            return PrintError(ERR_BAD_OPERAND) ;
2275        /* Complète l'opérande */
2276        reg = (run.regcode > REG_PC) ? run.regcode - 2 : run.regcode ;
2277        if ((run.code[2] & StackTable[reg]) != 0)
2278            PrintError(ERR_REGISTER_ERROR) ;
2279        info.cycle.plus += (run.regcode > REG_PC) ? 1 : 2 ;
2280        run.code[2] |= StackTable[reg] ;
2281        /* Exclut U pour PULU/PSHU et S pour PULS/PSHS */
2282        if (run.regcode == exclude)
2283            return PrintError(ERR_BAD_OPERAND) ;
2284    } while (*(line++) == ',') ;
2285    line--;
2286    if (ScanLine() != END_CHAR)
2287        return PrintError(ERR_BAD_OPERAND) ;
2288    return RecordLine(PRINT_TWO_FOR_TWO) ;
2289}
2290
2291/*
2292 * Assemblage opérande pour PSHS/PULS
2293 */
2294int Ass_SStack(void)
2295{
2296    return Ass_Stack(REG_S) ;
2297}
2298
2299/*
2300 * Assemblage opérande pour PSHS/PULS
2301 */
2302int Ass_UStack(void)
2303{
2304    return Ass_Stack(REG_U) ;
2305}
2306
2307/*-------------------------------------------------------------------
2308 * Assemblage opérande pour inhérent
2309 */
2310int Ass_Inherent(void)
2311{
2312    run.size = 1 ;
2313    return RecordLine(PRINT_ONE_FOR_ONE) ;
2314}
2315
2316/*-------------------------------------------------------------------
2317 * Assemblage opérande pour branchements courts
2318 */
2319int Ass_ShortBr(void)
2320{
2321    if (Eval() != NO_ERROR) return ERR_ERROR ;
2322    run.size = 2 ;
2323    run.code[2] = 0xFE ;
2324    eval.operand -= run.pc + run.size ;
2325    if ((eval.operand < -128) || (eval.operand > 127))
2326        PrintError(ERR_BRANCH_OUT_OF_RANGE) ;
2327    else
2328        run.code[2] = eval.operand & 0xFF ;
2329    return RecordLine(PRINT_TWO_FOR_TWO) ;
2330}
2331
2332/*-------------------------------------------------------------------
2333 * Assemblage opérande pour branchements longs
2334 */
2335int Ass_LongBr(void)
2336{
2337    if (Eval() != NO_ERROR) return ERR_ERROR ;
2338    run.size = 3 ;
2339    run.code[2] = 0xFF ;
2340    run.code[3] = 0xFD ;
2341    eval.operand -= run.pc + run.size + ((run.code[0] != 0) ? 1 : 0) ;
2342    if (((eval.operand >= -128) && (eval.operand <= 127))
2343      && (run.opt[OPT_OP] == TRUE))
2344        PrintError(ERR_8_BITS) ;
2345    run.code[2] = (eval.operand >> 8) & 0xFF ;
2346    run.code[3] = eval.operand & 0xFF ;
2347    return RecordLine(PRINT_TWO_FOR_THREE) ;
2348}
2349
2350/*-------------------------------------------------------------------
2351 * Liste des instructions
2352 */
2353const struct {
2354     char name[7] ;       /* Nom de l'instruction */
2355     unsigned char page ; /* Flag de page (0x00, 0x10 ou 0x11) */
2356     unsigned char code ; /* Code de l'instruction */
2357     int cycles ;         /* Base de cycles */
2358     int ifuppercase ;    /* Pour création de fichiers Assembler
2359                           * TRUE  = Opérande
2360                           * FALSE = Pas d'opérande */
2361     int (*prog)(void) ;  /* Programme de traitement */
2362  } inst_table[] = {
2363     { "ABX"  , 0x00, 0x3A,  3, FALSE, Ass_Inherent  },
2364     { "ADCA" , 0x00, 0x89,  4, TRUE , Ass_All       },
2365     { "ADCB" , 0x00, 0xC9,  4, TRUE , Ass_All       },
2366     { "ADDA" , 0x00, 0x8B,  4, TRUE , Ass_All       },
2367     { "ADDB" , 0x00, 0xCB,  4, TRUE , Ass_All       },
2368     { "ADDD" , 0x00, 0xC3,  6, TRUE , Ass_All       },
2369     { "ANDA" , 0x00, 0x84,  4, TRUE , Ass_All       },
2370     { "ANDB" , 0x00, 0xC4,  4, TRUE , Ass_All       },
2371     { "ANDCC", 0x00, 0x1C,  2, TRUE , Ass_Immediate },
2372     { "ASLA" , 0x00, 0x48,  2, FALSE, Ass_Inherent  },
2373     { "ASLB" , 0x00, 0x58,  2, FALSE, Ass_Inherent  },
2374     { "ASL"  , 0x00, 0x08,  6, TRUE , Ass_NotImmed  },
2375     { "ASRA" , 0x00, 0x47,  2, FALSE, Ass_Inherent  },
2376     { "ASRB" , 0x00, 0x57,  2, FALSE, Ass_Inherent  },
2377     { "ASR"  , 0x00, 0x07,  6, TRUE , Ass_NotImmed  },
2378     { "BITA" , 0x00, 0x85,  4, TRUE , Ass_All       },
2379     { "BITB" , 0x00, 0xC5,  4, TRUE , Ass_All       },
2380     { "BRA"  , 0x00, 0x20,  3, TRUE , Ass_ShortBr   },
2381     { "BRN"  , 0x00, 0x21,  3, TRUE , Ass_ShortBr   },
2382     { "BHI"  , 0x00, 0x22,  3, TRUE , Ass_ShortBr   },
2383     { "BLS"  , 0x00, 0x23,  3, TRUE , Ass_ShortBr   },
2384     { "BCC"  , 0x00, 0x24,  3, TRUE , Ass_ShortBr   },
2385     { "BHS"  , 0x00, 0x24,  3, TRUE , Ass_ShortBr   },
2386     { "BCS"  , 0x00, 0x25,  3, TRUE , Ass_ShortBr   },
2387     { "BLO"  , 0x00, 0x25,  3, TRUE , Ass_ShortBr   },
2388     { "BNE"  , 0x00, 0x26,  3, TRUE , Ass_ShortBr   },
2389     { "BEQ"  , 0x00, 0x27,  3, TRUE , Ass_ShortBr   },
2390     { "BVC"  , 0x00, 0x28,  3, TRUE , Ass_ShortBr   },
2391     { "BVS"  , 0x00, 0x29,  3, TRUE , Ass_ShortBr   },
2392     { "BPL"  , 0x00, 0x2A,  3, TRUE , Ass_ShortBr   },
2393     { "BMI"  , 0x00, 0x2B,  3, TRUE , Ass_ShortBr   },
2394     { "BGE"  , 0x00, 0x2C,  3, TRUE , Ass_ShortBr   },
2395     { "BLT"  , 0x00, 0x2D,  3, TRUE , Ass_ShortBr   },
2396     { "BGT"  , 0x00, 0x2E,  3, TRUE , Ass_ShortBr   },
2397     { "BLE"  , 0x00, 0x2F,  3, TRUE , Ass_ShortBr   },
2398     { "BSR"  , 0x00, 0x8D,  7, TRUE , Ass_ShortBr   },
2399     { "CLRA" , 0x00, 0x4F,  2, FALSE, Ass_Inherent  },
2400     { "CLRB" , 0x00, 0x5F,  2, FALSE, Ass_Inherent  },
2401     { "CLR"  , 0x00, 0x0F,  6, TRUE , Ass_NotImmed  },
2402     { "CMPA" , 0x00, 0x81,  4, TRUE , Ass_All       },
2403     { "CMPB" , 0x00, 0xC1,  4, TRUE , Ass_All       },
2404     { "CMPD" , 0x10, 0x83,  7, TRUE , Ass_All       },
2405     { "CMPS" , 0x11, 0x8C,  7, TRUE , Ass_All       },
2406     { "CMPU" , 0x11, 0x83,  7, TRUE , Ass_All       },
2407     { "CMPX" , 0x00, 0x8C,  6, TRUE , Ass_All       },
2408     { "CMPY" , 0x10, 0x8C,  7, TRUE , Ass_All       },
2409     { "COMA" , 0x00, 0x43,  2, FALSE, Ass_Inherent  },
2410     { "COMB" , 0x00, 0x53,  2, FALSE, Ass_Inherent  },
2411     { "COM"  , 0x00, 0x03,  6, TRUE , Ass_NotImmed  },
2412     { "CWAI" , 0x00, 0x3C, 20, TRUE , Ass_Immediate },
2413     { "DAA"  , 0x00, 0x19,  2, FALSE, Ass_Inherent  },
2414     { "DECA" , 0x00, 0x4A,  2, FALSE, Ass_Inherent  },
2415     { "DECB" , 0x00, 0x5A,  2, FALSE, Ass_Inherent  },
2416     { "DEC"  , 0x00, 0x0A,  6, TRUE , Ass_NotImmed  },
2417     { "EORA" , 0x00, 0x88,  4, TRUE , Ass_All       },
2418     { "EORB" , 0x00, 0xC8,  4, TRUE , Ass_All       },
2419     { "EXG"  , 0x00, 0x1E,  8, TRUE , Ass_Transfer  },
2420     { "INCA" , 0x00, 0x4C,  2, FALSE, Ass_Inherent  },
2421     { "INCB" , 0x00, 0x5C,  2, FALSE, Ass_Inherent  },
2422     { "INC"  , 0x00, 0x0C,  6, TRUE , Ass_NotImmed  },
2423     { "JMP"  , 0x00, 0x0E,  3, TRUE , Ass_NotImmed  },
2424     { "JSR"  , 0x00, 0x9D,  7, TRUE , Ass_All       },
2425     { "LBRA" , 0x00, 0x16,  5, TRUE , Ass_LongBr    },
2426     { "LBRN" , 0x10, 0x21,  5, TRUE , Ass_LongBr    },
2427     { "LBHI" , 0x10, 0x22,  6, TRUE , Ass_LongBr    },
2428     { "LBLS" , 0x10, 0x23,  6, TRUE , Ass_LongBr    },
2429     { "LBCC" , 0x10, 0x24,  6, TRUE , Ass_LongBr    },
2430     { "LBHS" , 0x10, 0x24,  6, TRUE , Ass_LongBr    },
2431     { "LBCS" , 0x10, 0x25,  6, TRUE , Ass_LongBr    },
2432     { "LBLO" , 0x10, 0x25,  6, TRUE , Ass_LongBr    },
2433     { "LBNE" , 0x10, 0x26,  6, TRUE , Ass_LongBr    },
2434     { "LBEQ" , 0x10, 0x27,  6, TRUE , Ass_LongBr    },
2435     { "LBVC" , 0x10, 0x28,  6, TRUE , Ass_LongBr    },
2436     { "LBVS" , 0x10, 0x29,  6, TRUE , Ass_LongBr    },
2437     { "LBPL" , 0x10, 0x2A,  6, TRUE , Ass_LongBr    },
2438     { "LBMI" , 0x10, 0x2B,  6, TRUE , Ass_LongBr    },
2439     { "LBGE" , 0x10, 0x2C,  6, TRUE , Ass_LongBr    },
2440     { "LBLT" , 0x10, 0x2D,  6, TRUE , Ass_LongBr    },
2441     { "LBGT" , 0x10, 0x2E,  6, TRUE , Ass_LongBr    },
2442     { "LBLE" , 0x10, 0x2F,  6, TRUE , Ass_LongBr    },
2443     { "LBSR" , 0x00, 0x17,  9, TRUE , Ass_LongBr    },
2444     { "LDA"  , 0x00, 0x86,  4, TRUE , Ass_All       },
2445     { "LDB"  , 0x00, 0xC6,  4, TRUE , Ass_All       },
2446     { "LDD"  , 0x00, 0xCC,  5, TRUE , Ass_All       },
2447     { "LDS"  , 0x10, 0xCE,  6, TRUE , Ass_All       },
2448     { "LDU"  , 0x00, 0xCE,  5, TRUE , Ass_All       },
2449     { "LDX"  , 0x00, 0x8E,  5, TRUE , Ass_All       },
2450     { "LDY"  , 0x10, 0x8E,  6, TRUE , Ass_All       },
2451     { "LEAS" , 0x00, 0x32,  4, TRUE , Ass_Lea       },
2452     { "LEAU" , 0x00, 0x33,  4, TRUE , Ass_Lea       },
2453     { "LEAX" , 0x00, 0x30,  4, TRUE , Ass_Lea       },
2454     { "LEAY" , 0x00, 0x31,  4, TRUE , Ass_Lea       },
2455     { "LSLA" , 0x00, 0x48,  2, FALSE, Ass_Inherent  },
2456     { "LSLB" , 0x00, 0x58,  2, FALSE, Ass_Inherent  },
2457     { "LSL"  , 0x00, 0x08,  6, TRUE , Ass_NotImmed  },
2458     { "LSRA" , 0x00, 0x44,  2, FALSE, Ass_Inherent  },
2459     { "LSRB" , 0x00, 0x54,  2, FALSE, Ass_Inherent  },
2460     { "LSR"  , 0x00, 0x04,  6, TRUE , Ass_NotImmed  },
2461     { "MUL"  , 0x00, 0x3D, 11, FALSE, Ass_Inherent  },
2462     { "NEGA" , 0x00, 0x40,  2, FALSE, Ass_Inherent  },
2463     { "NEGB" , 0x00, 0x50,  2, FALSE, Ass_Inherent  },
2464     { "NEG"  , 0x00, 0x00,  6, TRUE , Ass_NotImmed  },
2465     { "NOP"  , 0x00, 0x12,  2, FALSE, Ass_Inherent  },
2466     { "ORA"  , 0x00, 0x8A,  4, TRUE , Ass_All       },
2467     { "ORB"  , 0x00, 0xCA,  4, TRUE , Ass_All       },
2468     { "ORCC" , 0x00, 0x1A,  2, TRUE , Ass_Immediate },
2469     { "PSHS" , 0x00, 0x34,  5, TRUE , Ass_SStack    },
2470     { "PSHU" , 0x00, 0x36,  5, TRUE , Ass_UStack    },
2471     { "PULS" , 0x00, 0x35,  5, TRUE , Ass_SStack    },
2472     { "PULU" , 0x00, 0x37,  5, TRUE , Ass_UStack    },
2473     { "ROLA" , 0x00, 0x49,  2, FALSE, Ass_Inherent  },
2474     { "ROLB" , 0x00, 0x59,  2, FALSE, Ass_Inherent  },
2475     { "ROL"  , 0x00, 0x09,  6, TRUE , Ass_NotImmed  },
2476     { "RORA" , 0x00, 0x46,  2, FALSE, Ass_Inherent  },
2477     { "RORB" , 0x00, 0x56,  2, FALSE, Ass_Inherent  },
2478     { "ROR"  , 0x00, 0x06,  6, TRUE , Ass_NotImmed  },
2479     { "RTI"  , 0x00, 0x3B, 15, FALSE, Ass_Inherent  },
2480     { "RTS"  , 0x00, 0x39,  5, FALSE, Ass_Inherent  },
2481     { "SBCA" , 0x00, 0x82,  4, TRUE , Ass_All       },
2482     { "SBCB" , 0x00, 0xC2,  4, TRUE , Ass_All       },
2483     { "SEX"  , 0x00, 0x1D,  2, FALSE, Ass_Inherent  },
2484     { "STA"  , 0x00, 0x97,  4, TRUE , Ass_All       },
2485     { "STB"  , 0x00, 0xD7,  4, TRUE , Ass_All       },
2486     { "STD"  , 0x00, 0xDD,  5, TRUE , Ass_All       },
2487     { "STS"  , 0x10, 0xDF,  6, TRUE , Ass_All       },
2488     { "STU"  , 0x00, 0xDF,  5, TRUE , Ass_All       },
2489     { "STX"  , 0x00, 0x9F,  5, TRUE , Ass_All       },
2490     { "STY"  , 0x10, 0x9F,  6, TRUE , Ass_All       },
2491     { "SUBA" , 0x00, 0x80,  4, TRUE , Ass_All       },
2492     { "SUBB" , 0x00, 0xC0,  4, TRUE , Ass_All       },
2493     { "SUBD" , 0x00, 0x83,  6, TRUE , Ass_All       },
2494     { "SWI"  , 0x00, 0x3F, 19, FALSE, Ass_Inherent  },
2495     { "SWI2" , 0x10, 0x3F, 20, FALSE, Ass_Inherent  },
2496     { "SWI3" , 0x11, 0x3F, 20, FALSE, Ass_Inherent  },
2497     { "SYNC" , 0x00, 0x13,  4, FALSE, Ass_Inherent  },
2498     { "TFR"  , 0x00, 0x1F,  6, TRUE , Ass_Transfer  },
2499     { "TSTA" , 0x00, 0x4D,  2, FALSE, Ass_Inherent  },
2500     { "TSTB" , 0x00, 0x5D,  2, FALSE, Ass_Inherent  },
2501     { "TST"  , 0x00, 0x0D,  6, TRUE , Ass_NotImmed  }
2502};
2503#define ITSIZE (int)sizeof(inst_table)/(int)sizeof(inst_table[0])
2504
2505
2506/***********************************************************************
2507 *
2508 * Assemblage des directives
2509 *
2510 ***********************************************************************/
2511 
2512/*
2513 * Récupération d'un descripteur de fichier
2514 */
2515struct {
2516    int drive ;     /* Numéro du lecteur */
2517    char name[14] ; /* Nom du fichier : xxxxxxxx.xxx */
2518} desc ;
2519
2520int GetDescriptor(char *suffix)
2521{
2522    int i ;
2523
2524    if ((*line != '\0')
2525     && (*(line+1) == ':'))
2526    {
2527        if ((*line <= '0') && (*line > '4'))
2528            return PrintError(ERR_BAD_FILE_NAME) ;
2529        desc.drive = *line - '0' ;
2530        line += 2 ;
2531    }
2532
2533    desc.name[0] = '\0' ;
2534    for(i=0;i<9;i++)
2535    {
2536        if ((*line == 0x20)
2537         || (*line == 0x00)
2538         || (*line == CHAR127)
2539         || (*line == '.'))
2540            break ;
2541        if ((*line == '(')
2542         || (*line == ')')
2543         || (*line == ':')
2544         || ((*line & 0xFF) > 0x7F))
2545            return PrintError(ERR_BAD_FILE_NAME) ;
2546        strncat(desc.name,line++,1) ;
2547    }
2548
2549    if ((i > 8) || (i == 0))
2550        return PrintError(ERR_BAD_FILE_NAME) ;
2551
2552    if (*line == '.')
2553    {
2554        strcat(desc.name,".") ;
2555        line++ ;
2556        for(i=0;i<4;i++)
2557        {
2558            if ((*line == 0x20)
2559             || (*line == CHAR127)
2560             || (*line == 0x00))
2561                break ;
2562            if ((*line == '(')
2563             || (*line == ')')
2564             || (*line == ':')
2565             || (*line == '.')
2566             || ((*line & 0xFF) > 0x7F))
2567                return PrintError(ERR_BAD_FILE_NAME) ;
2568            strncat(desc.name,line++,1) ;
2569        }
2570        if (i > 3)
2571            return PrintError(ERR_BAD_FILE_NAME) ;
2572    }
2573    else
2574    {
2575        strcat(desc.name,".") ;
2576        strcat(desc.name,suffix) ;
2577    }
2578
2579    return NO_ERROR ;
2580}
2581
2582/*-------------------------------------------------------------------
2583 * Assemblage des directives Fill
2584 */
2585
2586enum{
2587    FCB_TYPE,
2588    FCC_TYPE,
2589    FCN_TYPE,
2590    FCS_TYPE,
2591    FDB_TYPE
2592} ;
2593
2594/*
2595 * Enregistre la liste des codes
2596 */
2597int RecordFC(int flag, int type)
2598{
2599    int i ;
2600    if (run.size != 0)
2601    {
2602        RecordLine(flag) ;
2603        flag = (type == FDB_TYPE) ? PRINT_WORDS_ONLY : PRINT_BYTES_ONLY ;
2604        for(i=0;i<run.size;i++)
2605            SaveBinChar(run.code[i+1]) ;
2606        run.size = 0 ;
2607    }
2608    return flag ;
2609}
2610
2611/*
2612 * Enregistre la liste des codes si buffer plein
2613 */
2614int RecordFCIf(unsigned char c, int flag, int type)
2615{
2616    if(run.size == 4)
2617        flag = RecordFC(flag,type) ;
2618    run.code[++run.size] = c ;
2619    return flag ;
2620}
2621
2622int Ass_All_FC(int type)
2623{
2624    int i ;
2625    int flag = (type == FDB_TYPE) ? PRINT_WORDS : PRINT_BYTES ;
2626    int flagexit = FALSE ;
2627    unsigned char charend = '\0' ;
2628   
2629    char asciitable[][2] = {
2630        "Kc",    /* c cédille      */
2631        "Ba",    /* a accent aigu  */
2632        "Ca",    /* a accent circ  */
2633        "Ha",    /* a tréma        */
2634        "Aa",    /* a accent grave */
2635        "Be",    /* e accent aigu  */
2636        "Ce",    /* e accent circ  */
2637        "He",    /* e tréma        */
2638        "Ae",    /* e accent grave */
2639        "Ci",    /* i accent circ  */
2640        "Hi",    /* i tréma        */
2641        "Co",    /* o accent circ  */
2642        "Ho",    /* o tréma        */
2643        "Cu",    /* u accent circ  */
2644        "Hu",    /* u tréma        */
2645        "Au"     /* u accent grave */
2646    } ;
2647
2648    run.size = 0 ;
2649
2650    if ((type != FCB_TYPE) && (type != FDB_TYPE))
2651    {
2652        if (*line == '\0')
2653            return PrintError(ERR_MISSING_INFORMATION) ;
2654        else
2655            charend = *(line++) ;
2656    }
2657
2658    do
2659    {
2660        switch(type)
2661        {
2662            case FCB_TYPE :
2663                if (Eval() != NO_ERROR) return ERR_ERROR ;
2664                if ((eval.operand < -256 ) || (eval.operand > 255))
2665                    PrintError(ERR_OPERAND_OUT_OF_RANGE) ;
2666                flag = RecordFCIf(eval.operand & 0xFF, flag, type) ;
2667                if (*line == ',') line++ ; else flagexit = TRUE ;
2668                break ;
2669            case FDB_TYPE :
2670                if (Eval() != NO_ERROR) return ERR_ERROR ;
2671                flag = RecordFCIf((eval.operand >> 8) & 0xFF, flag, type) ;
2672                flag = RecordFCIf(eval.operand & 0xFF, flag, type) ;
2673                if (*line == ',') line++ ; else flagexit = TRUE ;
2674                break ;
2675            default :
2676                if (*line == '\0')
2677                    return PrintError(ERR_MISSING_INFORMATION) ;
2678                else
2679                if (*line == charend)
2680                {
2681                    flagexit = TRUE ;
2682                    if ((type == FCN_TYPE)
2683                     && (run.size > 0))
2684                        run.code[run.size] |= 0x80 ;
2685                    line++ ;
2686                }
2687                else
2688                if ((unsigned char)*line > 0x7F)
2689                {
2690                    if (scan.soft == SOFT_ASSEMBLER)
2691                        return PrintError(ERR_BAD_OPERAND) ;
2692                    i = 0 ;
2693                    while (*line != acc_table[i]) i++ ;
2694                    flag = RecordFCIf(0x16, flag, type) ;
2695                    flag = RecordFCIf(asciitable[i][0], flag, type) ;
2696                    flag = RecordFCIf(asciitable[i][1], flag, type) ;
2697                    line++ ;
2698                }
2699                else
2700                if (*line >= 0x20)
2701                {
2702                    if (*line == CHAR127)
2703                        flag = RecordFCIf(' ', flag, type) ;
2704                    else
2705                        flag = RecordFCIf(*line, flag, type) ;
2706                    line++ ;
2707                }
2708                break ;
2709        }
2710    } while(flagexit == FALSE) ;
2711
2712    if (type == FCS_TYPE) {
2713        flag = RecordFCIf(0x00, flag, type) ; }
2714
2715    if (run.size != 0)
2716        RecordFC(flag, type) ;
2717
2718    return NO_ERROR ;
2719}
2720
2721
2722int Ass_FCB(void)
2723{
2724    return Ass_All_FC(FCB_TYPE) ;
2725}
2726
2727int Ass_FCC(void)
2728{
2729    return Ass_All_FC(FCC_TYPE) ;
2730}
2731
2732int Ass_FCS(void)
2733{
2734    return Ass_All_FC(FCS_TYPE) ;
2735}
2736
2737int Ass_FCN(void)
2738{
2739    return Ass_All_FC(FCN_TYPE) ;
2740}
2741
2742int Ass_FDB(void)
2743{
2744    return Ass_All_FC(FDB_TYPE) ;
2745}
2746
2747/*-------------------------------------------------------------------
2748 * Assemblage des réservations mémoire
2749 */
2750
2751int Ass_PrintWithPcr(unsigned short pcr2)
2752{
2753    unsigned short pcr1 ;
2754    pcr1 = run.pc ;
2755    run.pc = pcr2 ;
2756    RecordLine(PRINT_PC) ;
2757    run.pc = pcr1 ;
2758    return NO_ERROR ;
2759}
2760
2761int Ass_RMx(int size)
2762{
2763    int i ;
2764    int count ;
2765    unsigned short pcr = run.pc ;
2766
2767    run.size = 0 ;
2768    if (Eval() != NO_ERROR) return ERR_ERROR ;
2769    if ((count = eval.operand) < 0)
2770        return PrintError(ERR_BAD_OPERAND) ;
2771    if(*line != ',')
2772        run.pc += count * size ;
2773    else
2774    {
2775        if (scan.soft == SOFT_ASSEMBLER)
2776            return PrintError(ERR_BAD_OPERAND) ;
2777        line++ ;
2778        if (Eval() != NO_ERROR) return ERR_ERROR ;
2779        if ((size == 1)
2780         && ((eval.operand < -256) || (eval.operand > 255)))
2781            return PrintError(ERR_BAD_OPERAND) ;
2782        for(i=0;i<count;i++)
2783        {
2784            if (size == 2)
2785                SaveBinChar((eval.operand >> 8) & 0xFF) ;
2786            SaveBinChar(eval.operand & 0xFF) ;
2787        }
2788    }
2789    return Ass_PrintWithPcr(pcr) ;
2790}
2791
2792int Ass_RMB(void)
2793{
2794    return Ass_RMx(1) ;
2795}
2796
2797int Ass_RMD(void)
2798{
2799    return Ass_RMx(2) ;
2800}
2801
2802/*-------------------------------------------------------------------
2803 * Assemblage des directives MO
2804 */
2805
2806int Ass_Special_MO(void)
2807{
2808    if ((scan.soft == SOFT_ASSEMBLER)
2809     && (scan.computer != MO_COMPUTER))
2810        return PrintError(ERR_BAD_OPCODE) ;
2811    return NO_ERROR ;
2812}
2813
2814int Ass_CALL_And_GOTO(unsigned char jump)
2815{
2816    if (Ass_Special_MO() != NO_ERROR) return ERR_ERROR ;
2817    run.size = 2 ;
2818    if (Eval() != NO_ERROR) return ERR_ERROR ;
2819    if((eval.operand < 0) || (eval.operand > 255))
2820        return PrintError(ERR_BAD_OPERAND) ;
2821    run.code[0] = 0x00 ;
2822    run.code[1] = 0x3F ;
2823    run.code[2] = (eval.operand & 0xFF) | jump ;
2824    return RecordLine(PRINT_TWO_FOR_TWO) ;     
2825}
2826
2827int Ass_CALL(void)
2828{
2829    return Ass_CALL_And_GOTO(0x00) ;
2830}
2831
2832int Ass_GOTO(void)
2833{
2834    return Ass_CALL_And_GOTO(0x80) ;
2835}
2836
2837int Ass_STOP(void)
2838{
2839    if (Ass_Special_MO() != NO_ERROR) return ERR_ERROR ;
2840    run.size = 3 ;
2841    run.code[0] = 0x00 ;
2842    run.code[1] = 0xBD ;
2843    run.code[2] = 0xB0 ;
2844    run.code[3] = 0x00 ;
2845    return RecordLine(PRINT_TWO_FOR_THREE) ;
2846}
2847
2848/*-------------------------------------------------------------------
2849 * Assemblage des déclarations
2850 */
2851
2852int Ass_SET_And_EQU(int type)
2853{
2854    if (Eval() != NO_ERROR) return ERR_ERROR ;
2855    if (DoSymbol(labelname,eval.operand,type) != NO_ERROR)
2856        return ERR_ERROR ;
2857    return RecordLine(PRINT_LIKE_END) ;
2858}
2859
2860int Ass_SET(void)
2861{
2862    return Ass_SET_And_EQU(SET_VALUE) ;
2863}
2864
2865int Ass_EQU(void)
2866{
2867    return Ass_SET_And_EQU(EQU_VALUE) ;
2868}
2869
2870/*-------------------------------------------------------------------
2871 * Assemblage des includes
2872 */
2873
2874struct SRCLIST {
2875     struct SRCLIST *next ; /* Pointeur sur section suivante */
2876     unsigned char drive ;  /* Numéro de lecteur */
2877     char name[13] ; /* Nom du fichier xxxxxxxx.xxx */
2878     int line  ;     /* Numéro de ligne */
2879     int asm_size  ; /* Taille ASM compressé */
2880     char *start ;   /* Pointeur sur début du source */
2881     char *end ;     /* Pointeur sur fin du source */
2882} ;
2883
2884struct SRCLIST *first_source ;
2885struct SRCLIST *current_source ;
2886
2887/*
2888 * Initialise le chaînage des includes
2889 */
2890void InitIncludChain(void)
2891{
2892    first_includ = malloc(sizeof(struct INCLIST)) ;
2893    first_includ->prev = NULL ;
2894    first_includ->line = first_source->line ;
2895    first_includ->count = 0 ;
2896    first_includ->drive  = first_source->drive ;
2897    first_includ->name[0] = '\0' ;
2898    strcat(first_includ->name,first_source->name) ;
2899    first_includ->start = first_source->start ;
2900    first_includ->end   = first_source->end ;
2901}
2902
2903/*
2904 * Libère la mémoire pour le chaînage des includes
2905 */
2906void FreeIncludChain(void)
2907{
2908    struct INCLIST *last_includ ;
2909    while((last_includ = first_includ))
2910    {
2911        first_includ = first_includ->prev ;
2912        free(last_includ) ;
2913    }
2914}
2915
2916/*
2917 * Engage une séquence d'include
2918 */
2919int Ass_Start_INC(char *suffix)
2920{
2921    if (((run.locked & MACRO_LOCK) || (macro.level))
2922      && (scan.soft == SOFT_MACROASSEMBLER))
2923         return PrintError(ERR_ILLEGAL_INCLUDE) ;
2924    if(GetDescriptor(suffix) != NO_ERROR) return ERR_ERROR ;
2925    return NO_ERROR ;
2926}
2927
2928
2929/*
2930 * Assemble les INCLUD
2931 */
2932int Ass_INCLUD(void)
2933{
2934    struct INCLIST *prev_includ = NULL ;
2935
2936    if (Ass_Start_INC("ASM") != NO_ERROR)
2937        return ERR_ERROR ;
2938    if (run.pass > MACROPASS)
2939    {
2940        /* Recherche l'include dans la liste des sources */
2941        current_source = first_source ;
2942        while((current_source != NULL)
2943           && (strcmp(current_source->name,desc.name)))
2944            current_source = current_source->next ;
2945
2946        /* Erreur si INCLUD introuvable */
2947        if (current_source == NULL)
2948            return PrintError(ERR_FILE_NOT_FOUND) ;
2949
2950        /* Met l'includ courant à jour */
2951        first_includ->start = source ;
2952        first_includ->line = run.line ;
2953        /* Crée le nouvel includ */
2954        prev_includ = first_includ ;
2955        first_includ = malloc(sizeof(struct INCLIST)) ;
2956        first_includ->prev  = prev_includ ;
2957        first_includ->drive  = current_source->drive ;
2958        first_includ->name[0] = '\0' ;
2959        strcat(first_includ->name, current_source->name) ;
2960        first_includ->line  = current_source->line ;
2961        first_includ->start = current_source->start ;
2962        first_includ->end   = current_source->end ;
2963        first_includ->count = prev_includ->count + 1 ;
2964        source = first_includ->start ;
2965        run.line = first_includ->line ;
2966        RecordLine(PRINT_NO_CODE) ;
2967    }
2968    return NO_ERROR ;
2969}
2970
2971/*
2972 * Erreur 'Bad File Format' pour les INCBIN
2973 */
2974int Ass_BadFileFormat(FILE *fp_file)
2975{
2976    fclose(fp_file) ;
2977    return PrintError(ERR_BAD_FILE_FORMAT) ;
2978}
2979
2980/*
2981 * Assemble les INCBIN
2982 */
2983int Ass_INCBIN(void)
2984{
2985    FILE *fp_file;
2986    int flag = 0 ;
2987    int size = 0 ;
2988    int i ;
2989    unsigned short pcr = run.pc ;
2990
2991    if (Ass_Start_INC("BIN") != NO_ERROR)
2992        return ERR_ERROR ;
2993    printf("fichier = %s\n",desc.name) ;
2994    if ((fp_file = fopen(desc.name,"rb")) == NULL)
2995        return PrintError(ERR_FILE_NOT_FOUND) ;
2996
2997    if (feof(fp_file)) return Ass_BadFileFormat(fp_file) ;
2998    printf("flag = %08x\n",flag) ;
2999    flag = fgetc(fp_file) ;
3000    printf("flag = %08x\n",flag) ;
3001    if (feof(fp_file)) return Ass_BadFileFormat(fp_file) ;
3002    while (flag == 0x00)
3003    {
3004        size = fgetc(fp_file) << 8 ;
3005        if (feof(fp_file)) return Ass_BadFileFormat(fp_file) ;
3006        size |= fgetc(fp_file) ;
3007        if (feof(fp_file)) return Ass_BadFileFormat(fp_file) ;
3008        fgetc(fp_file) ;
3009        if (feof(fp_file)) return Ass_BadFileFormat(fp_file) ;
3010        fgetc(fp_file) ;
3011        if (feof(fp_file)) return Ass_BadFileFormat(fp_file) ;
3012        for(i=0;i<size;i++)
3013        {
3014            SaveBinChar(fgetc(fp_file)) ;
3015            if (feof(fp_file)) return Ass_BadFileFormat(fp_file) ;
3016        }
3017        flag = fgetc(fp_file) ;
3018        if (feof(fp_file)) return Ass_BadFileFormat(fp_file) ;
3019    }
3020    if (flag != 0xFF)
3021        return Ass_BadFileFormat(fp_file) ;
3022    if ((fgetc(fp_file) != 0x00)
3023     || (feof(fp_file)))
3024        return Ass_BadFileFormat(fp_file) ;
3025    if ((fgetc(fp_file) != 0x00)
3026     || (feof(fp_file)))
3027        return Ass_BadFileFormat(fp_file) ;
3028    fgetc(fp_file) ;
3029    if (feof(fp_file))
3030        return Ass_BadFileFormat(fp_file) ;
3031    fclose(fp_file) ;
3032
3033    return Ass_PrintWithPcr(pcr) ;
3034}
3035
3036/*
3037 * Assemble les INCDAT
3038 */
3039int Ass_INCDAT(void)
3040{
3041    FILE *fp_file ;
3042    unsigned short pcr = run.pc ;
3043
3044    if (Ass_Start_INC("") != NO_ERROR)
3045        return ERR_ERROR ;
3046    if ((fp_file = fopen(desc.name,"rb")) ==  NULL)
3047        return PrintError(ERR_FILE_NOT_FOUND) ;
3048    while (!feof(fp_file))
3049        SaveBinChar(fgetc(fp_file)) ;
3050    fclose(fp_file) ;
3051    return Ass_PrintWithPcr(pcr) ;
3052}
3053
3054/*-------------------------------------------------------------------
3055 * Assemblage d'affichage
3056 */
3057
3058int Ass_ECHO(void)
3059{
3060    char c ;
3061    int i ;
3062    char operand[18] ;
3063    char echoline[LINE_MAX_SIZE+2] ;
3064
3065    if ((run.pass == PASS2)
3066     && (run.opt[OPT_WL] == FALSE))
3067    {
3068        echoline[0] = '\0' ;
3069        while(*line != 0)
3070        {
3071            operand[0] = '\0' ;
3072            switch (c = *(line++))
3073            {
3074                case '%':
3075                    if (Eval() != NO_ERROR) return ERR_ERROR ;
3076                    strcat(operand,"%") ;
3077                    i = 0x8000 ;
3078                    while(((eval.operand & i) == 0) && (i != 1))
3079                        i >>= 1 ;
3080                    while(i != 0) {
3081                        if (eval.operand & i) strcat(operand,"1") ;
3082                        else  strcat(operand,"0") ;
3083                        i >>= 1 ; }
3084                    break ;
3085                case '@':
3086                    if (Eval() != NO_ERROR) return ERR_ERROR ;
3087                    sprintf(operand,"@%o",eval.operand & 0xFFFF) ;
3088                    break ;
3089                case '&':
3090                    if (Eval() != NO_ERROR) return ERR_ERROR ;
3091                    sprintf(operand,"%d",eval.operand & 0xFFFF) ;
3092                    break ;
3093                case '$':
3094                    if (Eval() != NO_ERROR) return ERR_ERROR ;
3095                    sprintf(operand,"$%04X",eval.operand & 0xFFFF) ;
3096                    break ;
3097                default :
3098                    strncat(echoline,&c,1) ;
3099                    break ;
3100            }
3101            strcat(echoline,operand) ;
3102        }
3103        printf("%s\n",echoline) ;
3104    }
3105    return RecordLine(PRINT_NO_CODE) ;
3106}
3107
3108int Ass_PRINT(void)
3109{
3110    if ((run.pass == PASS1)
3111     && (run.opt[OPT_WL] == FALSE))
3112        printf("%s\n",line) ;
3113    return RecordLine(PRINT_NO_CODE) ;
3114}
3115
3116/*-------------------------------------------------------------------
3117 * Assemblage de mise en page
3118 */
3119
3120int Ass_TITLE(void)
3121{
3122    return RecordLine(PRINT_NO_CODE) ;
3123}
3124
3125int Ass_PAGE(void)
3126{
3127    if (*line != '\0')
3128        return PrintError(ERR_ILLEGAL_OPERAND) ;
3129    return RecordLine(PRINT_NO_CODE) ;
3130}
3131
3132/*-------------------------------------------------------------------
3133 * Assemblage conditionnel
3134 */
3135
3136enum {
3137    IF_IFNE,
3138    IF_IFEQ,
3139    IF_IFGT,
3140    IF_IFLT,
3141    IF_IFGE,
3142    IF_IFLE
3143} ;
3144
3145int Ass_All_IF(int condition)
3146{
3147    int result = FALSE ;
3148
3149    if (run.locked & (COMMENT_LOCK | MACRO_LOCK))
3150        return RecordLine(PRINT_NO_CODE) ;
3151    if ((ifc.count == 16)
3152      && (scan.soft == SOFT_MACROASSEMBLER))
3153        return PrintError(ERR_IF_OUT_OF_RANGE) ;
3154    if (Eval() != NO_ERROR) return ERR_ERROR ;
3155    switch(condition)
3156    {
3157        case IF_IFNE : result = (eval.operand != 0) ; break ;
3158        case IF_IFEQ : result = (eval.operand == 0) ; break ;
3159        case IF_IFGT : result = (eval.operand >  0) ; break ;
3160        case IF_IFLT : result = (eval.operand <  0) ; break ;
3161        case IF_IFGE : result = (eval.operand >= 0) ; break ;
3162        case IF_IFLE : result = (eval.operand <= 0) ; break ;
3163    }
3164
3165    ifc.count++ ;
3166    if ((ifc.buf[ifc.count - 1] == IF_TRUE)
3167     || (ifc.buf[ifc.count - 1] == IF_FALSE_ELSE))
3168        ifc.buf[ifc.count] = (result == TRUE) ? IF_TRUE : IF_FALSE ;
3169    else
3170        ifc.buf[ifc.count] = IF_STOP ;
3171
3172    run.locked &= ~IF_LOCK ;
3173    if (ifc.buf[ifc.count] != IF_TRUE) run.locked |= IF_LOCK ;
3174
3175    return RecordLine(PRINT_NO_CODE) ;
3176}
3177
3178int Ass_IF(void)
3179{
3180    return Ass_All_IF(IF_IFNE) ;
3181}
3182
3183int Ass_IFNE(void)
3184{
3185    return Ass_All_IF(IF_IFNE) ;
3186}
3187
3188int Ass_IFEQ(void)
3189{
3190    return Ass_All_IF(IF_IFEQ) ;
3191}
3192
3193int Ass_IFGT(void)
3194{
3195    return Ass_All_IF(IF_IFGT) ;
3196}
3197
3198int Ass_IFLT(void)
3199{
3200    return Ass_All_IF(IF_IFLT) ;
3201}
3202
3203int Ass_IFGE(void)
3204{
3205    return Ass_All_IF(IF_IFGE) ;
3206}
3207
3208int Ass_IFLE(void)
3209{
3210    return Ass_All_IF(IF_IFLE) ;
3211}
3212
3213int Ass_ELSE(void)
3214{
3215    if (run.locked & (COMMENT_LOCK | MACRO_LOCK))
3216        return RecordLine(PRINT_NO_CODE) ;
3217
3218    if (ifc.count == 0)
3219        return PrintError(ERR_MISSING_IF) ;
3220
3221    switch(ifc.buf[ifc.count])
3222    {
3223        case IF_TRUE_ELSE  :
3224        case IF_FALSE_ELSE :
3225             return PrintError(ERR_BAD_ELSE) ;
3226             break ;
3227        case IF_STOP :
3228            break ;
3229        default :
3230            ifc.buf[ifc.count] = (ifc.buf[ifc.count] == IF_TRUE) ? IF_TRUE_ELSE : IF_FALSE_ELSE ;
3231            break ;
3232    }
3233    run.locked &= ~IF_LOCK ;
3234    if (ifc.buf[ifc.count] != IF_FALSE_ELSE) run.locked |= IF_LOCK ;
3235
3236    return RecordLine(PRINT_NO_CODE) ;
3237}
3238
3239int Ass_ENDC(void)
3240{
3241    if (run.locked & (COMMENT_LOCK | MACRO_LOCK))
3242        return RecordLine(PRINT_NO_CODE) ;
3243
3244    if (ifc.count == 0)
3245        return PrintError(ERR_MISSING_IF) ;
3246
3247    ifc.count-- ;
3248    run.locked &= ~IF_LOCK ;
3249    if ((ifc.buf[ifc.count] != IF_FALSE_ELSE)
3250     && (ifc.buf[ifc.count] != IF_TRUE)) run.locked |= IF_LOCK ;
3251
3252    return RecordLine(PRINT_NO_CODE) ;
3253}
3254
3255/*-------------------------------------------------------------------
3256 * Assemblage des macros
3257 */
3258
3259struct MACROLIST {
3260     struct MACROLIST *next ; /* Pointeur sur section suivante */
3261     int count  ;    /* Identificateur de macro */
3262     int line  ;     /* Numéro de ligne */
3263     char *arg[10] ; /* Liste des arguments */
3264     char *start ;   /* Pointeur sur début de macro */
3265     char *end ;     /* Pointeur sur fin de macro */
3266} ;
3267
3268struct MACROLIST *first_macro ;
3269struct MACROLIST *current_macro ;
3270extern int CheckIfReservedName(void) ;
3271
3272struct MACROARGLIST {
3273     struct MACROARGLIST *prev ; /* Pointeur sur section précedente */
3274     int  line ;     /* Numéro de ligne */
3275     char *ptr ;     /* Ptr sur macro */
3276     char *arg[10] ; /* Liste des arguments de macro */
3277} ;
3278
3279struct MACROARGLIST *current_macroarg ;
3280
3281/*
3282 * Initialise le chaînage des macros
3283 */
3284void InitMacroChain(void)
3285{
3286    first_macro = malloc(sizeof(struct MACROLIST)) ;
3287    first_macro->next  = NULL ;
3288    first_macro->line  = 0 ;
3289    first_macro->start = NULL ;
3290    first_macro->end   = NULL ;
3291    current_macro = first_macro ;
3292}
3293
3294/*
3295 * Libère la mémoire pour le chaînage des macros
3296 */
3297void FreeMacroChain(void)
3298{
3299    while((current_macro = first_macro))
3300    {
3301        first_macro = first_macro->next ;
3302        free(current_macro) ;
3303    }
3304}
3305
3306
3307int Ass_MACRO(void)
3308{
3309    if (run.locked & (COMMENT_LOCK + IF_LOCK))
3310        return RecordLine(PRINT_NO_CODE) ;
3311
3312    macro.count++ ;
3313    if (macro.level)
3314        return PrintError(ERR_EMBEDDED_MACRO) ;
3315    else
3316    if (run.pass == MACROPASS)
3317    {
3318        current_macro->next = malloc(sizeof(struct MACROLIST)) ;
3319        current_macro = current_macro->next ;
3320        current_macro->next  = NULL ;
3321        current_macro->count = macro.count ;
3322        current_macro->line  = run.line ;
3323        current_macro->start = source ;
3324        current_macro->end   = NULL ;
3325    }
3326    else     {
3327        /* Erreur si une macro a déjà été déclarée */
3328        if (run.locked & MACRO_LOCK)
3329            return PrintError(ERR_EMBEDDED_MACRO) ;
3330        /* Erreur si le nom de la macro est réservé */
3331        if (CheckIfReservedName() != NO_ERROR)
3332            return ERR_ERROR ;
3333        /* Erreur éventuelle si assemblage conditionnel en cours */
3334        if ((ifc.count > 0) && (scan.soft == SOFT_MACROASSEMBLER))
3335            return PrintError(ERR_MACRO_INTO_IF_RANGE) ;
3336        /* Déclare la macro */
3337        if (DoSymbol(labelname,macro.count,MACRO_VALUE) != NO_ERROR)
3338            return ERR_ERROR ;
3339        /* Active le bit macro */
3340        run.locked |= MACRO_LOCK ;
3341        RecordLine(PRINT_NO_CODE) ;
3342    }
3343    return NO_ERROR ;
3344}
3345
3346
3347int Ass_ENDM(void)
3348{
3349    struct MACROARGLIST *prev_macroarg ;
3350
3351    if (run.locked & (COMMENT_LOCK + IF_LOCK))
3352        return RecordLine(PRINT_NO_CODE) ;
3353
3354    if (macro.level)
3355    {
3356        if (current_macroarg->prev == NULL)
3357            return PrintError(ERR_ENDM_WITHOUT_MACRO) ;
3358        prev_macroarg = current_macroarg->prev ;
3359        free(current_macroarg) ;
3360        current_macroarg = prev_macroarg ;
3361        source   = current_macroarg->ptr ;
3362        run.line = current_macroarg->line ;
3363        macro.level-- ;
3364        return NO_ERROR ;
3365    }
3366    else
3367    if (run.pass == MACROPASS)
3368    {
3369        if (current_macro->end != NULL)
3370            return PrintError(ERR_ENDM_WITHOUT_MACRO) ;
3371        current_macro->end = source ;
3372    }
3373    else
3374    if ((run.locked & MACRO_LOCK) == 0)
3375        return PrintError(ERR_ENDM_WITHOUT_MACRO) ;
3376
3377    run.locked &= ~MACRO_LOCK ;
3378    return RecordLine(PRINT_NO_CODE) ;
3379}
3380
3381/*-------------------------------------------------------------------
3382 * Assemblage des autres directives
3383 */
3384
3385int Ass_ORG(void)
3386{
3387    if (Eval() != NO_ERROR) return ERR_ERROR ;
3388    run.pc = eval.operand ;
3389    return RecordLine(PRINT_PC) ;
3390}
3391
3392int Ass_SETDP(void)
3393{
3394    if (Eval() != NO_ERROR) return ERR_ERROR ;
3395    if((eval.operand < -256) || (eval.operand > 255))
3396        return PrintError(ERR_BAD_OPERAND) ;
3397    run.dp = eval.operand & 0xFF ;
3398    return RecordLine(PRINT_LIKE_DP) ;
3399}
3400
3401int Ass_END(void)
3402{
3403    eval.operand = 0 ;
3404    if ((*line != '\0')
3405     && (*line != ' ')
3406     && (*line != CHAR127))
3407    {
3408        if (Eval() != NO_ERROR) return ERR_ERROR ;
3409        run.exec = eval.operand ;
3410    }
3411    run.exit = TRUE ;
3412    return RecordLine(PRINT_LIKE_END) ;
3413}
3414
3415int Ass_OPT(void)
3416{
3417    const struct {
3418        char name[3] ; /* Nom du switch d'option */
3419        int type ;     /* Code du switch d'option */
3420      } OptTable[6] = {
3421       { "NO", OPT_NO }, /* Pas d'objet */
3422       { "OP", OPT_OP }, /* Optimisation */
3423       { "SS", OPT_SS }, /* Lignes séparées   (inactif) */
3424       { "WE", OPT_WE }, /* Attend à l'erreur (inactif) */
3425       { "WL", OPT_WL }, /* Affiche lignes */
3426       { "WS", OPT_WS }  /* Affiche symboles */
3427    } ;
3428
3429    int i ;
3430    int status ;
3431
3432    if ((*line == '\0')
3433     || ((run.pass != SCANPASS) && (run.pass != PASS2)))
3434        return NO_ERROR ;
3435    do
3436    {
3437        status = TRUE ;
3438        if (*line == '.') { status = FALSE ; line++ ; }
3439        if (ScanLine() != ALPHA_CHAR)
3440            return PrintError(ERR_BAD_PARAM) ;
3441        upper_string(arg) ;
3442        i = 0 ;
3443        while ((i < 6) && (strcmp(arg,OptTable[i].name))) i++ ;
3444        if (i == 6)
3445            return PrintError(ERR_BAD_PARAM) ;
3446        run.opt[OptTable[i].type] = status ;
3447    } while((ScanLine() != END_CHAR) && (*arg == '/')) ;
3448
3449    return RecordLine(PRINT_NO_CODE) ;
3450}
3451
3452/*-------------------------------------------------------------------
3453 * Liste des directives
3454 */
3455enum {
3456    NO_LABEL, /* Pas d'étiquette */
3457    LABEL,    /* Etiquette éventuelle */
3458    A_LABEL   /* Etiquette obligatoire */
3459} ;
3460const struct DIRECTTABLE {
3461     char name[7] ;    /* Nom de la directive */
3462     int iflabel ;     /* NO_LABEL/LABEL/A_LABEL */
3463     int soft ;        /* SOFT_ASSEMBLER/SOFT_MACROASSEMBLER */
3464     int ifprint ;     /* TRUE = exécution inconditionnelle */
3465     int ifuppercase ; /* Pour création de fichiers Assembler
3466                        * TRUE  = Opérande supposée
3467                        * FALSE = Pas d'opérande */
3468     int (*prog)(void) ; /* Programme de traitement */
3469  } direct_table[] = {
3470     { "CALL"   , LABEL   , SOFT_MACROASSEMBLER, FALSE, TRUE , Ass_CALL   },
3471     { "ECHO"   , NO_LABEL, SOFT_MACROASSEMBLER, FALSE, FALSE, Ass_ECHO   },
3472     { "ELSE"   , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , FALSE, Ass_ELSE   },
3473     { "END"    , NO_LABEL, SOFT_ASSEMBLER     , FALSE, TRUE , Ass_END    },
3474     { "ENDC"   , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , FALSE, Ass_ENDC   },
3475     { "ENDM"   , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , FALSE, Ass_ENDM   },
3476     { "EQU"    , A_LABEL , SOFT_ASSEMBLER     , FALSE, TRUE , Ass_EQU    },
3477     { "FCB"    , LABEL   , SOFT_ASSEMBLER     , FALSE, TRUE , Ass_FCB    },
3478     { "FCC"    , LABEL   , SOFT_ASSEMBLER     , FALSE, FALSE, Ass_FCC    },
3479     { "FCN"    , LABEL   , SOFT_MACROASSEMBLER, FALSE, FALSE, Ass_FCN    },
3480     { "FCS"    , LABEL   , SOFT_MACROASSEMBLER, FALSE, FALSE, Ass_FCS    },
3481     { "FDB"    , LABEL   , SOFT_ASSEMBLER     , FALSE, TRUE , Ass_FDB    },
3482     { "GOTO"   , LABEL   , SOFT_MACROASSEMBLER, FALSE, TRUE , Ass_GOTO   },
3483     { "IF"     , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , TRUE , Ass_IF     },
3484     { "IFEQ"   , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , TRUE , Ass_IFEQ   },
3485     { "IFGE"   , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , TRUE , Ass_IFGE   },
3486     { "IFGT"   , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , TRUE , Ass_IFGT   },
3487     { "IFLE"   , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , TRUE , Ass_IFLE   },
3488     { "IFLT"   , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , TRUE , Ass_IFLT   },
3489     { "IFNE"   , NO_LABEL, SOFT_MACROASSEMBLER, TRUE , TRUE , Ass_IFNE   },
3490     { "INCBIN" , NO_LABEL, SOFT_MACROASSEMBLER, FALSE, FALSE, Ass_INCBIN },
3491     { "INCDAT" , NO_LABEL, SOFT_MACROASSEMBLER, FALSE, FALSE, Ass_INCDAT },
3492     { "INCLUD" , NO_LABEL, SOFT_ASSEMBLER     , FALSE, FALSE, Ass_INCLUD },
3493     { "MACRO"  , A_LABEL , SOFT_MACROASSEMBLER, TRUE , FALSE, Ass_MACRO  },
3494     { "OPT"    , NO_LABEL, SOFT_MACROASSEMBLER, FALSE, TRUE , Ass_OPT    },
3495     { "ORG"    , NO_LABEL, SOFT_ASSEMBLER     , FALSE, TRUE , Ass_ORG    },
3496     { "PAGE"   , NO_LABEL, SOFT_ASSEMBLER     , FALSE, FALSE, Ass_PAGE   },
3497     { "PRINT"  , NO_LABEL, SOFT_MACROASSEMBLER, FALSE, FALSE, Ass_PRINT  },
3498     { "RMB"    , LABEL   , SOFT_ASSEMBLER     , FALSE, TRUE , Ass_RMB    },
3499     { "RMD"    , LABEL   , SOFT_MACROASSEMBLER, FALSE, TRUE , Ass_RMD    },
3500     { "SET"    , A_LABEL , SOFT_ASSEMBLER     , FALSE, TRUE , Ass_SET    },
3501     { "SETDP"  , NO_LABEL, SOFT_ASSEMBLER     , FALSE, TRUE , Ass_SETDP  },
3502     { "STOP"   , LABEL   , SOFT_MACROASSEMBLER, FALSE, FALSE, Ass_STOP   },
3503     { "TITLE"  , NO_LABEL, SOFT_ASSEMBLER     , FALSE, FALSE, Ass_TITLE  }
3504};
3505#define DTSIZE (int)sizeof(direct_table)/(int)sizeof(direct_table[0])
3506
3507/*
3508 * Vérifie si le nom de macro est réservé
3509 */
3510int CheckIfReservedName(void)
3511{
3512    int i ;
3513    char macrname[ARG_MAX_SIZE+2] ;
3514
3515    macrname[0] = '\0' ;
3516    strcat(macrname,labelname) ;
3517    upper_string(macrname) ;
3518
3519    /* Vérifie si le nom de macro est celui d'une instruction */
3520    for(i=0;i<ITSIZE;i++)
3521        if (!strcmp(inst_table[i].name,macrname))
3522            return PrintError(ERR_BAD_MACRO_NAME) ;
3523
3524    /* Vérifie si le nom de macro est celui d'une directive */
3525    for(i=0;i<DTSIZE;i++)
3526        if (!strcmp(direct_table[i].name,macrname))
3527            return PrintError(ERR_BAD_MACRO_NAME) ;
3528
3529    return NO_ERROR ;
3530}
3531
3532
3533/***********************************************************************
3534 *
3535 * Assemblage de la ligne de code
3536 *
3537 ***********************************************************************/
3538
3539/*
3540 * Passe les espaces
3541 */
3542void SkipSpaces(void)
3543{
3544    while(*line == 0x20)
3545        line++ ;
3546}
3547
3548/*
3549 * Initialise le chaînage des arguments de macros
3550 */
3551void InitMacroArgChain(void)
3552{
3553    int i ;
3554    current_macroarg = malloc(sizeof(struct MACROARGLIST)) ;
3555    current_macroarg->prev = NULL ;
3556    for(i=0;i<10;i++) current_macroarg->arg[i] = NULL ;
3557}
3558
3559/*
3560 * Libère la mémoire pour le chaînage des arguments de macros
3561 */
3562void FreeMacroArgChain(void)
3563{
3564    struct MACROARGLIST *last_macroarg ;
3565    while((last_macroarg = current_macroarg))
3566    {
3567        current_macroarg = current_macroarg->prev ;
3568        free(last_macroarg) ;
3569    }
3570}
3571
3572/*
3573 * Assemble la ligne
3574 */
3575int AssembleLine(void)
3576{
3577    struct MACROARGLIST *prev_macroarg ;
3578    struct INCLIST *prev_includ = NULL ;
3579    int i ;
3580    int done = FALSE ;
3581    int label = FALSE ;
3582    char macroname[ARG_MAX_SIZE+2] ;
3583    char argname[ARG_MAX_SIZE+2] ;
3584    char ll[LINE_MAX_SIZE+2] ;
3585    int argn ;
3586    int error = NO_ERROR ;
3587
3588    run.size = 0 ;
3589    info.cycle.count = -1 ;
3590    info.cycle.plus  = -1 ;
3591
3592    /* Retour éventuel d'includ */
3593    if ((first_includ->count != 0)
3594     && (source == first_includ->end))
3595    {
3596        prev_includ = first_includ->prev ;
3597        free(first_includ) ;
3598        first_includ = prev_includ ;
3599        run.line = first_includ->line ;
3600        source = first_includ->start ;
3601    }
3602
3603    GetLine() ;
3604
3605    if (*line == '\0') return RecordLine(PRINT_EMPTY) ;
3606
3607    /*
3608     * Traitement du marquage
3609     */
3610    if ((*line == '(') && (run.pass == PASS2))
3611    {
3612        line++ ;
3613        ScanLine() ;
3614        if (!strcmp(arg,"info"))
3615        {
3616            fprintf(fp_lst,"----------------\n") ;
3617            fprintf(fp_lst,"%d cycle(s)\n",info.cycle.total) ;
3618            fprintf(fp_lst,"%d byte(s)\n",info.size) ;
3619            fprintf(fp_lst,"----------------\n") ;
3620            info.cycle.total = 0 ;
3621            info.size = 0 ;
3622        }
3623        else
3624        if (!strcmp(arg,"check"))
3625        {
3626            line++ ;
3627            SkipSpaces() ;
3628            if(*line == '\0')
3629            {
3630                check[0][0] = 0 ; /* Cycles limite */
3631                check[0][1] = 0 ; /* Cycles */
3632                check[1][0] = 0 ; /* Taille limite */
3633                check[1][1] = 0 ; /* Taille */
3634            }
3635            else
3636            {
3637                i = 0 ;
3638                while ((*line > 0x20) && (i < 2))
3639                {
3640                    if ((*line != ',')
3641                     && (*line > 0x20))
3642                    {
3643                        if (Eval() != NO_ERROR) return ERR_ERROR ;
3644                        check[i][0] = eval.operand ;
3645                        if ((check[i][0] != 0)
3646                         && (check[i][0] != check[i][1]))
3647                        {
3648                            PrintError(ERR_CHECK_ERROR) ;
3649                            printf("Check[%d,%d]\n",check[0][1],check[1][1]) ;
3650                            fprintf(fp_lst,"Check [%d,%d]\n",check[0][1],check[1][1]) ;
3651                        }
3652                    }
3653                    if (*line == ',') line++ ;
3654                }
3655                check[0][1] = 0 ;
3656                check[1][1] = 0 ;
3657            }
3658        }
3659        return NO_ERROR ;
3660    }
3661
3662    /*
3663     * Reconstruction de la ligne si exécution de macro
3664     */
3665    if (macro.level)
3666    {
3667        i = 0 ;
3668        ll[0] = '\0' ;
3669        while (linebuffer[i] != 0)
3670        {
3671            if (linebuffer[i] == '\\')
3672            {
3673                i++ ;
3674                /* Récupère le numéro de l'argument de macro */
3675                if (is_numeric(linebuffer[i]) == FALSE)
3676                    return PrintError(ERR_MACRO_ERROR) ;
3677                argn = linebuffer[i++] - '0' ;
3678                /* Interprète l'argument de macro */
3679                prev_macroarg = current_macroarg ;
3680                while((prev_macroarg->arg[argn] != NULL)
3681                   && (prev_macroarg->arg[argn][0] == '\\'))
3682                {
3683                    if (prev_macroarg->prev == NULL)
3684                        return PrintError(ERR_MACRO_ERROR) ;
3685                    if (is_numeric(prev_macroarg->arg[argn][1]) == FALSE)
3686                        return PrintError(ERR_MACRO_ERROR) ;
3687                    argn = prev_macroarg->arg[argn][1] - '0' ;
3688                    prev_macroarg = prev_macroarg->prev ;
3689                }
3690                if (prev_macroarg->arg[argn] != NULL)
3691                    strcat(ll,prev_macroarg->arg[argn]) ;
3692            }
3693            else
3694                strncat(ll,&linebuffer[i++],1) ;
3695        }
3696        linebuffer[0] = '\0' ;
3697        strcat(linebuffer,ll) ;
3698    }
3699
3700    /*
3701     * Traitement étiquette/commentaire
3702     */
3703    if (*line != 0x20)
3704    {
3705        /* Traitement du slash de commentaire */
3706        if (*line == '/') {
3707            run.locked ^= COMMENT_LOCK ;
3708            return RecordLine(PRINT_NO_CODE) ; }
3709        /* Traitement de l'astérisque de commentaire */
3710        if ((*line == '*')
3711         || (run.locked & COMMENT_LOCK))
3712            return RecordLine(PRINT_NO_CODE) ;
3713        /* Lecture de l'étiquette */
3714        if (ScanLine() != ALPHA_CHAR)
3715            return PrintError(ERR_BAD_LABEL) ;
3716        if (((scan.soft == SOFT_ASSEMBLER) && ((int)strlen(arg) > 6))
3717         || ((scan.soft == SOFT_MACROASSEMBLER) && ((int)strlen(arg) > ARG_MAX_SIZE)))
3718            return PrintError(ERR_LABEL_NAME_TOO_LONG) ;
3719        labelname[0] = '\0' ;
3720        strcat(labelname,arg) ;
3721        if (scan.soft == SOFT_ASSEMBLER)
3722            upper_string(labelname) ;
3723        label = TRUE ;
3724    }
3725
3726    /*
3727     * Traitement étiquette sèche
3728     */
3729    SkipSpaces() ;
3730    if ((*line == '\0')
3731      || (*line == '*'))
3732    {
3733        if ((label == TRUE)
3734         && (run.pass > MACROPASS))
3735        {
3736            if (DoSymbol(labelname,run.pc,LABEL_VALUE) != NO_ERROR)
3737                return ERR_ERROR ;
3738            return RecordLine(PRINT_PC) ;
3739        }
3740        return RecordLine(PRINT_NO_CODE) ;
3741    }
3742
3743    /*
3744     * Récupération de l'instruction
3745     */
3746    if (ScanLine() != ALPHA_CHAR)
3747        return PrintError(ERR_BAD_OPCODE) ;
3748    SkipSpaces() ;
3749    macroname[0] = '\0' ;
3750    strcat(macroname,arg) ;
3751
3752    run.size = 0 ;
3753    run.code[0] = 0 ;
3754
3755    /* Traitement de l'instruction */
3756
3757    upper_string(arg) ;
3758    if (run.pass > MACROPASS)
3759    {
3760        i = 0 ;
3761        while((i<ITSIZE) && (done == FALSE))
3762        {
3763            if(!strcmp(inst_table[i].name,arg))
3764            {
3765                run.code[0] = inst_table[i].page ;
3766                run.code[1] = inst_table[i].code ;
3767                info.cycle.count = inst_table[i].cycles ;
3768                if (run.locked == UNLOCKED)
3769                {
3770                    if ((label == TRUE)
3771                     && (DoSymbol(labelname,run.pc,LABEL_VALUE) != NO_ERROR))
3772                        return ERR_ERROR ;
3773                    upper_string(arg) ;
3774                    error = (*inst_table[i].prog)() ;
3775                }
3776                else RecordLine(PRINT_NO_CODE) ;
3777                done = TRUE ;
3778            }
3779            i++ ;
3780        }
3781    }
3782
3783    /* Traitement de la directive */
3784
3785    if (done == FALSE)
3786    {
3787        i = 0 ;
3788        while((i<DTSIZE) && (done == FALSE))
3789        {
3790            if(!strcmp(direct_table[i].name,arg))
3791            {
3792                if ((scan.soft == SOFT_ASSEMBLER)
3793                 && (direct_table[i].soft != SOFT_ASSEMBLER))
3794                    return PrintError(ERR_BAD_OPCODE) ;
3795
3796                /* Au pass de macro, seules les directives
3797                 * MACRO et ENDM doivent passer
3798                 * Aux pass 1 et 2, seules les directives
3799                 * qui ne se trouvent ni dans une zone de
3800                 * commentaire, ni dans une déclaration de
3801                 * macro, ni dans un IF faux (sauf les
3802                 * directives de condition, etc...) doivent
3803                 * passer */
3804                if (((run.pass == MACROPASS)
3805                  && (strcmp(direct_table[i].name,"MACRO"))
3806                  && (strcmp(direct_table[i].name,"ENDM")))
3807                 || ((run.pass > MACROPASS)
3808                  && (run.locked)
3809                  && (direct_table[i].ifprint == FALSE)))
3810                    return RecordLine(PRINT_NO_CODE) ;
3811
3812                switch (direct_table[i].iflabel)
3813                {
3814                    case NO_LABEL :
3815                        if (label == TRUE)
3816                            return PrintError(ERR_ILLEGAL_LABEL) ;
3817                        break ;
3818                    case A_LABEL :
3819                        if (label == FALSE)
3820                            return PrintError(ERR_MISSING_LABEL) ;
3821                        break ;
3822                    case LABEL :
3823                        if ((label == TRUE)
3824                         && (DoSymbol(labelname,run.pc,LABEL_VALUE) != NO_ERROR))
3825                            return ERR_ERROR ;
3826                        break ;
3827                }
3828                error = (*direct_table[i].prog)() ;
3829                done = TRUE ;
3830            }
3831            i++ ;
3832        }
3833    }
3834
3835
3836    /* Traitement de la macro */
3837    if ((done == FALSE) && (run.pass > MACROPASS))
3838    {
3839        if (scan.soft == SOFT_ASSEMBLER)
3840            return PrintError(ERR_BAD_OPCODE) ;
3841        if (run.locked)
3842            return RecordLine(PRINT_NO_CODE) ;
3843        if (DoSymbol(macroname,0,READ_VALUE) != NO_ERROR)
3844            return ERR_ERROR ;
3845        if (eval.type != MACRO_VALUE)
3846            return PrintError(ERR_UNDEFINED_MACRO) ;
3847
3848        /* Limite le nombre d'imbrications */
3849        if ((macro.level == 8)
3850         && (scan.soft == SOFT_MACROASSEMBLER))
3851            return PrintError(ERR_MACRO_OUT_OF_RANGE) ;
3852        macro.level++ ;
3853
3854        /* Sauvegarde les arguments de macro */
3855        current_macroarg->line = run.line  ;
3856        current_macroarg->ptr = source ;
3857        prev_macroarg = current_macroarg ;
3858        current_macroarg = malloc(sizeof(struct MACROARGLIST)) ;
3859        current_macroarg->prev = prev_macroarg ;
3860        for(i=0;i<10;i++) current_macroarg->arg[i] = NULL ;
3861        if (*line != '\0')
3862        {
3863            i = 0 ;
3864            while ((*line != '\0')
3865                && (*line != ' ')
3866                && (i < 10))
3867            {
3868                if ((i) && (*(line++) != ','))
3869                    return PrintError(ERR_MACRO_ERROR) ;
3870                argname[0] = '\0' ;
3871                while((*line != '\0')
3872                   && (*line != ' ')
3873                   && (*line != ','))
3874                    strncat(argname,line++,1) ;
3875                current_macroarg->arg[i] = malloc(strlen(argname)+1) ;
3876                current_macroarg->arg[i][0] = '\0' ;
3877                strcat(current_macroarg->arg[i],argname) ;
3878                i++ ;
3879            }
3880        }
3881        /* Recherche la macro dans la liste */
3882        current_macro = first_macro ;
3883        while(current_macro->count != (unsigned short)eval.operand)
3884            current_macro = current_macro->next ;
3885        /* Lance l'exécution de la macro */
3886        source = current_macro->start ;
3887        run.line = current_macro->line ;
3888    }
3889
3890    /* Effectue le total des cycles */
3891    if (info.cycle.count != -1)
3892    {
3893        info.cycle.total += info.cycle.count ;
3894        check[0][1] += info.cycle.count ;
3895    }
3896    if (info.cycle.plus  != -1)
3897    {
3898        info.cycle.total += info.cycle.plus  ;
3899        check[0][1] += info.cycle.plus ;
3900    }
3901
3902    /* Sauvegarde des octets de code */
3903    if ((run.size != 0) && (error == NO_ERROR))
3904    {
3905        if(run.code[0])
3906            SaveBinChar(run.code[0]) ;
3907        for(i=0;i<run.size;i++)
3908            SaveBinChar(run.code[i+1]) ;
3909    }
3910
3911    return NO_ERROR ;
3912}
3913
3914
3915
3916
3917/***********************************************************************
3918 *
3919 * Chargement et traitement du fichier source
3920 *
3921 ***********************************************************************/
3922
3923enum{
3924    NO_MARK,
3925    MAIN_MARK,
3926    INFO_MARK,
3927    CHECK_MARK,
3928    INCLUDE_MARK
3929} ;
3930
3931const struct {
3932    char name[8] ; /* Nom du marquage */
3933    int type ;      /* Type du marquage */
3934  } mark[] = {
3935      { "main"   , MAIN_MARK    },
3936      { "info"   , INFO_MARK    },
3937      { "check"  , CHECK_MARK   },
3938      { "include", INCLUDE_MARK }
3939} ;
3940#define MTSIZE  (int)sizeof(mark)/(int)sizeof(mark[0])
3941
3942struct {
3943    int status ;  /* TRUE = création des fichiers ASM */
3944    int comment ; /* Flag de passage d'un '/' de commentaire */
3945    int top ;     /* Compteur de lignes vides de début de source */
3946    int bottom ;  /* Compteur de lignes vides de fin de source */
3947} create ;
3948
3949
3950/*
3951 * Initialise le chaînage des sources
3952 */
3953void InitSourceChain(void)
3954{
3955    first_source = malloc(sizeof(struct SRCLIST)) ;
3956    first_source->next = NULL ;
3957    first_source->start = NULL ;
3958}
3959
3960
3961/*
3962 * Libère la mémoire pour le chaînage des sources
3963 */
3964void FreeSourceChain(void)
3965{
3966    while((current_source = first_source))
3967    {
3968        first_source = first_source->next ;
3969        free(current_source) ;
3970    }
3971}
3972
3973
3974/*
3975 * Ferme le fichier ASM courant
3976 */
3977void CloseASM(void)
3978{
3979    if (fp_asm != NULL)
3980        fclose(fp_asm) ;
3981}
3982
3983
3984int RecordSourceChainIf(void)
3985{
3986    int i = 0 ;
3987    int accent ;
3988    int markflag = NO_MARK ;
3989    struct SRCLIST *next_source ;
3990    char crunchedline[ARG_MAX_SIZE+2] ;
3991    char *p = line ;
3992    unsigned char c = '\0' ;
3993    int spaces = 0 ;
3994
3995    int done = FALSE ;
3996    int flag = FALSE ;
3997    int csize = 0 ;
3998
3999    /*
4000     * Crée la ligne au format ASM
4001     */
4002    if (*line != '(')
4003    {
4004        while((*line != '\0') && ((line - p) < COLON_40))
4005        {
4006            /* Filtre les caractères */
4007            switch(c = (unsigned char)*(line++))
4008            {
4009                case CHAR127 : c = 0x7F ; break ;
4010                case 0x20 :
4011                    spaces++ ;
4012                    while(*line == 0x20)
4013                    {
4014                        spaces++ ;
4015                        line++ ;
4016                    }
4017                    break ;
4018                default :
4019                    if (c > 0x7F)
4020                    {
4021                        accent = 0 ;
4022                        while((accent<16) && (c != acc_table[accent])) accent++ ;
4023                        if (accent == 16) c = '?' ; else c = 0x80 + accent ;
4024                    }
4025                    break ;
4026            }
4027            /* Ajoute un caractère si valide */
4028            if (c > 0x20)
4029            {
4030                /* Ajoute les lignes vides préalables */
4031                if (create.top)
4032                {
4033                    while(create.bottom > 0)
4034                    {
4035                        if ((fp_asm != NULL) && (create.status == TRUE))
4036                            fputc(0x0D,fp_asm) ;
4037                        current_source->asm_size += create.bottom * 3 ;
4038                        create.bottom-- ;
4039                    }
4040                }
4041                create.bottom = 0 ;
4042
4043                /* Ajoute les espaces préalables */
4044                while (spaces >= 15)
4045                {
4046                    crunchedline[csize++] = (char)0xFF ;
4047                    spaces -= 15 ;
4048                }
4049                if (spaces) crunchedline[csize++] = spaces | 0xF0 ;
4050                spaces = 0 ;
4051
4052                /* Ajoute le caractère */
4053                crunchedline[csize++] = c ;
4054            }
4055        }
4056        crunchedline[csize++] = 0x0D ;
4057        if (crunchedline[0] != 0x0D) create.top = 1 ;
4058            else if (create.top) create.bottom++ ;
4059        if ((create.top != 0) && (create.bottom == 0))
4060        {
4061            current_source->asm_size += 3 + csize - 1 ;
4062
4063            /*
4064             * Capitalise les lettres si compatibilité Assembler demandée
4065             */
4066
4067            if ((scan.soft == SOFT_ASSEMBLER)
4068             && (create.status == TRUE))
4069            {
4070                line = &crunchedline[0] ;
4071                /* Traitement de l'étiquette */
4072                if (*line == '/') create.comment ^= COMMENT_LOCK ;
4073                else
4074                if ((create.comment == 0)
4075                 && (*line != '\0')
4076                 && (*line != '*')
4077                 && (*line != '/'))
4078                {
4079                    while (((unsigned char)*line <= 0xF0) && (*line != 0x0D))
4080                    {
4081                        *(line) = upper_case((unsigned char)*(line)) ;
4082                        line++ ;
4083                    }
4084                    while ((unsigned char)*line > 0xF0) line++ ;
4085
4086                    /* Traitement de l'instruction/directive/macro */
4087                    if ((*line != 0x0D) && (*line != '*'))
4088                    {
4089                        i = 0 ;
4090                        while (((unsigned char)*line <= 0xF0) && (*line != 0x0D))
4091                        {
4092                           *line = upper_case(*line) ;
4093                           arg[i++] = *(line++) ;
4094                        }
4095                        arg[i] = '\0' ;
4096                        while ((unsigned char)*line > 0xF0) line++ ;
4097
4098                        if (*line != 0x0D)
4099                        {
4100                            /* Recherche si opérande pour instruction */
4101                            upper_string(arg) ;
4102                            i = 0 ;
4103                            while((i<ITSIZE) && (done == FALSE))
4104                            {
4105                                if(!strcmp(inst_table[i].name,arg))
4106                                {
4107                                    flag = inst_table[i].ifuppercase ;
4108                                    done = TRUE ;
4109                                }
4110                                i++ ;
4111                            }
4112
4113                            /* Recherche si opérande pour directive */
4114                            i = 0 ;
4115                            while((i<DTSIZE) && (done == FALSE))
4116                            {
4117                                if(!strcmp(direct_table[i].name,arg))
4118                                {
4119                                    flag = direct_table[i].ifuppercase ;
4120                                    done = TRUE ;
4121                                }
4122                                i++ ;
4123                            }
4124
4125                            /* Traitement de l'opérande éventuelle */
4126                            if ((done == TRUE) && (flag == TRUE))
4127                            {
4128                                while (((unsigned char)*line < 0xF0) && (*line != 0x0D))
4129                                {
4130                                    if ((*line == '\'')
4131                                     && (*(line + 1) != 0x0D))
4132                                        line++ ;
4133                                    else
4134                                        *line = upper_case((unsigned char)*line) ;
4135                                    line++ ;
4136                                }
4137                            }
4138                        }
4139                    }
4140                }
4141            }
4142
4143            /*
4144             * Sauvegarde éventuellement la ligne au format ASM
4145             */
4146
4147            if ((fp_asm != NULL)
4148             && (create.status == TRUE))
4149                fwrite(crunchedline,sizeof(char),csize,fp_asm) ;
4150        }
4151        return NO_ERROR ;
4152    }
4153
4154    /* Vérifie la validité du marquage */
4155    line++ ;
4156    if (ScanLine() != ALPHA_CHAR)
4157        return PrintError(ERR_WRONG_MARK) ;
4158    for(i=0;i<MTSIZE;i++)
4159        if (!strcmp(arg,mark[i].name))
4160            markflag = mark[i].type ;
4161    if (markflag == NO_MARK)
4162        return PrintError(ERR_WRONG_MARK) ;
4163    if(*(line++) != ')')
4164        return PrintError(ERR_WRONG_MARK) ;
4165
4166    /* Traite le marquage */
4167    switch(markflag)
4168    {
4169        case MAIN_MARK :
4170        case INCLUDE_MARK :
4171            CloseASM() ;
4172            SkipSpaces() ;
4173            if (GetDescriptor("ASM") != NO_ERROR)
4174                return ERR_ERROR ;
4175            /* Vérifie l'unicité du nom de source */
4176            next_source = first_source ;
4177            do {
4178                current_source = next_source ;
4179                if (!strcmp(current_source->name,desc.name))
4180                    return PrintError(ERR_DUPLICATE_NAME) ;
4181            } while((next_source = next_source->next) != NULL) ;
4182
4183            /* Enregistre la déclaration */
4184            switch(markflag)
4185            {
4186                case MAIN_MARK :
4187                    /* Met à jour le 'main' */
4188                    current_source = first_source ;
4189                    if (current_source->start != NULL)
4190                        return PrintError(ERR_DUPLICATE_MAIN) ;
4191                    break ;
4192                case INCLUDE_MARK :
4193                    /* Chaîne l'include */
4194                    current_source->next = malloc(sizeof(struct SRCLIST)) ;
4195                    current_source = current_source->next ;
4196                    current_source->next = NULL ;
4197                    break ;
4198            }
4199            /* Enregistre les paramètres de l'include */
4200            current_source->drive = desc.drive ;
4201            current_source->name[0] = '\0' ;
4202            strcat(current_source->name,desc.name) ;
4203            current_source->line = run.line ;
4204            current_source->start = source ;
4205            current_source->asm_size = 0 ;
4206            create.top = 0 ;
4207            create.bottom = 0 ;
4208            create.comment = 0 ;
4209            /* Ouvre le fichier suivant */
4210            if (create.status == TRUE)
4211                fp_asm = fopen(current_source->name,"wb") ;
4212            break ;
4213    }
4214    return NO_ERROR ;
4215}
4216
4217
4218/*
4219 * Chargement du fichier source
4220 */
4221int LoadFile(char *name)
4222{
4223    FILE *fp_file ;
4224
4225    int fsize = 1 ;
4226    int error ;
4227
4228    if (!(fp_file = fopen(name,"rb")))
4229    {
4230        printf("*** Impossible d'ouvrir '%s'\n",name) ;
4231        return ERR_ERROR ;
4232    }
4233    fseek(fp_file, 0, SEEK_END) ;
4234    fsize = ftell(fp_file) ;
4235    fclose(fp_file) ;
4236    filebuffer = malloc(fsize+1) ;
4237    fp_file = fopen(name,"rb") ;
4238    fread(filebuffer, sizeof(char), fsize, fp_file) ;
4239    fclose(fp_file) ;
4240    filebuffer[fsize] = '\0' ;
4241
4242    run.line = 0 ;
4243    source = filebuffer ;
4244    current_source = first_source ;
4245    while (source < filebuffer+fsize)
4246    {
4247        /* Sauve le pointeur de fin du source précédent */
4248        current_source->end = source ;
4249       
4250        /* Récupère la ligne */
4251        if ((error = GetLine()) != NO_ERROR)
4252            return PrintError(error) ;
4253        RecordSourceChainIf() ;
4254    }
4255    CloseASM() ;
4256    current_source->end = source ;
4257    if (first_source->start == NULL)
4258        return PrintError(ERR_MISSING_MAIN) ;
4259
4260    return NO_ERROR ;
4261}
4262
4263
4264/*
4265 * Assemble le source
4266 */
4267void AssembleSource(int pass)
4268{
4269    int i = 0 ;
4270
4271    const struct {
4272        char string[11] ; /* Message de pass */
4273        int type ;        /* Code de pass */
4274    } PassTable[3] = {
4275        { "Macro Pass", MACROPASS },
4276        { "Pass1"     , PASS1     },
4277        { "Pass2"     , PASS2     },
4278    } ;
4279
4280    /* Notifie le pass d'assemblage */
4281    run.pass = pass ;
4282    if ((run.pass == MACROPASS)
4283     && (scan.soft == SOFT_ASSEMBLER))
4284        return ;
4285    while(PassTable[i].type != run.pass) i++ ;
4286    fprintf(fp_lst,"%s\n", PassTable[i].string) ;
4287    printf("%s\n", PassTable[i].string) ;
4288
4289    /* Initialise les variables d'assemblage */
4290    run.exit  = FALSE ;
4291    macro.count  = 0 ;
4292    run.dp    = 0x00 ;
4293    run.pc    = 0x0000 ;
4294    run.exec  = 0x0000 ;
4295    ifc.count = 0 ;
4296    ifc.buf[0]  = IF_TRUE ;
4297    run.locked = UNLOCKED ;
4298    info.cycle.total = 0 ;
4299    info.size = 0 ;
4300    check[0][0] = 0 ;
4301    check[0][1] = 0 ;
4302    check[1][0] = 0 ;
4303    check[1][1] = 0 ;
4304    macro.level = 0 ;
4305    memcpy(&run.opt, &scan.opt, sizeof(run.opt)) ;
4306
4307    /* Initialise les listes d'includes/arguments de macros */
4308    InitIncludChain() ;
4309    InitMacroArgChain() ;
4310
4311    /* Assemble les lignes des sources */
4312    source   = first_source->start ;
4313    run.line = first_source->line ;
4314    while((run.exit == FALSE)
4315       && (source != first_source->end))
4316        AssembleLine() ;
4317
4318    /* Erreur si macro en cours */
4319    if (run.locked & MACRO_LOCK)
4320        PrintError(ERR_MISSING_ENDM) ;
4321    /* Erreur si commentaire en cours */
4322    if (run.locked & COMMENT_LOCK)
4323        PrintError(ERR_MISSING_SLASH) ;
4324    /* Traite les erreurs si pas END */
4325    if (run.exit == FALSE)
4326    {
4327        /* Erreur si assemblage conditionnel en cours */
4328        if (ifc.count != 0)
4329            PrintError(ERR_MISSING_ENDC) ;
4330        /* Erreur si ASSEMBLER et pas 'END' */
4331        if (scan.soft == SOFT_ASSEMBLER)
4332            PrintError(ERR_MISSING_END_STATEMENT) ;
4333    }
4334    /* Libère les listes d'includes/arguments de macros */
4335    FreeIncludChain() ;
4336    FreeMacroArgChain() ;
4337}
4338
4339
4340
4341/***********************************************************************
4342 *
4343 * Programme principal
4344 *
4345 ***********************************************************************/
4346
4347/*
4348 * Vérifie si pas de dépassement de capacité de l'ASM
4349 */
4350void CheckSourceSize(int size, char *name)
4351{
4352    if (size > 29000)
4353    {
4354        fprintf(fp_lst,"*** Le fichier '%s' pourrait être trop grand pour être chargé\n", name) ;
4355        printf("*** Le fichier '%s' pourrait etre trop grand pour etre charge\n", name) ;
4356    }
4357}
4358
4359/*
4360 * Enregistre l'en-tête de listing
4361 */
4362void PrintListHeader(char *fload, char *fsave)
4363{
4364    struct SRCLIST *current_source ;
4365    fprintf(fp_lst,"/*--------------------------------------------------------------*\n") ;
4366    fprintf(fp_lst," * Compilé avec C6809 v0.83                                     *\n") ;
4367    fprintf(fp_lst," *--------------------------------------------------------------*\n") ;
4368    fprintf(fp_lst," * Fichier source      : %s\n",fload) ;
4369    fprintf(fp_lst," * Fichier destination : %s\n",fsave) ;
4370    fprintf(fp_lst," * Contenu :\n") ;
4371    CheckSourceSize(first_source->asm_size, first_source->name) ;
4372    fprintf(fp_lst," *     Main     %1d:%-12s %d\n",
4373                               first_source->drive,
4374                               first_source->name,
4375                               first_source->asm_size) ;
4376    current_source = first_source ;
4377    if ((current_source = current_source->next) != NULL)
4378    {
4379        do {
4380            CheckSourceSize(current_source->asm_size, current_source->name) ;
4381            fprintf(fp_lst," *     Include  %1d:%-12s %d\n",
4382                               current_source->drive,
4383                               current_source->name,
4384                               current_source->asm_size) ;
4385        } while((current_source = current_source->next) != NULL) ;
4386    }
4387    fprintf(fp_lst," *--------------------------------------------------------------*/\n") ;
4388    fprintf(fp_lst,"\n") ;
4389}
4390
4391/*
4392 * Referme toutes les déclarations
4393 */
4394int CloseAll(void)
4395{
4396    /* Libération des mémoires */
4397    FreeErrorChain() ;   /* Erreurs  */
4398    FreeSymbolChain() ;  /* Symboles */
4399    FreeSourceChain() ;  /* Sources  */
4400    FreeMacroChain() ;   /* Macros   */
4401
4402    /* Fermeture des fichiers */
4403    fclose(fp_lst) ;
4404    return 0 ;
4405}
4406
4407
4408/*
4409 * Affichage de l'aide
4410 */
4411void PrintHelp(void)
4412{
4413    printf("\n") ;
4414    printf("Compilateur Macro/Assembler-like\n") ;
4415    printf("  Francois MOURET (c) C6809 v 0.83 - mars 2010\n") ;
4416    printf("\n") ;
4417    printf("C6809 [options] fichier_source fichier_destination\n") ;
4418    printf("\n") ;
4419    printf("  options :\n") ;
4420    printf("  -h  aide de ce programme\n") ;
4421    printf("  -o  option(s) d'assemblage (NO, OP, SS, WE, WL et WS)\n") ;
4422    printf("      les parametres d'option (tous desactives par defaut) doivent\n") ;
4423    printf("      etre separes par des '/'\n") ;
4424    printf("  -b  type de la sortie (binaire non lineaire par defaut)\n") ;
4425    printf("      l  binaire lineaire\n") ;
4426    printf("      h  binaire hybride\n") ;
4427    printf("      d  donnee\n") ;
4428    printf("  -d  passage d'argument (<symbole>=<valeur>)\n") ;
4429    printf("  -c  cree les fichiers ASM au format Thomson\n") ;
4430    printf("  -q  notifie le depassement de 40 caracteres par ligne (300 par defaut)\n") ;
4431    printf("  -e  groupe les messages d'erreur du listing (ordre de ligne par defaut)\n") ;
4432    printf("  -s  ordre d'affichage des symboles du listing (alphabetique par defaut)\n") ;
4433    printf("      e  par erreur de symbole\n") ;
4434    printf("      t  par type de symbole\n") ;
4435    printf("      n  par frequence d'utilisation\n") ;
4436    printf("  -a  Notifie la compatibilite (assembleur virtuel par defaut)\n") ;
4437    printf("      a  ASSEMBLER1.0 et ASSEMBLER 2.0\n") ;
4438    printf("      m  MACROASSEMBLER 3.6\n") ;
4439    printf("  -m  + TO/TO7/MO machine de travail (TO par defaut)\n") ;
4440    exit(CloseAll()) ;
4441}
4442
4443/*
4444 * Affichage de l'erreur et du conseil
4445 */
4446void PrintAdvice(char *argument, char *errorstring)
4447{
4448    printf("*** %s : %s\n", argument, errorstring) ;
4449    printf("Taper 'C6809 -h' pour afficher l'aide\n") ;
4450    exit(CloseAll()) ;
4451}
4452
4453
4454
4455/*
4456 * Programme principal
4457 */
4458int main(int argc, char *argv[])
4459{
4460    int i ;
4461    int fcount = 0 ;
4462    char label[ARG_MAX_SIZE+2] = "";
4463    char my_argv[ARGV_MAX_SIZE] = "";
4464    char fload[ARGV_MAX_SIZE] = "";
4465    char fsave[ARGV_MAX_SIZE] = "";
4466    int argp ;
4467
4468    const struct {
4469        char name[4] ; /* Nom de l'option */
4470        int type ;     /* Code de l'option */
4471      } Computer[3] = {
4472            { "TO" , TO_COMPUTER  },
4473            { "TO7", TO7_COMPUTER },
4474            { "MO" , MO_COMPUTER  }
4475    } ;
4476
4477   /*
4478    * Initialisation du programme
4479    */
4480    memset(&bin, 0, sizeof(bin)) ;
4481     bin.type = BIN_FILE ;
4482    memset(&run, 0, sizeof(run)) ;
4483     run.pass        = SCANPASS ;
4484     run.opt[OPT_NO] = FALSE ;
4485     run.opt[OPT_OP] = FALSE ;
4486     run.opt[OPT_SS] = FALSE ;
4487     run.opt[OPT_WE] = FALSE ;
4488     run.opt[OPT_WL] = FALSE ;
4489     run.opt[OPT_WS] = FALSE ;
4490    memset(&scan, 0, sizeof(scan)) ;
4491     scan.computer   = TO_COMPUTER ;
4492     scan.soft       = SOFT_UPDATE ;
4493     scan.symb_order = INITIAL_ORDER ;
4494     scan.err_order  = INITIAL_ORDER ;
4495     scan.limit      = COLON_300 ;
4496     scan.opt[OPT_NO] = FALSE ;
4497     scan.opt[OPT_OP] = FALSE ;
4498     scan.opt[OPT_SS] = FALSE ;
4499     scan.opt[OPT_WE] = FALSE ;
4500     scan.opt[OPT_WL] = FALSE ;
4501     scan.opt[OPT_WS] = FALSE ;
4502    memset(&macro, 0, sizeof(macro)) ;
4503    memset(&create, 0, sizeof(create)) ;
4504     create.status  = FALSE ;
4505     create.comment = 0 ;
4506
4507    /*
4508     * Ouverture du fichier de liste
4509     */
4510    if ((fp_lst = fopen("codes.lst","w")) == NULL) {
4511        printf("*** Impossible d'ouvrir le fichier 'codes.lst'\n") ;
4512        return 0 ; }
4513
4514    /* Initialisation des listes */
4515    InitErrorChain() ;   /* Erreurs  */
4516    InitSymbolChain() ;  /* Symboles */
4517    InitSourceChain() ;  /* Sources  */
4518    InitMacroChain() ;   /* Macros   */
4519
4520   /*
4521    * Traitement des arguments de lancement
4522    */
4523    if(argc < 2) PrintHelp() ;
4524
4525    for(argp=1; argp<argc; argp++)
4526    {
4527        snprintf (my_argv, (strlen(argv[argp])+1 > (size_t)ARGV_MAX_SIZE)
4528                               ? (size_t)ARGV_MAX_SIZE : strlen(argv[argp])+1,
4529                           "%s", argv[argp]);
4530        my_argv[(int)strlen(my_argv)] = '\0';
4531        for (i=(int)strlen(my_argv); i>=0; i--)
4532             if (my_argv[i] <= 0x20)
4533                 my_argv[i] = '\0';
4534             else break;
4535             
4536        if (my_argv[0] == '-')
4537        {
4538            switch ((int)strlen(my_argv))
4539            {
4540                case 2 :
4541                    switch(my_argv[1])
4542                    {
4543                        case 'h' : PrintHelp() ; break ;
4544                        case 'c' : create.status  = TRUE        ; break ;
4545                        case 'q' : scan.limit     = COLON_40    ; break ;
4546                        case 'e' : scan.err_order = ERROR_ORDER ; break ;
4547                        case 'd' :
4548                        case 'a' :
4549                        case 'b' :
4550                        case 's' :
4551                        case 'o' :
4552                            PrintAdvice (my_argv, "Option incomplete") ;
4553                            break ;
4554                        default :
4555                            PrintAdvice (my_argv, "Option inconnue") ;
4556                            break ;
4557                    }
4558                    break ;
4559                case 3 :
4560                    switch(my_argv[1])
4561                    {
4562                        case 'b' :
4563                            switch(my_argv[2])
4564                            {
4565                                case 'l' : bin.type = LINEAR_FILE ; break ;
4566                                case 'd' : bin.type = DATA_FILE   ; break ;
4567                                case 'h' : bin.type = HYBRID_FILE ; break ;
4568                                case 's' : break ;
4569                                default :
4570                                    PrintAdvice(my_argv, "Parametre d'option inconnu") ;
4571                                    break ;
4572                            }
4573                            break ;
4574                        case 's' :
4575                            switch(my_argv[2])
4576                            {
4577                                case 'e' : scan.symb_order = ERROR_ORDER ; break ;
4578                                case 't' : scan.symb_order = TYPE_ORDER  ; break ;
4579                                case 'n' : scan.symb_order = TIME_ORDER  ; break ;
4580                                default :
4581                                    PrintAdvice(my_argv,"Parametre d'option inconnu") ;
4582                                    break ;
4583                            }
4584                            break ;
4585                        case 'a' :
4586                            switch(my_argv[2])
4587                            {
4588                                case 'a' : scan.soft = SOFT_ASSEMBLER      ; break ;
4589                                case 'm' : scan.soft = SOFT_MACROASSEMBLER ; break ;
4590                                default :
4591                                    PrintAdvice (my_argv, "Parametre d'option inconnu") ;
4592                                    break ;
4593                            }
4594                            break ;
4595                             
4596                        default :
4597                            PrintAdvice (my_argv, "Option inconnue") ;
4598                            break ;
4599                    }
4600                    break ;
4601                default :
4602                    switch(my_argv[1])
4603                    {
4604                        case 'o' :
4605                            line = &my_argv[2] ;
4606                            Ass_OPT() ;
4607                            memcpy(&scan.opt, &run.opt, sizeof(run.opt)) ;
4608                            break ;
4609                        case 'm' :
4610                            upper_string(&my_argv[2]) ;
4611                            i = 0 ;
4612                            while((i<3) && (!strcmp(&my_argv[2],Computer[i].name))) i++ ;
4613                            if (i == 3)
4614                                PrintAdvice (my_argv, "Parametre d'option inconnu") ;
4615                            else scan.computer = Computer[i].type ;
4616                            break ;
4617                        case 'd' :
4618                            i = ERR_ERROR ;
4619                            line = &my_argv[2] ;
4620                            if (ScanLine() == ALPHA_CHAR)
4621                            {
4622                                label[0] = '\0' ;
4623                                strcat(label,arg) ;
4624                                if ((ScanLine() == SIGN_CHAR)
4625                                 && (arg[0] == '='))
4626                                {
4627                                    if (Eval() == NO_ERROR)
4628                                    {
4629                                        run.pass = PASS1 ;
4630                                        i = DoSymbol(label,eval.operand,ARG_VALUE) ;
4631                                        run.pass = SCANPASS ;
4632                                    }
4633                                }
4634                            }
4635                            if (i != NO_ERROR) PrintAdvice (my_argv, "Erreur de parametrage") ;
4636                            break ;
4637                        default :
4638                            PrintAdvice (my_argv, "Option inconnue") ;
4639                            break ;
4640                    }
4641                    break ;
4642            }
4643        }
4644        else
4645        {
4646            switch(fcount)
4647            {
4648                case 0 : snprintf (fload, ARGV_MAX_SIZE, "%s", my_argv); break ;
4649                case 1 : snprintf (fsave, ARGV_MAX_SIZE, "%s", my_argv); break ;
4650                default :
4651                    PrintAdvice (my_argv, "Argument excedentaire") ;
4652                    break ;
4653            }
4654            fcount++ ;
4655        }
4656    }
4657
4658    /*
4659     * Vérification des arguments de lancement
4660     */
4661    if (fload == NULL) PrintAdvice(fload,"Fichier source manquant") ;
4662    if (fsave == NULL) PrintAdvice(fsave,"Fichier destination manquant") ;
4663    if(!strchr(fload,'.')) PrintAdvice(fload,"Suffixe de fichier necessaire") ;
4664    if(!strchr(fsave,'.')) PrintAdvice(fsave,"Suffixe de fichier necessaire") ;
4665
4666    /*
4667     * Assemblage du source
4668     */
4669    if (LoadFile(fload) == NO_ERROR)
4670    {
4671        if (OpenBin(fsave) == NO_ERROR)
4672        {
4673            /* Engagement pour le listing */
4674            PrintListHeader(fload,fsave) ;
4675
4676            /* Assemblage du source */
4677            AssembleSource(MACROPASS) ;
4678            AssembleSource(PASS1) ;
4679            AssembleSource(PASS2) ;
4680
4681            /* Enregistrement des erreurs */
4682            PrintErrorList() ;
4683
4684            /* Enregistrement des symboles */
4685            PrintSymbolList() ;
4686
4687            CloseBin() ;
4688        }
4689
4690        if (filebuffer != NULL) free(filebuffer) ;
4691    }
4692
4693    return CloseAll() ;
4694}
Note: See TracBrowser for help on using the repository browser.