C:\Users\Utilisateur\Desktop\Thomson\c6809-0.83\fpu\c6809\c6809.c.orig C:\Users\Utilisateur\Desktop\Thomson\c6809-0.83\fpu\c6809\c6809.c
/* /*
*  C6809 - Compilateur macro-assembler pour Thomson (MacroAssembler-like) *  C6809 - Compilateur macro-assembler pour Thomson (MacroAssembler-like)
* *
*  Programme principal *  Programme principal
* *
*  Copyright (C) mars 2010 François Mouret *  Copyright (C) mars 2010 François Mouret
* *
*  This program is free software; you can redistribute it and/or modify *  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by *  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or *  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version. *  (at your option) any later version.
* *
*  This program is distributed in the hope that it will be useful, *  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of *  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details. *  GNU General Public License for more details.
* *
*  You should have received a copy of the GNU General Public License *  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software *  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/  */ 
   
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
   
#ifndef TRUE #ifndef TRUE
#   define TRUE 1 #   define TRUE 1
#endif #endif
   
#ifndef FALSE #ifndef FALSE
#   define FALSE 0 #   define FALSE 0
#endif #endif
   
#ifndef NULL #ifndef NULL
#   define NULL 0 #   define NULL 0
#endif #endif
   
   
/*********************************************************************** /***********************************************************************
* *
*     Variables globales *     Variables globales
* *
***********************************************************************/  ***********************************************************************/ 
   
#define CHAR127 '|'       /* Caractère de remplacement pour CHR$(127) */  #define CHAR127 '|'       /* Caractère de remplacement pour CHR$(127) */ 
#define ARGV_MAX_SIZE 300 #define ARGV_MAX_SIZE 300
#define LINE_MAX_SIZE 75  /* Taille maximum de la ligne à afficher */  #define LINE_MAX_SIZE 75  /* Taille maximum de la ligne à afficher */ 
#define ARG_MAX_SIZE  40  /* Taille maximum d'un argument */  #define ARG_MAX_SIZE  40  /* Taille maximum d'un argument */ 
#define ASM_MAX_SIZE 29000 /* Taille maximum en octets pour un fichier ASM */  #define ASM_MAX_SIZE 29000 /* Taille maximum en octets pour un fichier ASM */ 
   
/* Correspondance caractères 'Occidental ISO-8859' */  /* Correspondance caractères 'Occidental ISO-8859' */ 
unsigned char acc_table[] = { unsigned char acc_table[] = {
   0xE7, /* ç */     0xE7, /* ç */ 
   0xE1, /* á */     0xE1, /* á */ 
   0xE2, /* â */     0xE2, /* â */ 
   0xE4, /* ä */      0xE4, /* ä */  
   0xE0, /* à */     0xE0, /* à */ 
   0xE9, /* é */     0xE9, /* é */ 
   0xEA, /* ê */     0xEA, /* ê */ 
   0xEB, /* ë */     0xEB, /* ë */ 
   0xE8, /* è */     0xE8, /* è */ 
   0xEE, /* î */     0xEE, /* î */ 
   0xEF, /* ï */     0xEF, /* ï */ 
   0xF4, /* ô */     0xF4, /* ô */ 
   0xF6, /* ö */     0xF6, /* ö */ 
   0xFB, /* û */     0xFB, /* û */ 
   0xFC, /* ü */     0xFC, /* ü */ 
   0xF9  /* ù */     0xF9  /* ù */ 
} ; } ;
   
FILE *fp_lst = NULL ;       /* Pour listing d'assemblage */  FILE *fp_lst = NULL ;       /* Pour listing d'assemblage */ 
FILE *fp_asm = NULL ;       /* Pour sauvegarde au format ASM */  FILE *fp_asm = NULL ;       /* Pour sauvegarde au format ASM */ 
char linebuffer[LINE_MAX_SIZE+2] ; /* Buffer de ligne */  char linebuffer[LINE_MAX_SIZE+2] ; /* Buffer de ligne */ 
char *line ;          /* Pointeur de ligne */  char *line ;          /* Pointeur de ligne */ 
char *filebuffer ;    /* Buffer de source */  char *filebuffer ;    /* Buffer de source */ 
char *source ;        /* Pointeur de source */  char *source ;        /* Pointeur de source */ 
char arg[ARG_MAX_SIZE+2] ;        /* Buffer d'argument */  char arg[ARG_MAX_SIZE+2] ;        /* Buffer d'argument */ 
char labelname[ARG_MAX_SIZE+2] ;  /* Buffer du nom d'étiquette */  char labelname[ARG_MAX_SIZE+2] ;  /* Buffer du nom d'étiquette */ 
   
   
/* ------------------------------------------------------------------- /* -------------------------------------------------------------------
* Pour scan du source * Pour scan du source
*/  */ 
enum{ enum{
   SOFT_ASSEMBLER,    SOFT_ASSEMBLER,
   SOFT_MACROASSEMBLER,    SOFT_MACROASSEMBLER,
   SOFT_UPDATE    SOFT_UPDATE
} ; } ;
enum{ enum{
   TO_COMPUTER,      TO_COMPUTER,  
   TO7_COMPUTER,    TO7_COMPUTER,
   MO_COMPUTER    MO_COMPUTER
} ; } ;
enum{ enum{
   OPT_NO, /* Pas de code objet */     OPT_NO, /* Pas de code objet */ 
   OPT_OP, /* Optimisation */     OPT_OP, /* Optimisation */ 
   OPT_SS, /* Lignes séparées (sans effet) */     OPT_SS, /* Lignes séparées (sans effet) */ 
   OPT_WE, /* Attente à l'erreur (sans effet) */     OPT_WE, /* Attente à l'erreur (sans effet) */ 
   OPT_WL, /* Affiche les lignes à l'assemblage */     OPT_WL, /* Affiche les lignes à l'assemblage */ 
   OPT_WS, /* Affiche les symboles à l'assemblage */     OPT_WS, /* Affiche les symboles à l'assemblage */ 
   OPT_SIZEOF    OPT_SIZEOF
} ; } ;
struct { struct {
   int opt[OPT_SIZEOF] ; /* Table des options initiales (passage d'argument) */     int opt[OPT_SIZEOF] ; /* Table des options initiales (passage d'argument) */ 
   int computer ;   /* Type de machine sélectionnée */     int computer ;   /* Type de machine sélectionnée */ 
   int soft ;       /* Type d'assembleur sélectionné */     int soft ;       /* Type d'assembleur sélectionné */ 
   int symb_order ; /* Ordre d'affichage des symboles */     int symb_order ; /* Ordre d'affichage des symboles */ 
   int err_order ;  /* Ordre d'affichage des erreurs */     int err_order ;  /* Ordre d'affichage des erreurs */ 
   int limit ;      /* Taille limite d'une ligne */     int limit ;      /* Taille limite d'une ligne */ 
} scan ; } scan ;
   
   
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
* Pour assemblage du source * Pour assemblage du source
*/  */ 
enum{ enum{
   SCANPASS,  /* Pass de scan */     SCANPASS,  /* Pass de scan */ 
   MACROPASS, /* Pass de macro */     MACROPASS, /* Pass de macro */ 
   PASS1,     /* Pass 1 d'assemblage */     PASS1,     /* Pass 1 d'assemblage */ 
   PASS2      /* Pass 2 d'assemblage */     PASS2      /* Pass 2 d'assemblage */ 
} ; } ;
enum { enum {
   UNLOCKED,    UNLOCKED,
   IF_LOCK,    IF_LOCK,
   MACRO_LOCK,    MACRO_LOCK,
   COMMENT_LOCK = 4    COMMENT_LOCK = 4
} ; } ;
   
struct { struct {
   char *source ; /* Pointeur courant sur le source */     char *source ; /* Pointeur courant sur le source */ 
   int line ;     /* Numéro de ligne courante */     int line ;     /* Numéro de ligne courante */ 
   int pass ;     /* Numéro du pass d'assemblage */     int pass ;     /* Numéro du pass d'assemblage */ 
   int locked ;   /* Bloque l'enregistrement des codes machine */     int locked ;   /* Bloque l'enregistrement des codes machine */ 
   int exit ;     /* Demande l'arrêt de l'assemblage si directive 'END' */     int exit ;     /* Demande l'arrêt de l'assemblage si directive 'END' */ 
   int size ;             /* Taille de l'assemblage */     int size ;             /* Taille de l'assemblage */ 
   unsigned char code[5] ; /* Buffer d'assemblage */     unsigned char code[5] ; /* Buffer d'assemblage */ 
   unsigned char dp ;     /* Valeur du DP */     unsigned char dp ;     /* Valeur du DP */ 
   unsigned short pc ;    /* Valeur du PC */     unsigned short pc ;    /* Valeur du PC */ 
   unsigned short exec ;  /* Valeur de l'adresse d'exécution */     unsigned short exec ;  /* Valeur de l'adresse d'exécution */ 
   int regcode ;          /* Code du registre éventuel (délivré par ScanLine()) */     int regcode ;          /* Code du registre éventuel (délivré par ScanLine()) */ 
   int opt[OPT_SIZEOF] ;  /* Table des options courantes */     int opt[OPT_SIZEOF] ;  /* Table des options courantes */ 
     int quiet;               /* n'affiche pas les lignes sans octets en memoire */ 
} run ; } run ;
   
   
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
* Pour évaluation d'opérande * Pour évaluation d'opérande
*/  */ 
struct { struct {
   int priority ;         /* Priorité de l'opérateur */     int priority ;         /* Priorité de l'opérateur */ 
   char sign ;            /* Signe de l'opérateur */     char sign ;            /* Signe de l'opérateur */ 
   signed short operand ; /* Valeur opérande */     signed short operand ; /* Valeur opérande */ 
   int type ;             /* SET_VALUE/EQU_VALUE/LABEL_VALUE/MACRO_VALUE    int type ;             /* SET_VALUE/EQU_VALUE/LABEL_VALUE/MACRO_VALUE
                           * renvoyé par DoSymbol() (et donc Eval())*/                             * renvoyé par DoSymbol() (et donc Eval())*/ 
   int pass ;             /* Pass de la dernière évaluation */     int pass ;             /* Pass de la dernière évaluation */ 
} eval ; } eval ;
   
   
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
* Pour assemblage conditionnel * Pour assemblage conditionnel
*/  */ 
enum { enum {
   IF_TRUE,    IF_TRUE,
   IF_TRUE_ELSE,    IF_TRUE_ELSE,
   IF_FALSE,    IF_FALSE,
   IF_FALSE_ELSE,    IF_FALSE_ELSE,
   IF_STOP    IF_STOP
} ; } ;
struct { struct {
   int count ;   /* Compteur de degrés d'assemblage conditionnel */     int count ;   /* Compteur de degrés d'assemblage conditionnel */ 
   int buf[17] ; /* Buffer des degrés d'assemblage conditionnel */     int buf[17] ; /* Buffer des degrés d'assemblage conditionnel */ 
} ifc ; } ifc ;
   
   
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
* Pour macro * Pour macro
*/  */ 
struct { struct {
   int count ; /* Identificateur de macro */     int count ; /* Identificateur de macro */ 
   int level ; /* Degré d'appel de macro */     int level ; /* Degré d'appel de macro */ 
} macro ; } macro ;
   
   
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
* Pour marquage 'info' * Pour marquage 'info'
*/  */ 
struct { struct {
   struct {    struct {
       int count ; /* Nombre de cycles de base (-1 si pas) */         int count ; /* Nombre de cycles de base (-1 si pas) */ 
       int plus ;  /* Nombre de cycles ajoutés (-1 si pas) */         int plus ;  /* Nombre de cycles ajoutés (-1 si pas) */ 
       int total ; /* Total du nombre de cycles */         int total ; /* Total du nombre de cycles */ 
   } cycle ;    } cycle ;
   int size ; /* Taille du code assemblé parcouru */     int size ; /* Taille du code assemblé parcouru */ 
} info ; } info ;
   
   
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
* Pour marquage 'check' * Pour marquage 'check'
*/  */ 
int check[4][2] ; int check[4][2] ;
   
   
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
* Pour INCLUD * Pour INCLUD
*/  */ 
struct INCLIST { struct INCLIST {
    struct INCLIST *prev ; /* Pointeur sur l'INCLUD précédent */      struct INCLIST *prev ; /* Pointeur sur l'INCLUD précédent */ 
    int  drive ;    /* Numéro de lecteur */      int  drive ;    /* Numéro de lecteur */ 
    char name[13] ; /* Nom du fichier : xxxxxxxx.xxx */      char name[13] ; /* Nom du fichier : xxxxxxxx.xxx */ 
    int  line  ;    /* Numéro de ligne de l'INCLUD */      int  line  ;    /* Numéro de ligne de l'INCLUD */ 
    int  count ;    /* Compteur d'INCLUD */      int  count ;    /* Compteur d'INCLUD */ 
    char *start ;   /* Pointeur sur début du code d'INCLUD */      char *start ;   /* Pointeur sur début du code d'INCLUD */ 
    char *end ;     /* Pointeur sur fin du code d'INCLUD */      char *end ;     /* Pointeur sur fin du code d'INCLUD */ 
} ; } ;
   
struct INCLIST *first_includ ; struct INCLIST *first_includ ;
   
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
* Liste des codes d'erreur * Liste des codes d'erreur
*/  */ 
enum { enum {
   NO_ERROR,      /* Pas d'erreur */     NO_ERROR,      /* Pas d'erreur */ 
   ERR_ERROR,     /* Erreur */     ERR_ERROR,     /* Erreur */ 
/* Erreurs affichées sans condition */  /* Erreurs affichées sans condition */ 
   ERR_DUPLICATE_MAIN,    ERR_DUPLICATE_MAIN,
   ERR_DUPLICATE_NAME,    ERR_DUPLICATE_NAME,
   ERR_FILE_NOT_FOUND,    ERR_FILE_NOT_FOUND,
   ERR_ILLEGAL_CHAR,    ERR_ILLEGAL_CHAR,
   ERR_IO_ERROR,    ERR_IO_ERROR,
   ERR_MISSING_MAIN,    ERR_MISSING_MAIN,
   ERR_WRONG_MARK,    ERR_WRONG_MARK,
   ERR_EMBEDDED_MACRO,    ERR_EMBEDDED_MACRO,
   ____BREAK_ERROR,    ____BREAK_ERROR,
/* Erreurs affichées seulement au pass 2 de l'assemblage avec /* Erreurs affichées seulement au pass 2 de l'assemblage avec
* affichage de la ligne du source */  * affichage de la ligne du source */ 
   ERR_BAD_ELSE,    ERR_BAD_ELSE,
   ERR_BAD_FILE_FORMAT,    ERR_BAD_FILE_FORMAT,
   ERR_BAD_FILE_NAME,    ERR_BAD_FILE_NAME,
   ERR_BAD_LABEL,    ERR_BAD_LABEL,
   ERR_BAD_MACRO_NAME,    ERR_BAD_MACRO_NAME,
   ERR_BAD_OPERAND,    ERR_BAD_OPERAND,
   ERR_BAD_OPCODE,    ERR_BAD_OPCODE,
   ERR_BAD_PARAM,    ERR_BAD_PARAM,
   ERR_DIVISION_BY_ZERO,    ERR_DIVISION_BY_ZERO,
   ERR_ENDM_WITHOUT_MACRO,    ERR_ENDM_WITHOUT_MACRO,
   ERR_EXPRESSION_ERROR,    ERR_EXPRESSION_ERROR,
   ERR_IF_OUT_OF_RANGE,    ERR_IF_OUT_OF_RANGE,
   ERR_ILLEGAL_INCLUDE,    ERR_ILLEGAL_INCLUDE,
   ERR_ILLEGAL_LABEL,    ERR_ILLEGAL_LABEL,
   ERR_ILLEGAL_OPERAND,    ERR_ILLEGAL_OPERAND,
   ERR_INCLUDE_OUT_OF_RANGE,    ERR_INCLUDE_OUT_OF_RANGE,
   ERR_LABEL_NAME_TOO_LONG,    ERR_LABEL_NAME_TOO_LONG,
   ERR_MACRO_ERROR,    ERR_MACRO_ERROR,
   ERR_MACRO_INTO_IF_RANGE,    ERR_MACRO_INTO_IF_RANGE,
   ERR_MACRO_OUT_OF_RANGE,    ERR_MACRO_OUT_OF_RANGE,
   ERR_MISSING_ENDC,    ERR_MISSING_ENDC,
   ERR_MISSING_IF,    ERR_MISSING_IF,
   ERR_MISSING_INFORMATION,    ERR_MISSING_INFORMATION,
   ERR_MISSING_LABEL,    ERR_MISSING_LABEL,
   ERR_MISSING_OPERAND,    ERR_MISSING_OPERAND,
   ERR_MULTIPLY_DEFINED_SYMBOL,    ERR_MULTIPLY_DEFINED_SYMBOL,
   ERR_OPERAND_IS_MACRO,    ERR_OPERAND_IS_MACRO,
   ERR_SYMBOL_ERROR,    ERR_SYMBOL_ERROR,
   ERR_UNDEFINED_MACRO,    ERR_UNDEFINED_MACRO,
/* Erreurs affichées seulement au pass 2 de l'assemblage mais /* Erreurs affichées seulement au pass 2 de l'assemblage mais
* sans afficher la ligne du source * sans afficher la ligne du source
* Pour certaines, l'erreur n'est pas affichée en 'return' * Pour certaines, l'erreur n'est pas affichée en 'return'
* pour que le pass 1 ne récupère pas une erreur dans le cas où * pour que le pass 1 ne récupère pas une erreur dans le cas où
* l'étiquette se trouve après le branchement, alors que le pass * l'étiquette se trouve après le branchement, alors que le pass
* 2 n'en récupèrera aucune si l'étiquette a été répertoriée au * 2 n'en récupèrera aucune si l'étiquette a été répertoriée au
* pass 1 */  * pass 1 */ 
   ____NO_LINE_ERROR,    ____NO_LINE_ERROR,
   ERR_LINE_TOO_LONG,    ERR_LINE_TOO_LONG,
   ERR_0_BIT,    ERR_0_BIT,
   ERR_5_BITS,    ERR_5_BITS,
   ERR_8_BITS,    ERR_8_BITS,
   ERR_BINARY_NOT_LINEAR,    ERR_BINARY_NOT_LINEAR,
   ERR_BRANCH_OUT_OF_RANGE,    ERR_BRANCH_OUT_OF_RANGE,
   ERR_CHECK_ERROR,    ERR_CHECK_ERROR,
   ERR_DP_ERROR,    ERR_DP_ERROR,
   ERR_OPERAND_OUT_OF_RANGE,    ERR_OPERAND_OUT_OF_RANGE,
   ERR_FORCE_TO_DP,    ERR_FORCE_TO_DP,
   ERR_LONE_SYMBOL,    ERR_LONE_SYMBOL,
   ERR_MISSING_END_STATEMENT,    ERR_MISSING_END_STATEMENT,
   ERR_MISSING_ENDM,    ERR_MISSING_ENDM,
   ERR_MISSING_SLASH,    ERR_MISSING_SLASH,
   ERR_REGISTER_ERROR    ERR_REGISTER_ERROR
} ; } ;
   
   
/* /*
* Capitalise un caractère * Capitalise un caractère
*/  */ 
unsigned char upper_case(char c) unsigned char upper_case(char c)
{ {
   if((c >= 'a') && (c <= 'z'))    if((c >= 'a') && (c <= 'z'))
       c &= 0xDF ;        c &= 0xDF ;
   return c ;    return c ;
} }
   
/* /*
* Capitalise une chaîne de caractères * Capitalise une chaîne de caractères
*/  */ 
void upper_string(char *p) void upper_string(char *p)
{ {
   while(*p != '\0')    while(*p != '\0')
   {    {
       if((*p >= 'a') && (*p <= 'z'))        if((*p >= 'a') && (*p <= 'z'))
           *p &= 0xDF ;            *p &= 0xDF ;
       p++ ;        p++ ;
   }    }
} }
   
   
/*********************************************************************** /***********************************************************************
* *
* Analyse et copie d'une ligne du source pour scan/assemblage * Analyse et copie d'une ligne du source pour scan/assemblage
* *
***********************************************************************/  ***********************************************************************/ 
   
#define COLON_300 300 #define COLON_300 300
#define COLON_40  40 #define COLON_40  40
   
/* Stocke la ligne suivante /* Stocke la ligne suivante
* - Les tabulations sont transformées en série d'espace * - Les tabulations sont transformées en série d'espace
* - La validité des caractères accentués est vérifiée * - La validité des caractères accentués est vérifiée
* - La taille de la ligne est vérifiée * - La taille de la ligne est vérifiée
*/  */ 
int GetLine(void) int GetLine(void)
{ {
   int i ;    int i ;
   int space ;    int space ;
   int error = NO_ERROR ;    int error = NO_ERROR ;
   int size = 0 ;    int size = 0 ;
   
   run.source = source ;    run.source = source ;
   line = linebuffer ;    line = linebuffer ;
   *line = '\0' ;    *line = '\0' ;
   
   while ((size < LINE_MAX_SIZE-1)    while ((size < LINE_MAX_SIZE-1)
       && (*source != 0x00)        && (*source != 0x00)
       && (*source != 0x0A)        && (*source != 0x0A)
       && (*source != 0x0D))        && (*source != 0x0D))
   {    {
       /* Caractère de tabulation */         /* Caractère de tabulation */ 
       if(*source == 0x09)        if(*source == 0x09)
       {        {
           space = 7 - (size % 7) ;            space = 7 - (size % 7) ;
           for(i=0;i<space;i++)            for(i=0;i<space;i++)
               *(line++) = 0x20 ;                *(line++) = 0x20 ;
           size += space ;            size += space ;
       }        }
       else        else
       /* Caractères accentués */         /* Caractères accentués */ 
       if ((unsigned char)*source > 0x7F)        if ((unsigned char)*source > 0x7F)
       {        {
           i = 0 ;            i = 0 ;
           while((i<16) && ((unsigned char)*source != acc_table[i])) i++ ;            while((i<16) && ((unsigned char)*source != acc_table[i])) i++ ;
           if (i == 16)            if (i == 16)
               error = ERR_ILLEGAL_CHAR ;                error = ERR_ILLEGAL_CHAR ;
           *(line++) = *source ;            *(line++) = *source ;
           size++ ;            size++ ;
       }        }
       else        else
       /* Caractères de commande */         /* Caractères de commande */ 
       if ((unsigned char)*source < 0x20)        if ((unsigned char)*source < 0x20)
           error = ERR_ILLEGAL_CHAR ;            error = ERR_ILLEGAL_CHAR ;
       else {        else {
           *(line++) = *source ;            *(line++) = *source ;
           size++ ; }            size++ ; }
       source++ ;        source++ ;
   }    }
   
   /* Clôt la ligne */     /* Clôt la ligne */ 
   *(line++) = '\0' ;    *(line++) = '\0' ;
   
   /* Notifie le dépassement */     /* Notifie le dépassement */ 
   if(size > scan.limit)    if(size > scan.limit)
       error = ERR_LINE_TOO_LONG ;        error = ERR_LINE_TOO_LONG ;
   
   /* Va jusqu'au bout de la ligne */     /* Va jusqu'au bout de la ligne */ 
   while ((*source != 0x00)    while ((*source != 0x00)
       && (*source != 0x0A)        && (*source != 0x0A)
       && (*source != 0x0D)) {        && (*source != 0x0D)) {
          size++ ;           size++ ;
          source++ ; }           source++ ; }
   switch(*source)    switch(*source)
   {    {
       case 0x0A : if (*(source+1) == 0x0D) source++ ; break ;        case 0x0A : if (*(source+1) == 0x0D) source++ ; break ;
       case 0x0D : if (*(source+1) == 0x0A) source++ ; break ;        case 0x0D : if (*(source+1) == 0x0A) source++ ; break ;
   }    }
   source++ ;    source++ ;
   
   /* Elimine les caractères inutiles de fin de ligne */     /* Elimine les caractères inutiles de fin de ligne */ 
   while (((unsigned char)*(--line) <= 0x20)    while (((unsigned char)*(--line) <= 0x20)
       && (size > 0)) {        && (size > 0)) {
       *(line) = 0x00 ;        *(line) = 0x00 ;
       size-- ; }        size-- ; }
   
   /* Initialise les paramètres de lignes */     /* Initialise les paramètres de lignes */ 
   run.line++ ;    run.line++ ;
   line = linebuffer ;    line = linebuffer ;
   
   return error ;    return error ;
} }
   
   
/*********************************************************************** /***********************************************************************
* *
* Traitement des erreurs * Traitement des erreurs
* *
***********************************************************************/  ***********************************************************************/ 
   
/* La liste err_table est dans l'ordre pour l'affichage par code d'erreur */  /* La liste err_table est dans l'ordre pour l'affichage par code d'erreur */ 
#define ETSTRINGSIZE 24 #define ETSTRINGSIZE 24
const struct { const struct {
   char string[ETSTRINGSIZE] ; /* Message de l'erreur */     char string[ETSTRINGSIZE] ; /* Message de l'erreur */ 
   int code ;                  /* Code de l'erreur */     int code ;                  /* Code de l'erreur */ 
 } err_table[] = {  } err_table[] = {
 /* Erreurs de scan prioritaires */   /* Erreurs de scan prioritaires */ 
   { "Missing (main)"          , ERR_MISSING_MAIN            },    { "Missing (main)"          , ERR_MISSING_MAIN            },
   { "Duplicate (main)"        , ERR_DUPLICATE_MAIN          },    { "Duplicate (main)"        , ERR_DUPLICATE_MAIN          },
   { "Duplicate Name"          , ERR_DUPLICATE_NAME          },    { "Duplicate Name"          , ERR_DUPLICATE_NAME          },
   { "Line Too Long"           , ERR_LINE_TOO_LONG           },    { "Line Too Long"           , ERR_LINE_TOO_LONG           },
   { "Illegal Char"            , ERR_ILLEGAL_CHAR            },    { "Illegal Char"            , ERR_ILLEGAL_CHAR            },
   { "Wrong Mark"              , ERR_WRONG_MARK              },    { "Wrong Mark"              , ERR_WRONG_MARK              },
 /* Erreurs d'assemblage prioritaires (PASS1) */   /* Erreurs d'assemblage prioritaires (PASS1) */ 
   { "File Not Found"          , ERR_FILE_NOT_FOUND          },    { "File Not Found"          , ERR_FILE_NOT_FOUND          },
   { "I/O Error"               , ERR_IO_ERROR                },    { "I/O Error"               , ERR_IO_ERROR                },
   { "Missing Endm"            , ERR_MISSING_ENDM            },    { "Missing Endm"            , ERR_MISSING_ENDM            },
   { "Bad File Format"         , ERR_BAD_FILE_FORMAT         },    { "Bad File Format"         , ERR_BAD_FILE_FORMAT         },
   { "Bad File Name"           , ERR_BAD_FILE_NAME           },    { "Bad File Name"           , ERR_BAD_FILE_NAME           },
   { "Include Out Of Range"    , ERR_INCLUDE_OUT_OF_RANGE    },    { "Include Out Of Range"    , ERR_INCLUDE_OUT_OF_RANGE    },
 /* Erreurs d'optimisation */   /* Erreurs d'optimisation */ 
   { "0 bit"                   , ERR_0_BIT                   },    { "0 bit"                   , ERR_0_BIT                   },
   { "5 bits"                  , ERR_5_BITS                  },    { "5 bits"                  , ERR_5_BITS                  },
   { "8 bits"                  , ERR_8_BITS                  },    { "8 bits"                  , ERR_8_BITS                  },
   { "Lone Symbol"             , ERR_LONE_SYMBOL             },    { "Lone Symbol"             , ERR_LONE_SYMBOL             },
   { "Force To DP"             , ERR_FORCE_TO_DP             },    { "Force To DP"             , ERR_FORCE_TO_DP             },
 /* Erreurs courantes */   /* Erreurs courantes */ 
   { "Expression Error"        , ERR_EXPRESSION_ERROR        },    { "Expression Error"        , ERR_EXPRESSION_ERROR        },
   { "Branch Out Of Range"     , ERR_BRANCH_OUT_OF_RANGE     },    { "Branch Out Of Range"     , ERR_BRANCH_OUT_OF_RANGE     },
   { "Bad Operand"             , ERR_BAD_OPERAND             },    { "Bad Operand"             , ERR_BAD_OPERAND             },
   { "Bad Label"               , ERR_BAD_LABEL               },    { "Bad Label"               , ERR_BAD_LABEL               },
   { "Bad Opcode"              , ERR_BAD_OPCODE              },    { "Bad Opcode"              , ERR_BAD_OPCODE              },
   { "Missing Operand"         , ERR_MISSING_OPERAND         },    { "Missing Operand"         , ERR_MISSING_OPERAND         },
   { "Multiply Defined Symbol" , ERR_MULTIPLY_DEFINED_SYMBOL },    { "Multiply Defined Symbol" , ERR_MULTIPLY_DEFINED_SYMBOL },
   { "Operand Out Of Range"    , ERR_OPERAND_OUT_OF_RANGE    },    { "Operand Out Of Range"    , ERR_OPERAND_OUT_OF_RANGE    },
   { "Symbol Error"            , ERR_SYMBOL_ERROR            },    { "Symbol Error"            , ERR_SYMBOL_ERROR            },
   { "DP Error"                , ERR_DP_ERROR                },    { "DP Error"                , ERR_DP_ERROR                },
   { "Division By Zero"        , ERR_DIVISION_BY_ZERO        },    { "Division By Zero"        , ERR_DIVISION_BY_ZERO        },
 /* Erreur de condition */   /* Erreur de condition */ 
   { "If Out Of Range"         , ERR_IF_OUT_OF_RANGE         },    { "If Out Of Range"         , ERR_IF_OUT_OF_RANGE         },
   { "Missing If"              , ERR_MISSING_IF              },    { "Missing If"              , ERR_MISSING_IF              },
   { "Missing Endc"            , ERR_MISSING_ENDC            },    { "Missing Endc"            , ERR_MISSING_ENDC            },
   { "Bad Else"                , ERR_BAD_ELSE                },    { "Bad Else"                , ERR_BAD_ELSE                },
 /* Erreur de macro */   /* Erreur de macro */ 
   { "Illegal Include"         , ERR_ILLEGAL_INCLUDE         },    { "Illegal Include"         , ERR_ILLEGAL_INCLUDE         },
   { "Bad Macro Name"          , ERR_BAD_MACRO_NAME          },    { "Bad Macro Name"          , ERR_BAD_MACRO_NAME          },
   { "Macro Error"             , ERR_MACRO_ERROR             },    { "Macro Error"             , ERR_MACRO_ERROR             },
   { "Macro Into If Range"     , ERR_MACRO_INTO_IF_RANGE     },    { "Macro Into If Range"     , ERR_MACRO_INTO_IF_RANGE     },
   { "Macro Out Of Range"      , ERR_MACRO_OUT_OF_RANGE      },    { "Macro Out Of Range"      , ERR_MACRO_OUT_OF_RANGE      },
 /* Erreur peu courantes */   /* Erreur peu courantes */ 
   { "Bad Param"               , ERR_BAD_PARAM               },    { "Bad Param"               , ERR_BAD_PARAM               },
   { "Check Error"             , ERR_CHECK_ERROR             },    { "Check Error"             , ERR_CHECK_ERROR             },
   { "Embedded Macro"          , ERR_EMBEDDED_MACRO          },    { "Embedded Macro"          , ERR_EMBEDDED_MACRO          },
   { "Missing Information"     , ERR_MISSING_INFORMATION     },    { "Missing Information"     , ERR_MISSING_INFORMATION     },
   { "Missing Label"           , ERR_MISSING_LABEL           },    { "Missing Label"           , ERR_MISSING_LABEL           },
   { "Illegal Label"           , ERR_ILLEGAL_LABEL           },    { "Illegal Label"           , ERR_ILLEGAL_LABEL           },
   { "Label Name Too Long"     , ERR_LABEL_NAME_TOO_LONG     },    { "Label Name Too Long"     , ERR_LABEL_NAME_TOO_LONG     },
   { "Illegal Operand"         , ERR_ILLEGAL_OPERAND         },    { "Illegal Operand"         , ERR_ILLEGAL_OPERAND         },
   { "Operand Is Macro"        , ERR_OPERAND_IS_MACRO        },    { "Operand Is Macro"        , ERR_OPERAND_IS_MACRO        },
   { "Register Error"          , ERR_REGISTER_ERROR          },    { "Register Error"          , ERR_REGISTER_ERROR          },
   { "Binary Not Linear"       , ERR_BINARY_NOT_LINEAR       },    { "Binary Not Linear"       , ERR_BINARY_NOT_LINEAR       },
   { "DP Error"                , ERR_DP_ERROR                },    { "DP Error"                , ERR_DP_ERROR                },
   { "Endm Without Macro"      , ERR_ENDM_WITHOUT_MACRO      },    { "Endm Without Macro"      , ERR_ENDM_WITHOUT_MACRO      },
   { "Undefined Macro"         , ERR_UNDEFINED_MACRO         },    { "Undefined Macro"         , ERR_UNDEFINED_MACRO         },
   { "Missing Slash"           , ERR_MISSING_SLASH           },    { "Missing Slash"           , ERR_MISSING_SLASH           },
   { "Missing End Statement"   , ERR_MISSING_END_STATEMENT   }    { "Missing End Statement"   , ERR_MISSING_END_STATEMENT   }
} ; } ;
#define ETSIZE (int)sizeof(err_table)/(int)sizeof(err_table[0]) #define ETSIZE (int)sizeof(err_table)/(int)sizeof(err_table[0])
   
struct ERRLIST { struct ERRLIST {
   struct ERRLIST *next ; /* Pointeur sur section suivante */     struct ERRLIST *next ; /* Pointeur sur section suivante */ 
   int error ;    /* Numéro de l'erreur */     int error ;    /* Numéro de l'erreur */ 
   int line ;     /* Numéro de la ligne */     int line ;     /* Numéro de la ligne */ 
   char *source ; /* Ponteur sur la ligne du source */     char *source ; /* Ponteur sur la ligne du source */ 
} ; } ;
   
struct ERRLIST *first_error ; struct ERRLIST *first_error ;
   
/* /*
* Initialise le chaînage des erreurs * Initialise le chaînage des erreurs
* *
* Le premier élément de la liste (pointé par first_error) ne contient * Le premier élément de la liste (pointé par first_error) ne contient
* qu'un pointeur 'next', et le numéro de sa ligne est à 0 * qu'un pointeur 'next', et le numéro de sa ligne est à 0
* Ainsi, le pointeur first_error est invariable * Ainsi, le pointeur first_error est invariable
*/  */ 
void InitErrorChain(void) void InitErrorChain(void)
{ {
   first_error = malloc(sizeof(struct ERRLIST)) ;    first_error = malloc(sizeof(struct ERRLIST)) ;
   first_error->line = 0 ;    first_error->line = 0 ;
   first_error->next = NULL ;    first_error->next = NULL ;
} }
   
/* /*
* Libère la mémoire pour le chaînage des erreurs * Libère la mémoire pour le chaînage des erreurs
*/  */ 
void FreeErrorChain(void) void FreeErrorChain(void)
{ {
   struct ERRLIST *current_error ;    struct ERRLIST *current_error ;
   
   while ((current_error = first_error))    while ((current_error = first_error))
   {    {
       first_error = first_error->next ;        first_error = first_error->next ;
       free(current_error) ;        free(current_error) ;
   }    }
} }
   
/* /*
* Limite la taille de la ligne à afficher * Limite la taille de la ligne à afficher
*/  */ 
void MakeLimitedLine(char *formatstring) void MakeLimitedLine(char *formatstring)
{ {
   int size = LINE_MAX_SIZE - (int)strlen(formatstring) ;    int size = LINE_MAX_SIZE - (int)strlen(formatstring) ;
   if (size > 0)    if (size > 0)
       strncat(formatstring,linebuffer,LINE_MAX_SIZE - (int)strlen(formatstring)) ;        strncat(formatstring,linebuffer,LINE_MAX_SIZE - (int)strlen(formatstring)) ;
   formatstring[LINE_MAX_SIZE] = '>' ;    formatstring[LINE_MAX_SIZE] = '>' ;
   formatstring[LINE_MAX_SIZE+1] = '>' ;    formatstring[LINE_MAX_SIZE+1] = '>' ;
   formatstring[LINE_MAX_SIZE+2] = '\0' ;    formatstring[LINE_MAX_SIZE+2] = '\0' ;
} }
   
/* /*
* Affiche une erreur pour la liste de fin d'assemblage * Affiche une erreur pour la liste de fin d'assemblage
*/  */ 
void PrintErrorListLine(struct ERRLIST *rlist) void PrintErrorListLine(struct ERRLIST *rlist)
{ {
   char formatstring[LINE_MAX_SIZE+3] ;    char formatstring[LINE_MAX_SIZE+3] ;
   char fmt[30] ;    char fmt[30] ;
   
   sprintf(fmt,"%%%ds %% 7d ",ETSTRINGSIZE) ;    sprintf(fmt,"%%%ds %% 7d ",ETSTRINGSIZE) ;
   sprintf(formatstring,fmt,    sprintf(formatstring,fmt,
                        err_table[rlist->error].string,                         err_table[rlist->error].string,
                        rlist->line) ;                         rlist->line) ;
   source = rlist->source ;    source = rlist->source ;
   GetLine() ;    GetLine() ;
   MakeLimitedLine(formatstring) ;    MakeLimitedLine(formatstring) ;
   fprintf(fp_lst,"%s\n",formatstring) ;    fprintf(fp_lst,"%s\n",formatstring) ;
} }
   
/* /*
* Affiche/Enregistre les erreurs pour l'assemblage * Affiche/Enregistre les erreurs pour l'assemblage
*/  */ 
int PrintError(int code) int PrintError(int code)
{ {
   int i ;    int i ;
   struct ERRLIST *current_error ;    struct ERRLIST *current_error ;
   struct ERRLIST *found_error ;    struct ERRLIST *found_error ;
   struct ERRLIST *new_error ;    struct ERRLIST *new_error ;
   char formatstring[LINE_MAX_SIZE+3] ;    char formatstring[LINE_MAX_SIZE+3] ;
   char filestring[15] ;    char filestring[15] ;
   
   if ((code != NO_ERROR)    if ((code != NO_ERROR)
    && (code != ERR_ERROR))     && (code != ERR_ERROR))
   {    {
       /* Recherche la position de l'erreur */         /* Recherche la position de l'erreur */ 
       i = 0 ;        i = 0 ;
       while((i<ETSIZE) && (code != err_table[i].code)) i++ ;        while((i<ETSIZE) && (code != err_table[i].code)) i++ ;
       code = i ;        code = i ;
   
       /* Filtrage d'affichage        /* Filtrage d'affichage
        * L'erreur doit être affichée à tous les coups ou seulement au         * L'erreur doit être affichée à tous les coups ou seulement au
        * pass 2         * pass 2
        */          */ 
       if ((run.pass == SCANPASS)        if ((run.pass == SCANPASS)
        || (err_table[code].code < ____BREAK_ERROR)         || (err_table[code].code < ____BREAK_ERROR)
       || ((err_table[code].code > ____BREAK_ERROR) && (run.pass == PASS2)))        || ((err_table[code].code > ____BREAK_ERROR) && (run.pass == PASS2)))
       {        {
           /* Affiche/Enregistre l'erreur */             /* Affiche/Enregistre l'erreur */ 
           filestring[0] = '\0' ;            filestring[0] = '\0' ;
           if ((first_includ != NULL)            if ((first_includ != NULL)
            && (first_includ->count != 0))             && (first_includ->count != 0))
               sprintf(filestring,"%d:%s",                sprintf(filestring,"%d:%s",
                                  first_includ->drive,                                   first_includ->drive,
                                  first_includ->name) ;                                   first_includ->name) ;
           sprintf(formatstring,"(%d)%s %s",            sprintf(formatstring,"(%d)%s %s",
                                run.line,                                 run.line,
                                filestring,                                 filestring,
                                err_table[code].string) ;                                 err_table[code].string) ;
           fprintf(fp_lst,"%s\n",formatstring) ;            fprintf(fp_lst,"%s\n",formatstring) ;
           printf("%s\n",formatstring) ;            printf("%s\n",formatstring) ;
   
           /* Affiche éventuellement la ligne du source */             /* Affiche éventuellement la ligne du source */ 
           sprintf(formatstring, "% 7d ", run.line) ;            sprintf(formatstring, "% 7d ", run.line) ;
           MakeLimitedLine(formatstring) ;            MakeLimitedLine(formatstring) ;
           if (err_table[code].code < ____NO_LINE_ERROR)            if (err_table[code].code < ____NO_LINE_ERROR)
               fprintf(fp_lst,"%s\n",formatstring) ;                fprintf(fp_lst,"%s\n",formatstring) ;
           if (run.opt[OPT_WL] == FALSE)            if (run.opt[OPT_WL] == FALSE)
               printf("%s\n",formatstring) ;                printf("%s\n",formatstring) ;
   
           /* Collecte les erreurs pour fin d'assemblage            /* Collecte les erreurs pour fin d'assemblage
              Le programme en profite pour ranger les erreurs dans               Le programme en profite pour ranger les erreurs dans
              l'ordre croissant des numéros de lignes */                l'ordre croissant des numéros de lignes */ 
           current_error = first_error ;            current_error = first_error ;
           do {            do {
              found_error   = current_error ;               found_error   = current_error ;
              current_error = current_error->next ;               current_error = current_error->next ;
           } while((current_error != NULL)              } while((current_error != NULL)  
                && (current_error->line <= run.line)) ;                 && (current_error->line <= run.line)) ;
           new_error = malloc(sizeof(struct ERRLIST)) ;            new_error = malloc(sizeof(struct ERRLIST)) ;
           found_error->next = new_error ;            found_error->next = new_error ;
           new_error->next   = current_error ;            new_error->next   = current_error ;
           new_error->error  = code ;            new_error->error  = code ;
           new_error->line   = run.line ;            new_error->line   = run.line ;
           new_error->source = run.source ;            new_error->source = run.source ;
       }        }
       code = ERR_ERROR ;        code = ERR_ERROR ;
   }    }
   return code ;    return code ;
} }
   
enum{ enum{
   INITIAL_ORDER,    INITIAL_ORDER,
   ERROR_ORDER,    ERROR_ORDER,
   TYPE_ORDER,    TYPE_ORDER,
   TIME_ORDER    TIME_ORDER
} ; } ;
   
/* /*
* Enregistre les erreurs de fin d'assemblage * Enregistre les erreurs de fin d'assemblage
*/  */ 
void PrintErrorList(void) void PrintErrorList(void)
{ {
   int i = 0 ;    int i = 0 ;
   struct ERRLIST *current_error ;    struct ERRLIST *current_error ;
   
   current_error = first_error ;    current_error = first_error ;
   while((current_error = current_error->next) != NULL)    while((current_error = current_error->next) != NULL)
       i++ ;        i++ ;
   printf("\n%06d Total Errors\n",i) ;    printf("\n%06d Total Errors\n",i) ;
   fprintf(fp_lst, "\n%06d Total Errors\n",i) ;    fprintf(fp_lst, "\n%06d Total Errors\n",i) ;
   
   if (i != 0)    if (i != 0)
   {    {
       current_error = first_error ;        current_error = first_error ;
       switch(scan.err_order)        switch(scan.err_order)
       {        {
           case INITIAL_ORDER :            case INITIAL_ORDER :
               current_error = first_error ;                current_error = first_error ;
               while((current_error = current_error->next) != NULL)                while((current_error = current_error->next) != NULL)
                   PrintErrorListLine(current_error) ;                    PrintErrorListLine(current_error) ;
               break ;                break ;
           case ERROR_ORDER :            case ERROR_ORDER :
               for(i=0;i<ETSIZE;i++)                for(i=0;i<ETSIZE;i++)
               {                {
                   current_error = first_error ;                    current_error = first_error ;
                   while((current_error = current_error->next) != NULL)                    while((current_error = current_error->next) != NULL)
                       if (current_error->error == i)                        if (current_error->error == i)
                           PrintErrorListLine(current_error) ;                            PrintErrorListLine(current_error) ;
               }                }
               break ;                break ;
       }        }
   }    }
} }
   
   
/*********************************************************************** /***********************************************************************
* *
* Lecture d'un argument * Lecture d'un argument
* *
***********************************************************************/  ***********************************************************************/ 
   
/* /*
* Teste si caractère alphabétique * Teste si caractère alphabétique
*/  */ 
int is_alpha(unsigned char c) int is_alpha(unsigned char c)
{ {
   switch(scan.soft)    switch(scan.soft)
   {    {
       case SOFT_ASSEMBLER :        case SOFT_ASSEMBLER :
           return ((upper_case(c) >= 'A') && (upper_case(c) <= 'Z')) ? TRUE : FALSE ;            return ((upper_case(c) >= 'A') && (upper_case(c) <= 'Z')) ? TRUE : FALSE ;
           break ;            break ;
       default :        default :
           return (((upper_case(c) >= 'A') && (upper_case(c) <= 'Z'))            return (((upper_case(c) >= 'A') && (upper_case(c) <= 'Z'))
                 || (c == '_')) ? TRUE : FALSE ;                  || (c == '_')) ? TRUE : FALSE ;
           break ;            break ;
   }    }
   return FALSE ;    return FALSE ;
} }
   
/* /*
* Teste si caractère numérique * Teste si caractère numérique
*/  */ 
int is_numeric(unsigned char c) int is_numeric(unsigned char c)
{ {
   return ((c >= '0') && (c <= '9')) ? TRUE : FALSE ;    return ((c >= '0') && (c <= '9')) ? TRUE : FALSE ;
} }
   
/* Les valeurs de registres sont dans l'ordre pour TFR/EXG */  /* Les valeurs de registres sont dans l'ordre pour TFR/EXG */ 
enum { enum {
   REG_D = 0x00,    REG_D = 0x00,
   REG_X,    REG_X,
   REG_Y,    REG_Y,
   REG_U,    REG_U,
   REG_S,    REG_S,
   REG_PC,    REG_PC,
   REG_A = 0x08,    REG_A = 0x08,
   REG_B,    REG_B,
   REG_CC,    REG_CC,
   REG_DP,    REG_DP,
   REG_PCR = 0x0F,    REG_PCR = 0x0F,
   NUMERIC_CHAR,    NUMERIC_CHAR,
   ALPHA_CHAR,    ALPHA_CHAR,
   SIGN_CHAR    SIGN_CHAR
} ; } ;
   
/* Le bit ISREG set à déterminer s'il s'agit d'un registre hors PCR */  /* Le bit ISREG set à déterminer s'il s'agit d'un registre hors PCR */ 
enum { enum {
   END_CHAR,    END_CHAR,
   ISREG = 0x8000,    ISREG = 0x8000,
   REGS_PCR = 0x0004,    REGS_PCR = 0x0004,
   REGS_CCDPPC = 0x8005,    REGS_CCDPPC = 0x8005,
   REGS_ABD,    REGS_ABD,
   REGS_XYUS    REGS_XYUS
} ; } ;
   
int ScanLine(void) int ScanLine(void)
{ {
   int i ;    int i ;
   char *p ;    char *p ;
   char regbuf[4] ;    char regbuf[4] ;
         
   const struct {    const struct {
        char name[4] ; /* Nom du registre */          char name[4] ; /* Nom du registre */ 
        int code ;     /* Code du registre */          int code ;     /* Code du registre */ 
        int group ;    /* Code du groupe du registre */          int group ;    /* Code du groupe du registre */ 
     } Regs_T[11] = {      } Regs_T[11] = {
       {   "A", REG_A  , REGS_ABD    },        {   "A", REG_A  , REGS_ABD    },
       {   "B", REG_B  , REGS_ABD    },        {   "B", REG_B  , REGS_ABD    },
       {   "D", REG_D  , REGS_ABD    },        {   "D", REG_D  , REGS_ABD    },
       {   "X", REG_X  , REGS_XYUS   },        {   "X", REG_X  , REGS_XYUS   },
       {   "Y", REG_Y  , REGS_XYUS   },        {   "Y", REG_Y  , REGS_XYUS   },
       {   "U", REG_U  , REGS_XYUS   },        {   "U", REG_U  , REGS_XYUS   },
       {   "S", REG_S  , REGS_XYUS   },        {   "S", REG_S  , REGS_XYUS   },
       {  "CC", REG_CC , REGS_CCDPPC },        {  "CC", REG_CC , REGS_CCDPPC },
       {  "DP", REG_DP , REGS_CCDPPC },        {  "DP", REG_DP , REGS_CCDPPC },
       {  "PC", REG_PC , REGS_CCDPPC },        {  "PC", REG_PC , REGS_CCDPPC },
       { "PCR", REG_PCR, REGS_PCR    }        { "PCR", REG_PCR, REGS_PCR    }
   } ;    } ;
#define RTSIZE (int)sizeof(Regs_T)/(int)sizeof(Regs_T[0]) #define RTSIZE (int)sizeof(Regs_T)/(int)sizeof(Regs_T[0])
   
   *arg = '\0' ;    *arg = '\0' ;
   if (*line <= ' ') return END_CHAR ;    if (*line <= ' ') return END_CHAR ;
   
   /* Capture d'au moins un caractère jusqu'à fin élément */     /* Capture d'au moins un caractère jusqu'à fin élément */ 
   p = arg ;    p = arg ;
   i = 0 ;    i = 0 ;
   if ((is_alpha(*line) == TRUE) || (is_numeric(*line) == TRUE))    if ((is_alpha(*line) == TRUE) || (is_numeric(*line) == TRUE))
   {    {
       while (((is_alpha(*line) == TRUE) || (is_numeric(*line) == TRUE)) && (i < 41))        while (((is_alpha(*line) == TRUE) || (is_numeric(*line) == TRUE)) && (i < 41))
       {        {
           *(p++) = *(line++) ;            *(p++) = *(line++) ;
           i++ ;            i++ ;
       }        }
       while ((is_alpha(*line) == TRUE) || (is_numeric(*line) == TRUE))        while ((is_alpha(*line) == TRUE) || (is_numeric(*line) == TRUE))
           line++ ;            line++ ;
   }    }
   else *(p++) = *(line++) ;    else *(p++) = *(line++) ;
   
   *p = '\0' ;    *p = '\0' ;
   
   /* Si alphabétique */     /* Si alphabétique */ 
   if (is_alpha(*arg) == TRUE)    if (is_alpha(*arg) == TRUE)
   {    {
       if ((int)strlen(arg) < 4)        if ((int)strlen(arg) < 4)
       {        {
           regbuf[0] = '\0' ;            regbuf[0] = '\0' ;
           strcat(regbuf,arg) ;            strcat(regbuf,arg) ;
           upper_string(regbuf) ;            upper_string(regbuf) ;
           for(i=0;i<RTSIZE;i++)            for(i=0;i<RTSIZE;i++)
               if (!strcmp(regbuf,Regs_T[i].name)) {                if (!strcmp(regbuf,Regs_T[i].name)) {
                   run.regcode = Regs_T[i].code ;                    run.regcode = Regs_T[i].code ;
                   return (Regs_T[i].group) ; }                    return (Regs_T[i].group) ; }
       }        }
       return ALPHA_CHAR ;        return ALPHA_CHAR ;
   }    }
   
   /* Si numérique */     /* Si numérique */ 
   if (is_numeric(*arg) == TRUE) return NUMERIC_CHAR ;    if (is_numeric(*arg) == TRUE) return NUMERIC_CHAR ;
   
   /* Sinon, signe */     /* Sinon, signe */ 
   return SIGN_CHAR ;    return SIGN_CHAR ;
} }
   
   
/*********************************************************************** /***********************************************************************
* *
* Enregistrement de la ligne de code dans le listing * Enregistrement de la ligne de code dans le listing
* *
***********************************************************************/  ***********************************************************************/ 
   
#define CODE_STRING_SIZE 18 #define CODE_STRING_SIZE 18
   
enum{ enum{
   PRINT_EMPTY,    PRINT_EMPTY,
   PRINT_LINE,    PRINT_LINE,
   PRINT_NO_CODE,    PRINT_NO_CODE,
   PRINT_BYTES,    PRINT_BYTES,
   PRINT_BYTES_ONLY,    PRINT_BYTES_ONLY,
   PRINT_WORDS,    PRINT_WORDS,
   PRINT_WORDS_ONLY,    PRINT_WORDS_ONLY,
   PRINT_PC,    PRINT_PC,
   PRINT_LIKE_END,    PRINT_LIKE_END,
   PRINT_LIKE_DP,    PRINT_LIKE_DP,
   PRINT_ONE_FOR_ONE,    PRINT_ONE_FOR_ONE,
   PRINT_TWO_FOR_TWO,    PRINT_TWO_FOR_TWO,
   PRINT_TWO_FOR_THREE,    PRINT_TWO_FOR_THREE,
   PRINT_THREE_FOR_THREE,    PRINT_THREE_FOR_THREE,
   PRINT_THREE_FOR_FOUR    PRINT_THREE_FOR_FOUR
} ; } ;
   
/* /*
* Enregistre la ligne de code * Enregistre la ligne de code
*/  */ 
int RecordLine(int drawmode) int RecordLine(int drawmode)
{ {
   int i ;    int i ;
   int size ;    int size ;
   char opcodestring[5] ;    char opcodestring[5] ;
   char bytestring[6] ;    char bytestring[6] ;
   char codestring[CODE_STRING_SIZE+2] ;    char codestring[CODE_STRING_SIZE+2] ;
   char cyclestring[6] ;    char cyclestring[6] ;
   char formatstring[LINE_MAX_SIZE+3] ;    char formatstring[LINE_MAX_SIZE+3] ;
   char fmt[20] ;    char fmt[20] ;
   
   if (run.pass != PASS2) return NO_ERROR ;    if (run.pass != PASS2) return NO_ERROR ;
   
   if (run.locked) drawmode = PRINT_NO_CODE ;    if (run.locked) drawmode = PRINT_NO_CODE ;
   
     if(run.quiet!=0) /* sam */ 
         switch(drawmode) {
             case PRINT_EMPTY:
             case PRINT_NO_CODE:
             case PRINT_PC:
             case PRINT_LIKE_END:
             case PRINT_LIKE_DP:
                 return NO_ERROR;
             default:
                 break;
         }
              
   /* Prépare la chaîne de l'opcode */     /* Prépare la chaîne de l'opcode */ 
   if (run.code[0])    if (run.code[0])
       sprintf(opcodestring,"%02X%02X",run.code[0],run.code[1]) ;        sprintf(opcodestring,"%02X%02X",run.code[0],run.code[1]) ;
   else    else
       sprintf(opcodestring,"%02X  ",run.code[1]) ;        sprintf(opcodestring,"%02X  ",run.code[1]) ;
   
   /* Prépare la chaîne des cycles */     /* Prépare la chaîne des cycles */ 
   cyclestring[0] = '\0' ;    cyclestring[0] = '\0' ;
   if ((drawmode != PRINT_NO_CODE) && (info.cycle.count != -1))    if ((drawmode != PRINT_NO_CODE) && (info.cycle.count != -1))
   {    {
       if (info.cycle.plus != -1)        if (info.cycle.plus != -1)
           sprintf(cyclestring,"%d+%d",            sprintf(cyclestring,"%d+%d",
                               info.cycle.count,                                info.cycle.count,
                               info.cycle.plus) ;                                info.cycle.plus) ;
       else        else
           sprintf(cyclestring,"%d",info.cycle.count) ;            sprintf(cyclestring,"%d",info.cycle.count) ;
   }    }
   
   formatstring[0] = '\0' ;    formatstring[0] = '\0' ;
   codestring[0] = '\0' ;    codestring[0] = '\0' ;
         
   switch(drawmode)    switch(drawmode)
   {    {
       case PRINT_EMPTY :        case PRINT_EMPTY :
       case PRINT_NO_CODE :        case PRINT_NO_CODE :
           break ;            break ;
       case PRINT_BYTES :        case PRINT_BYTES :
       case PRINT_BYTES_ONLY :        case PRINT_BYTES_ONLY :
       case PRINT_WORDS :        case PRINT_WORDS :
       case PRINT_WORDS_ONLY :        case PRINT_WORDS_ONLY :
           size = ((drawmode == PRINT_BYTES) || (drawmode == PRINT_BYTES_ONLY)) ? 1 : 2 ;            size = ((drawmode == PRINT_BYTES) || (drawmode == PRINT_BYTES_ONLY)) ? 1 : 2 ;
           sprintf(codestring,"%04X ",run.pc) ;            sprintf(codestring,"%04X ",run.pc) ;
           for(i=0;i<run.size;i+=size)            for(i=0;i<run.size;i+=size)
           {            {
               if (i != 0) strcat(codestring," ") ;                if (i != 0) strcat(codestring," ") ;
               if (size == 1)                if (size == 1)
                   sprintf(bytestring,"%02X",run.code[i+1]) ;                    sprintf(bytestring,"%02X",run.code[i+1]) ;
               else                else
                   sprintf(bytestring,"%02X%02X",run.code[i+1],run.code[i+2]) ;                    sprintf(bytestring,"%02X%02X",run.code[i+1],run.code[i+2]) ;
               strcat(codestring,bytestring) ;                strcat(codestring,bytestring) ;
           }            }
           break ;            break ;
       case PRINT_PC :        case PRINT_PC :
           sprintf(codestring,"%04X",run.pc) ;            sprintf(codestring,"%04X",run.pc) ;
           break ;            break ;
       case PRINT_LIKE_END :        case PRINT_LIKE_END :
           sprintf(codestring,"%10s%04X","",(unsigned short)eval.operand) ;            sprintf(codestring,"%10s%04X","",(unsigned short)eval.operand) ;
           break ;            break ;
       case PRINT_LIKE_DP :        case PRINT_LIKE_DP :
           sprintf(codestring,"%10s%02X","",run.dp) ;            sprintf(codestring,"%10s%02X","",run.dp) ;
           break ;            break ;
       case PRINT_ONE_FOR_ONE :        case PRINT_ONE_FOR_ONE :
           sprintf(codestring,"%04X %s",            sprintf(codestring,"%04X %s",
               run.pc,                run.pc,
               opcodestring) ;                opcodestring) ;
           break ;            break ;
       case PRINT_TWO_FOR_TWO :        case PRINT_TWO_FOR_TWO :
           sprintf(codestring,"%04X %s %02X",            sprintf(codestring,"%04X %s %02X",
               run.pc,                run.pc,
               opcodestring,                opcodestring,
               run.code[2]) ;                run.code[2]) ;
           break ;            break ;
       case PRINT_TWO_FOR_THREE :        case PRINT_TWO_FOR_THREE :
           sprintf(codestring,"%04X %s %02X%02X",            sprintf(codestring,"%04X %s %02X%02X",
               run.pc,                run.pc,
               opcodestring,                opcodestring,
               run.code[2],                run.code[2],
               run.code[3]) ;                run.code[3]) ;
           break ;            break ;
       case PRINT_THREE_FOR_THREE :        case PRINT_THREE_FOR_THREE :
           sprintf(codestring,"%04X %s %02X %02X",            sprintf(codestring,"%04X %s %02X %02X",
               run.pc,                run.pc,
               opcodestring,                opcodestring,
               run.code[2],                run.code[2],
               run.code[3]) ;                run.code[3]) ;
           break ;            break ;
       case PRINT_THREE_FOR_FOUR :        case PRINT_THREE_FOR_FOUR :
           sprintf(codestring,"%04X %s %02X %02X%02X",            sprintf(codestring,"%04X %s %02X %02X%02X",
               run.pc,                run.pc,
               opcodestring,                opcodestring,
               run.code[2],                run.code[2],
               run.code[3],                run.code[3],
               run.code[4]) ;                run.code[4]) ;
           break ;            break ;
   }    }
      
      
   switch(drawmode)    switch(drawmode)
   {    {
       case PRINT_EMPTY :        case PRINT_EMPTY :
           sprintf(formatstring,"% 7d",run.line) ;            sprintf(formatstring,"% 7d",run.line) ;
           break ;            break ;
       case PRINT_BYTES_ONLY :        case PRINT_BYTES_ONLY :
       case PRINT_WORDS_ONLY :        case PRINT_WORDS_ONLY :
           sprintf(formatstring,"%14s %s","",codestring) ;            sprintf(formatstring,"%14s %s","",codestring) ;
           break ;            break ;
       default :        default :
           sprintf(fmt,"%% 7d  %%-5s %%-%ds ",CODE_STRING_SIZE) ;            sprintf(fmt,"%% 7d  %%-5s %%-%ds ",CODE_STRING_SIZE) ;
           sprintf(formatstring,fmt,run.line,cyclestring,codestring) ;            sprintf(formatstring,fmt,run.line,cyclestring,codestring) ;
           MakeLimitedLine(formatstring) ;            MakeLimitedLine(formatstring) ;
           break ;            break ;
   }    }
   
   fprintf(fp_lst,"%s\n",formatstring) ;    fprintf(fp_lst,"%s\n",formatstring) ;
   
   /* Affiche la ligne de code dans la fenêtre si WL */     /* Affiche la ligne de code dans la fenêtre si WL */ 
   if (run.opt[OPT_WL] == TRUE)    if (run.opt[OPT_WL] == TRUE)
       printf("%s\n",formatstring) ;        printf("%s\n",formatstring) ;
   
   return NO_ERROR ;    return NO_ERROR ;
} }
   
   
/*********************************************************************** /***********************************************************************
* *
* Opérations disque pour le fichier binaire * Opérations disque pour le fichier binaire
* *
***********************************************************************/  ***********************************************************************/ 
   
FILE *fp_bin ; FILE *fp_bin ;
   
enum{ enum{
   BIN_FILE,    BIN_FILE,
   LINEAR_FILE,    LINEAR_FILE,
   HYBRID_FILE,    HYBRID_FILE,
   DATA_FILE    DATA_FILE
} ; } ;
   
struct { struct {
   char flag ; /* Flag on/off binaire */     char flag ; /* Flag on/off binaire */ 
   size_t size ; /* Taille du hunk */     size_t size ; /* Taille du hunk */ 
   size_t addr ; /* Adresse du hunk */     size_t addr ; /* Adresse du hunk */ 
   char *data;   /* Buffer de hunk */     char *data;   /* Buffer de hunk */ 
   int type ; /* Type de fichier : BIN_FILE/LINEAR_FILE/DATA_FILE */     int type ; /* Type de fichier : BIN_FILE/LINEAR_FILE/DATA_FILE */ 
   long int pos ; /* Position du header précédent */     long int pos ; /* Position du header précédent */ 
} bin ; } bin ;
   
/* /*
* Sauve le header de fichier binaire * Sauve le header de fichier binaire
*/  */ 
void SaveBinHeader(char flag, size_t size, size_t addr) void SaveBinHeader(char flag, size_t size, size_t addr)
{ {
   fputc (flag, fp_bin) ;    fputc (flag, fp_bin) ;
   fputc (size >> 8, fp_bin) ;    fputc (size >> 8, fp_bin) ;
   fputc (size, fp_bin) ;    fputc (size, fp_bin) ;
   fputc (addr >> 8, fp_bin) ;    fputc (addr >> 8, fp_bin) ;
   fputc (addr, fp_bin) ;    fputc (addr, fp_bin) ;
} }
   
/* /*
* Sauve éventuellement le bloc courant * Sauve éventuellement le bloc courant
*/  */ 
void SaveBinBlock(void) void SaveBinBlock(void)
{ {
   if (bin.size != 0)    if (bin.size != 0)
   {    {
       switch (bin.type)        switch (bin.type)
       {        {
           case DATA_FILE :            case DATA_FILE :
               if ((size_t)run.pc != (bin.addr + bin.size))                if ((size_t)run.pc != (bin.addr + bin.size))
                   PrintError (ERR_BINARY_NOT_LINEAR) ;                    PrintError (ERR_BINARY_NOT_LINEAR) ;
               break;                break;
   
           case LINEAR_FILE :            case LINEAR_FILE :
             /*                if (bin.size > 0xFFFF) */               /*                if (bin.size > 0xFFFF) */ 
               if ((size_t)run.pc != (bin.addr + bin.size))                if ((size_t)run.pc != (bin.addr + bin.size))
                   PrintError (ERR_BINARY_NOT_LINEAR) ;                    PrintError (ERR_BINARY_NOT_LINEAR) ;
               SaveBinHeader (bin.flag, bin.size, bin.addr) ;                SaveBinHeader (bin.flag, bin.size, bin.addr) ;
               break;                break;
   
           default :            default :
               SaveBinHeader (bin.flag, bin.size, bin.addr) ;                SaveBinHeader (bin.flag, bin.size, bin.addr) ;
               break;                break;
       }        }
       fwrite (bin.data, sizeof(char), bin.size, fp_bin) ;        fwrite (bin.data, sizeof(char), bin.size, fp_bin) ;
   }    }
} }
   
   
/* /*
* Sauve une donnée binaire * Sauve une donnée binaire
*/  */ 
void SaveBinChar(unsigned char c) void SaveBinChar(unsigned char c)
{ {
   if ((run.pass == PASS2)    if ((run.pass == PASS2)
    && (run.locked == UNLOCKED)     && (run.locked == UNLOCKED)
    && (run.opt[OPT_NO] == FALSE))     && (run.opt[OPT_NO] == FALSE))
   {    {
       if (((size_t)run.pc != (bin.addr + bin.size))        if (((size_t)run.pc != (bin.addr + bin.size))
        || ((bin.type == BIN_FILE) && (bin.size == 0x0080))         || ((bin.type == BIN_FILE) && (bin.size == 0x0080))
        || (bin.size == 0xffff)         || (bin.size == 0xffff)
        || (bin.size == 0x0000))         || (bin.size == 0x0000))
       {        {
           /* Sauve éventuellement le bloc courant */             /* Sauve éventuellement le bloc courant */ 
           SaveBinBlock() ;            SaveBinBlock() ;
   
           /* Initialise le bloc suivant */             /* Initialise le bloc suivant */ 
           bin.flag = 0x00 ;            bin.flag = 0x00 ;
           bin.size = 0x0000 ;            bin.size = 0x0000 ;
           bin.addr = run.pc ;            bin.addr = run.pc ;
       }        }
       bin.data[bin.size++] = c ;        bin.data[bin.size++] = c ;
   }    }
   run.pc++ ;    run.pc++ ;
   info.size++ ;    info.size++ ;
   check[1][1]++ ;    check[1][1]++ ;
} }
   
/* /*
* Ferme le fichier binaire * Ferme le fichier binaire
*/  */ 
void CloseBin(void) void CloseBin(void)
{ {
   /* Sauve éventuellement le bloc courant */     /* Sauve éventuellement le bloc courant */ 
   SaveBinBlock() ;    SaveBinBlock() ;
   
   /* Sauve éventuellement le bloc de clôture */     /* Sauve éventuellement le bloc de clôture */ 
   if (bin.type != DATA_FILE)    if (bin.type != DATA_FILE)
       SaveBinHeader((char)0xFF,0x00,run.exec) ;        SaveBinHeader((char)0xFF,0x00,run.exec) ;
   if (bin.data != NULL)    if (bin.data != NULL)
   {    {
       free (bin.data);        free (bin.data);
       bin.data = NULL;        bin.data = NULL;
   }    }
   fclose(fp_bin) ;    fclose(fp_bin) ;
} }
   
/* /*
* Ouvre le fichier binaire * Ouvre le fichier binaire
*/  */ 
int OpenBin(char *name) int OpenBin(char *name)
{ {
    bin.data = NULL;     bin.data = NULL;
    bin.size = 0x0000 ;     bin.size = 0x0000 ;
   if ((fp_bin = fopen(name,"wb")) == NULL)    if ((fp_bin = fopen(name,"wb")) == NULL)
       return PrintError(ERR_IO_ERROR) ;        return PrintError(ERR_IO_ERROR) ;
   bin.data = (char *)malloc(65536);    bin.data = (char *)malloc(65536);
   
   return NO_ERROR ;    return NO_ERROR ;
} }
   
   
/*********************************************************************** /***********************************************************************
* *
* Traitement des symboles * Traitement des symboles
* *
***********************************************************************/  ***********************************************************************/ 
   
enum{ enum{
   ARG_VALUE,    ARG_VALUE,
   READ_VALUE,    READ_VALUE,
   SET_VALUE,    SET_VALUE,
   EQU_VALUE,    EQU_VALUE,
   LABEL_VALUE,    LABEL_VALUE,
   MACRO_VALUE    MACRO_VALUE
} ; } ;
   
struct SYMBLIST { struct SYMBLIST {
   struct SYMBLIST *next ;    struct SYMBLIST *next ;
   char name[ARG_MAX_SIZE+2] ; /* Nom du symbole */     char name[ARG_MAX_SIZE+2] ; /* Nom du symbole */ 
   unsigned short value ; /* Valeur du symbole */     unsigned short value ; /* Valeur du symbole */ 
   int error ; /* NO_ERROR/ERR_EXPRESSION_ERROR/ERR_MULTIPLY_DEFINED_SYMBOL */     int error ; /* NO_ERROR/ERR_EXPRESSION_ERROR/ERR_MULTIPLY_DEFINED_SYMBOL */ 
   int type ;  /* SET_VALUE/EQU_VALUE/LABEL_VALUE/MACRO_VALUE */     int type ;  /* SET_VALUE/EQU_VALUE/LABEL_VALUE/MACRO_VALUE */ 
   int time ;  /* Compteur d'apparition */     int time ;  /* Compteur d'apparition */ 
   int pass ;  /* Numéro de pass de la dernière définition */     int pass ;  /* Numéro de pass de la dernière définition */ 
} ; } ;
   
struct SYMBLIST *first_symbol ; struct SYMBLIST *first_symbol ;
   
/* /*
* Initialise le chaînage des symboles * Initialise le chaînage des symboles
* *
* Le premier élément de la liste (pointé par first_symbol) ne contient * Le premier élément de la liste (pointé par first_symbol) ne contient
* éventuellement qu'un pointeur 'next', et le premier caractère de son * éventuellement qu'un pointeur 'next', et le premier caractère de son
* nom est '\0' * nom est '\0'
* Ainsi, le pointeur first_symbol est invariable * Ainsi, le pointeur first_symbol est invariable
*/  */ 
void InitSymbolChain(void) void InitSymbolChain(void)
{ {
   first_symbol = malloc(sizeof(struct SYMBLIST)) ;    first_symbol = malloc(sizeof(struct SYMBLIST)) ;
   first_symbol->next = NULL ;    first_symbol->next = NULL ;
   first_symbol->name[0] = '\0' ;    first_symbol->name[0] = '\0' ;
} }
   
/* /*
* Libère la mémoire pour le chaînage des symboles * Libère la mémoire pour le chaînage des symboles
*/  */ 
void FreeSymbolChain(void) void FreeSymbolChain(void)
{ {
   struct SYMBLIST *current_symbol ;    struct SYMBLIST *current_symbol ;
   while ((current_symbol = first_symbol))    while ((current_symbol = first_symbol))
   {    {
       first_symbol = first_symbol->next ;        first_symbol = first_symbol->next ;
       free(current_symbol) ;        free(current_symbol) ;
   }    }
} }
   
/* Compare deux noms de symboles /* Compare deux noms de symboles
* Le programme renvoie 5 valeurs : * Le programme renvoie 5 valeurs :
* -2 = le 1er nom est inférieur (majuscule != minuscule) * -2 = le 1er nom est inférieur (majuscule != minuscule)
* -1 = le 1er nom est inférieur (majuscule = minuscule) * -1 = le 1er nom est inférieur (majuscule = minuscule)
*  0 = les deux noms sont égaux *  0 = les deux noms sont égaux
*  1 = le 1er nom est supérieur (majuscule = minuscule) *  1 = le 1er nom est supérieur (majuscule = minuscule)
*  2 = le 1er nom est supérieur (majuscule != minuscule) *  2 = le 1er nom est supérieur (majuscule != minuscule)
*/  */ 
int CompareSymbolNames(char *string1, char *string2) int CompareSymbolNames(char *string1, char *string2)
{ {
   int i = 0, j = 0 ;    int i = 0, j = 0 ;
   
   while((*(string1+i) != '\0')    while((*(string1+i) != '\0')
      && (*(string2+i) != '\0')       && (*(string2+i) != '\0')
      && (*(string1+i) == *(string2+i)))       && (*(string1+i) == *(string2+i)))
       i++ ;        i++ ;
   
   j = i ;    j = i ;
   while((*(string1+j) != '\0')    while((*(string1+j) != '\0')
      && (*(string2+j) != '\0')       && (*(string2+j) != '\0')
      && (upper_case(*(string1+j)) == upper_case(*(string2+j))))       && (upper_case(*(string1+j)) == upper_case(*(string2+j))))
       j++ ;        j++ ;
   
   if (upper_case(*(string1+j)) < upper_case(*(string2+j))) return -1 ;    if (upper_case(*(string1+j)) < upper_case(*(string2+j))) return -1 ;
   if (upper_case(*(string1+j)) > upper_case(*(string2+j))) return 1 ;    if (upper_case(*(string1+j)) > upper_case(*(string2+j))) return 1 ;
   if (*(string1+i) < *(string2+i)) return -2 ;    if (*(string1+i) < *(string2+i)) return -2 ;
   if (*(string1+i) > *(string2+i)) return 2 ;    if (*(string1+i) > *(string2+i)) return 2 ;
   return 0 ;    return 0 ;
} }
   
/* /*
* - Ajoute éventuellement un symbole à la liste * - Ajoute éventuellement un symbole à la liste
* - Met éventuellement le symbole à jour * - Met éventuellement le symbole à jour
* - Lit le symbole * - Lit le symbole
*/  */ 
int DoSymbol(char *name, unsigned short value, int type) int DoSymbol(char *name, unsigned short value, int type)
{ {
   int match = 0 ;    int match = 0 ;
   struct SYMBLIST *prev_symbol   = NULL ;    struct SYMBLIST *prev_symbol   = NULL ;
   struct SYMBLIST *insert_symbol = NULL ;    struct SYMBLIST *insert_symbol = NULL ;
   struct SYMBLIST *found_symbol  = NULL ;    struct SYMBLIST *found_symbol  = NULL ;
   struct SYMBLIST *new_symbol    = NULL ;    struct SYMBLIST *new_symbol    = NULL ;
   
   /* Recherche le symbole dans la liste    /* Recherche le symbole dans la liste
    * Le programme en profite pour ranger les symboles dans l'ordre     * Le programme en profite pour ranger les symboles dans l'ordre
    * alphabétique sans distinction entre majuscule et minuscule */      * alphabétique sans distinction entre majuscule et minuscule */ 
   insert_symbol = NULL ;    insert_symbol = NULL ;
   found_symbol = first_symbol ;    found_symbol = first_symbol ;
   do {    do {
       if (insert_symbol == NULL)        if (insert_symbol == NULL)
           prev_symbol = found_symbol ;            prev_symbol = found_symbol ;
       if ((found_symbol = found_symbol->next) != NULL)        if ((found_symbol = found_symbol->next) != NULL)
       {        {
           match = CompareSymbolNames(name,found_symbol->name) ;            match = CompareSymbolNames(name,found_symbol->name) ;
           if ((match == -1) || (match == 0))            if ((match == -1) || (match == 0))
               insert_symbol = found_symbol ;                insert_symbol = found_symbol ;
       }        }
   } while((found_symbol != NULL) && (match > 0)) ;    } while((found_symbol != NULL) && (match > 0)) ;
   
   /* Si trouvé */     /* Si trouvé */ 
   if ((found_symbol != NULL) && (match == 0))    if ((found_symbol != NULL) && (match == 0))
   {    {
       /* Actualise le pass si argument de commande */         /* Actualise le pass si argument de commande */ 
       if (found_symbol->type == ARG_VALUE)        if (found_symbol->type == ARG_VALUE)
           found_symbol->pass = run.pass ;            found_symbol->pass = run.pass ;
   
       if (type == READ_VALUE)        if (type == READ_VALUE)
       {        {
           eval.type = (found_symbol->type == ARG_VALUE) ? EQU_VALUE : found_symbol->type ;            eval.type = (found_symbol->type == ARG_VALUE) ? EQU_VALUE : found_symbol->type ;
           eval.operand = found_symbol->value ;            eval.operand = found_symbol->value ;
           if (found_symbol->pass < run.pass)            if (found_symbol->pass < run.pass)
               eval.pass = found_symbol->pass ;                eval.pass = found_symbol->pass ;
           switch(run.pass)            switch(run.pass)
           {            {
               case PASS1 :                case PASS1 :
                   found_symbol->time++ ;                    found_symbol->time++ ;
                   break ;                    break ;
               case PASS2 :                case PASS2 :
                   if ((found_symbol->time == 0)                    if ((found_symbol->time == 0)
                     && (run.opt[OPT_OP] == TRUE))                      && (run.opt[OPT_OP] == TRUE))
                       PrintError(ERR_LONE_SYMBOL) ;                        PrintError(ERR_LONE_SYMBOL) ;
                   if (found_symbol->error != NO_ERROR)                    if (found_symbol->error != NO_ERROR)
                       return PrintError(found_symbol->error) ;                        return PrintError(found_symbol->error) ;
                   break