summaryrefslogtreecommitdiff
path: root/misc-test
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2010-09-18 08:23:48 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2010-09-18 08:23:48 +0000
commit804cac5bcade6e128573d697c70fb23050f823f7 (patch)
treec6949c5a4651fae005211973635fa7e807b2d591 /misc-test
parent064ad15bb543f5f6649831f47bd4dfd6cb4262af (diff)
download2010-netlemmings-804cac5bcade6e128573d697c70fb23050f823f7.tar.gz
2010-netlemmings-804cac5bcade6e128573d697c70fb23050f823f7.tar.bz2
2010-netlemmings-804cac5bcade6e128573d697c70fb23050f823f7.zip
autres corrections pour que ça compile. Bon, ça compile toujours pas. Ajout pour exemple du compilateur c que j'avais fait à l'insa (et la machine virtuelle pour exec le code aussi)
git-svn-id: file:///var/svn/2010-netlemmings/trunk@32 077b3477-7977-48bd-8428-443f22f7bfda
Diffstat (limited to 'misc-test')
-rw-r--r--misc-test/compilateur_c_en_c/Makefile14
-rw-r--r--misc-test/compilateur_c_en_c/asm_defs.h26
-rw-r--r--misc-test/compilateur_c_en_c/compil.lex80
-rw-r--r--misc-test/compilateur_c_en_c/compil.yy429
-rw-r--r--misc-test/compilateur_c_en_c/reloc.c141
-rw-r--r--misc-test/compilateur_c_en_c/reloc.h37
-rw-r--r--misc-test/compilateur_c_en_c/table_sym.c71
-rw-r--r--misc-test/compilateur_c_en_c/table_sym.h32
-rwxr-xr-xmisc-test/compilateur_c_en_c/test.sh1
-rw-r--r--misc-test/compilateur_c_en_c/tests_parse/test.c4
-rw-r--r--misc-test/compilateur_c_en_c/tests_parse/test2.c8
-rw-r--r--misc-test/compilateur_c_en_c/tests_parse/test3.c29
-rw-r--r--misc-test/compilateur_c_en_c/tests_parse/test4.c13
-rw-r--r--misc-test/compilateur_c_en_c/tests_parse/test5.c12
-rw-r--r--misc-test/compilateur_c_en_c/tests_parse/test6.c16
-rw-r--r--misc-test/compilateur_c_en_c/tests_parse/test7.c6
-rwxr-xr-xmisc-test/compilateur_c_en_c/vm/compil.sh2
-rw-r--r--misc-test/compilateur_c_en_c/vm/pgcd.binbin0 -> 16375 bytes
-rw-r--r--misc-test/compilateur_c_en_c/vm/toto.binbin0 -> 12 bytes
-rwxr-xr-xmisc-test/compilateur_c_en_c/vm/vmbin0 -> 8914 bytes
-rw-r--r--misc-test/compilateur_c_en_c/vm/vm.c88
-rwxr-xr-xmisc-test/compilateur_c_en_c/vm/vm_ncursesbin0 -> 22394 bytes
-rw-r--r--misc-test/compilateur_c_en_c/vm/vm_ncurses.c325
23 files changed, 1334 insertions, 0 deletions
diff --git a/misc-test/compilateur_c_en_c/Makefile b/misc-test/compilateur_c_en_c/Makefile
new file mode 100644
index 0000000..407ea8e
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/Makefile
@@ -0,0 +1,14 @@
+
+default: compil
+
+lex.yy.c: compil.lex
+ flex compil.lex
+ #flex --debug compil.lex
+y.tab.c: compil.yy
+ yacc -v -d compil.yy
+
+compil: y.tab.c lex.yy.c table_sym.c table_sym.h reloc.c reloc.h
+ gcc -g -Wall y.tab.c lex.yy.c table_sym.c reloc.c -ll -o compil
+
+clean:
+ rm compil lex.yy.c y.tab.c y.tab.h y.output || true
diff --git a/misc-test/compilateur_c_en_c/asm_defs.h b/misc-test/compilateur_c_en_c/asm_defs.h
new file mode 100644
index 0000000..6dff988
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/asm_defs.h
@@ -0,0 +1,26 @@
+#ifndef ASM_DEFS_H
+#define ASM_DEFS_H
+
+
+#define I_NOP 0x0
+#define I_ADD 0x1
+#define I_MUL 0x2
+#define I_SOU 0x3
+#define I_DIV 0x4
+#define I_COP 0x5
+#define I_AFC 0x6
+#define I_JMP 0x7
+#define I_JMF 0x8
+#define I_INF 0x9
+#define I_SUP 0xa
+#define I_EQU 0xb
+#define I_PRI 0xc
+
+#define PAD '_'
+#define UNK 0xff
+
+char instructionNames[][4] = {
+ "NOP", "ADD", "MUL", "SOU", "DIV", "COP", "AFC", "JMP", "JMF", "INF", "SUP", "EQU", "PRI"
+};
+
+#endif /* ASM_DEFS_H */
diff --git a/misc-test/compilateur_c_en_c/compil.lex b/misc-test/compilateur_c_en_c/compil.lex
new file mode 100644
index 0000000..f298704
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/compil.lex
@@ -0,0 +1,80 @@
+%{
+ #include "y.tab.h"
+ #include "reloc.h" /* Pour MAX_LABEL_LEN */
+
+ #include <string.h>
+
+%}
+
+%option nounput
+
+
+CHIFFRE [0-9]
+BLANC [ \t\n]
+IDENTIFICATEUR [a-zA-Z][a-zA-Z0-9_]*
+
+%x MLCOMMENT
+ /* %s : inclusive start condition (inclus aussi les règles sans <cond>)
+ %x : exclusive start condition (règles sans <cond> inactives)
+ */
+
+%%
+
+"/*" BEGIN(MLCOMMENT);
+<MLCOMMENT>\n yylineno++;;
+<MLCOMMENT>"*/" BEGIN(INITIAL);
+<MLCOMMENT>. ;
+
+"//"[^\n]*\n yylineno++; /* Single line Comment*/
+
+if return IF;
+else return ELSE;
+while return WHILE;
+do return DO;
+for return FOR;
+switch return SWITCH;
+
+main{BLANC}*\({BLANC}*\) return MAIN;
+printf return PRINTF;
+\{ return '{';
+\} return '}';
+const return CONST;
+int return INT;
+"*" return '*';
+"/" return '/';
+"+" return '+';
+"-" return '-';
+">" return '>';
+"<" return '<';
+"=" return AFF;
+"==" return EGALE;
+"!=" return DIFFERENT;
+"++" return INCR;
+"--" return DECR;
+\( return '(';
+\) return ')';
+{IDENTIFICATEUR} {
+ int lg = strlen(yytext);
+ if ( lg > MAX_LABEL_LEN ) {
+ return LEXERROR;
+ } else {
+ yylval.str = malloc(sizeof(char)*lg);
+ strcpy(yylval.str, yytext);
+ return IDENTIFICATEUR;
+ }
+ }
+{CHIFFRE}+ {
+ yylval.nb = atoi(yytext);
+ return ENTIER;
+ }
+
+"," return ',';
+";" return ';';
+\n yylineno++; /*printf("\n");*/
+{BLANC} /*printf("BLANC");*/
+
+[^ \t\n] fprintf(stderr, "LEX : ERROR : unknown char '%c'", yytext[0]); // TODO standardiser le msg d'erreur
+ /*[ \t] ;*/
+%%
+
+
diff --git a/misc-test/compilateur_c_en_c/compil.yy b/misc-test/compilateur_c_en_c/compil.yy
new file mode 100644
index 0000000..2ed4ad4
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/compil.yy
@@ -0,0 +1,429 @@
+%{
+ #include "y.tab.h"
+ #include "table_sym.h"
+ #include "reloc.h"
+ #include "asm_defs.h"
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+
+ symbolStack tableSym = NULL; // Table de symboles initialement vide
+ extern int yylineno; // Bidouille pour avoir le numero de ligne du lexer ^^
+
+ int SP = 0; // StackPointer
+ int contextProf = 0; // Profondeur de contexte
+ int tempCount = 0; // Compteur pour génerer des noms de temporaires uniques
+ int structCount = 0; // Compteur pour génerer des noms de labels pour les structures unique
+
+
+ int yylex();
+ void yyerror(char *s);
+ void warning(char *msg);
+
+ struct symbolEntry * addSym(char *varName, int contextProf, int readOnly);
+ void genCode(int opcode, int op1, int op2, int op3);
+ void genCodeJump(int opcode, int op1, int op2, int op3, char *targetLabel);
+ void genLabel(char *lbl, char *prefix, int id);
+ struct symbolEntry * createTempo();
+%}
+
+
+%token LEXERROR
+
+%token IF
+%token ELSE
+%token WHILE
+%token DO
+%token FOR
+%token SWITCH
+
+%token MAIN
+%token CONST
+%token INT
+%token PRINTF
+
+%token AFF
+ /* TODO : += -= *= /= */
+%nonassoc EGALE DIFFERENT
+%nonassoc '>' '<'
+%left '+' '-'
+%left '*' '/'
+
+%token INCR DECR /* TODO : priorité ? */
+ /* TODO : affectations conditionnelles : <cond>?<then>:<else> */
+
+%token <str> IDENTIFICATEUR
+%token <nb> ENTIER
+
+
+%type <nb> Entier
+
+%type <nb> InitVarLoc
+%type <sym> DeclVarLoc1
+%type <sym> DeclConst1
+
+%type <sym> Symbole
+%type <sym> Constante
+
+%type <sym> LValue
+%type <sym> RValue
+
+%type <nb> BeginIf
+%type <nb> BeginFor
+%type <nb> BeginWhile
+%type <nb> BeginDoWhile
+%type <nb> BeginSwitch
+
+%union { int nb; char *str; struct symbolEntry *sym; }
+
+%start Prog
+%%
+
+Prog: MAIN Block { /* printSymTable(tableSym);*/ }
+Block: '{' { contextProf++; }
+ Declarations
+ Instructions
+ '}' { /* printf("Block\n");*/
+ /*printSymTable(tableSym);*/
+ cleanSymStack(&tableSym, --contextProf);
+ }
+
+BlockOuInstr: Block
+ | Instruction
+
+
+Declarations: /*vide*/ { printf("Declaration vide\n"); }
+ | Decl ';' Declarations
+
+Decl: INT DeclVarLocList { /*printf("Decl\n");*/ }
+ | CONST INT DeclConstList
+ | error /* TODO : essayer de perdre moins d'informations */
+
+/***********************
+** Liste de variables **
+***********************/
+DeclVarLocList: DeclVarLoc { /* printf("DeclVarLoc\n");*/ }
+ | DeclVarLoc ',' DeclVarLocList
+
+
+DeclVarLoc: DeclVarLoc1 { /*printf("Variable non initalisee : '%s'\n", $1->symName);*/ }
+ | DeclVarLoc1 InitVarLoc {
+ //printf("Variable initalisee '%s' à %i\n", $1->symName, $2);
+ if ( $1 == NULL )
+ {
+ yyerror("Symbol already declared");
+ YYERROR;
+ } else {
+ genCode(I_AFC, $1->address, $2, PAD);
+ $1->initialized = 1; // oui (et pas peut-être, car nouveau profondeur)
+ }
+ }
+
+DeclVarLoc1: IDENTIFICATEUR { $$ = addSym($1, contextProf, 0); }
+
+InitVarLoc: AFF Entier { $$=$2; /*printf("Init à la valeur %i\n", $2);*/ }
+
+/************************
+** Liste de constantes **
+************************/
+DeclConstList: DeclConst
+ | DeclConst ',' DeclConstList
+
+DeclConst: DeclConst1 AFF Entier {
+ if ( $1 == NULL ) {
+ yyerror("Symbol already declared");
+ YYERROR;
+ } else {
+ genCode(I_AFC, $1->address, $3, PAD);
+ $1->initialized = 1; // oui (et pas peut-être, car nouveau profondeur)
+ }
+ }
+
+DeclConst1: IDENTIFICATEUR { $$ = addSym($1, contextProf, 1); }
+
+/*****************
+** Instructions **
+*****************/
+Instructions: /* Vide */
+ | Instruction Instructions /* TODO : ajouter gestion d'erreur */
+
+Instruction: PRINTF '(' RValue ')' ';'
+ {
+ if ( $3->initialized == 0) // non
+ {
+ yyerror("Symbol uninitialized");
+ YYERROR;
+ } else {
+ if ( $3->initialized == 2 ) // peut-etre
+ {
+ warning("Symbol may be uninitialized");
+ }
+ genCode(I_PRI, $3->address, PAD, PAD);
+ }
+ }
+
+ | LValue AFF RValue ';' {
+ genCode(I_COP, $1->address, $3->address, PAD);
+
+ if ( contextProf > 0 )
+ {
+ $1->initialized=2; // TODO peut-être (gestion très limitée car nécessiterai un arbre de contextes numerotés au minimum pour être plus fin)
+ } else {
+ $1->initialized=1; // oui (on est dans le main)
+ }
+ }
+
+ | BeginIf Block/*OuInstr*/ { // TODO : comprendre pourquoi ça génère un décalage/réduction
+ char lbl[MAX_LABEL_LEN];
+ genLabel(lbl, "if1_",$1);
+ writeLabel(lbl);
+ }
+
+
+ | BeginIf Block/*OuInstr*/ ELSE {
+ char lbl[MAX_LABEL_LEN];
+ genLabel(lbl, "if2_", $1);
+ genCodeJump(I_JMP, UNK, PAD, PAD, lbl);
+
+ genLabel(lbl, "if1_", $1);
+ writeLabel(lbl);
+ }
+ BlockOuInstr {
+ char lbl[MAX_LABEL_LEN];
+ genLabel(lbl,"if2_",$1);
+ writeLabel(lbl);
+ }
+
+ | BeginWhile BlockOuInstr {
+ char lbl[MAX_LABEL_LEN];
+ genLabel(lbl, "wh1_", $1);
+ genCodeJump(I_JMP, UNK, PAD, PAD, lbl);
+
+ genLabel(lbl, "wh2_", $1);
+ writeLabel(lbl);
+ }
+
+ | BeginFor '(' Instruction {
+ char lbl[MAX_LABEL_LEN];
+ genLabel(lbl, "for1_",$1);
+ }
+ RValue {
+ char lbl[MAX_LABEL_LEN];
+ genLabel(lbl, "for2_",$1);
+ //genCodeJump(I_JMF, $4->address, PAD, PAD, lbl); TODO comprendre pourquoi compile pas
+ }
+ IDENTIFICATEUR INCR ')' Block /* Bricolage pour pas avoir a différer de la génération de code :S */
+ {
+ //struct symbolEntry *forVar;
+ /* TODO : choper le symbole de $5 puis genCode... */
+ yyerror("For not yet fully implemented !");
+
+ char lbl1[MAX_LABEL_LEN], lbl2[MAX_LABEL_LEN];
+ genLabel(lbl1, "for1_", $1); // FIXME : $1 pointe vers IDENTIFICATEUR ???
+ genLabel(lbl2, "for2_", $1);
+
+ genCodeJump(I_JMP, UNK, PAD, PAD, lbl1);
+
+ writeLabel(lbl2);
+ }
+
+ | BeginDoWhile BlockOuInstr WHILE '(' RValue ')' ';'
+ {
+ char lbl1[MAX_LABEL_LEN], lbl2[MAX_LABEL_LEN];
+ genLabel(lbl1, "do1_", $1);
+ genLabel(lbl2, "do2_", $1);
+
+ genCodeJump(I_JMF, $5->address, UNK, PAD, lbl2);
+ genCodeJump(I_JMP, UNK, PAD, PAD, lbl1);
+
+ writeLabel(lbl2);
+ }
+
+BeginFor: FOR { $$=structCount++; }
+BeginSwitch: SWITCH { $$=structCount++; }
+
+BeginIf: IF '(' RValue ')' {
+ char lbl[MAX_LABEL_LEN];
+ $$=structCount++;
+ genLabel(lbl, "if1_", $$);
+ genCodeJump(I_JMF, $3->address, UNK, PAD, lbl);
+ }
+
+BeginWhile: WHILE '(' RValue ')' {
+ char lbl[MAX_LABEL_LEN];
+ $$=structCount++;
+ genLabel(lbl, "wh1_", $$);
+ writeLabel(lbl);
+ genLabel(lbl, "wh2_", $$);
+ genCodeJump(I_JMF, $3->address, UNK, PAD, lbl);
+ }
+
+BeginDoWhile: DO {
+ char lbl[MAX_LABEL_LEN];
+ $$=structCount++;
+ genLabel(lbl, "do1_", $$);
+ writeLabel(lbl);
+ }
+
+Symbole: IDENTIFICATEUR {
+ $$=symbolFind(tableSym, $1, contextProf, contextProf);
+ if ( $$==NULL ) {
+ yyerror("Symbol not declared");
+ YYERROR;
+ }
+ }
+
+LValue: Symbole {
+ if ( $1->readOnly )
+ {
+ $$=NULL;
+ yyerror("Not a valid LValue : is read-only");
+ YYERROR;
+ } else {
+ $$=$1;
+ }
+ }
+/* Version de base, sans optimisation de calculs ni constantes composées
+RValue: Constante { $$=$1; }
+ | Symbole { $$=$1; }
+ | '(' RValue ')' { $$=$2; }
+ | RValue '+' RValue { $$=createTempo(); genCode(I_ADD, $$->address, $1->address, $3->address); }
+ | RValue '*' RValue { $$=createTempo(); genCode(I_MUL, $$->address, $1->address, $3->address); }
+ | RValue '-' RValue { $$=createTempo(); genCode(I_SOU, $$->address, $1->address, $3->address); }
+ | RValue '/' RValue { $$=createTempo(); genCode(I_DIV, $$->address, $1->address, $3->address); }
+ | RValue '<' RValue { $$=createTempo(); genCode(I_INF, $$->address, $1->address, $3->address); }
+ | RValue '>' RValue { $$=createTempo(); genCode(I_SUP, $$->address, $1->address, $3->address); }
+ | RValue EGALE RValue { $$=createTempo(); genCode(I_EQU, $$->address, $1->address, $3->address); }
+
+
+Constante: ENTIER { $$=createTempo(); genCode(I_AFC, $$->address, $1, PAD); $$->initialized=1; $$->readOnly=1; }
+*/
+
+
+RValue: Constante { $$=$1; }
+ | Symbole { $$=$1; }
+ | '(' RValue ')' { $$=$2; }
+ | AddsOrSubs { $$=$1 }
+ | Muls { $$=$1 }
+ | RValue '/' RValue { $$=createTempo(); genCode(I_DIV, $$->address, $1->address, $3->address); }
+ | RValue '<' RValue { $$=createTempo(); genCode(I_INF, $$->address, $1->address, $3->address); }
+ | RValue '>' RValue { $$=createTempo(); genCode(I_SUP, $$->address, $1->address, $3->address); }
+ | RValue EGALE RValue { $$=createTempo(); genCode(I_EQU, $$->address, $1->address, $3->address); }
+
+AddOrSubs: AddOrSubs '+' RValue
+
+ { $$=createTempo(); genCode(I_ADD, $$->address, $1->address, $3->address); }
+
+
+/* Vieux truc :
+// TODO : ça marche pas avec a=2-a; --> obligé d'avoir un GLR parser ?
+Entier: ENTIER { $$=$1; }
+ | '(' Entier ')' { $$=$2; }
+ | Entier '+' Entier %prec CST_PLUS { $$=$1+$3; }
+ | Entier '*' Entier %prec CST_MUL { $$=$1*$3; }
+ | Entier '-' Entier %prec CST_MOINS { $$=$1-$3; }
+ | Entier '/' Entier %prec CST_DIV { $$=$1/$3; }
+ | Entier '<' Entier %prec CST_INF { $$=$1<$3; }
+ | Entier '>' Entier %prec CST_SUP { $$=$1>$3; }
+ | Entier EGALE Entier %prec CST_EGALE { $$=$1==$3; }
+
+*/
+%%
+void yyerror(char *s)
+{
+ //fprintf(stderr, "Syntax Error : '%s' at l%d,c%d-l%d,c%d\n", s, @$.first_column, @$.last_line, @$.last_column); // Nécessite l'option %locations et un lexer qui va bien
+ fprintf(stderr, "(stdin):%i: error: %s\n", yylineno, s);
+}
+
+void warning(char *msg)
+{
+ fprintf(stderr, "(stdin):%i: warning: %s\n", yylineno, msg);
+}
+
+int main(int argc, char **argv)
+{ // Par défaut, c'est l'analyse LEXICALE qui est lancée !
+ if ( argc != 2 ) {
+ fprintf(stderr, "Usage : %s <nom_fichier_sortie>\n", argv[0]);
+ exit(-1);
+ }
+
+ printf("Opening...\n");
+ openWriteDestFiles(argv[1]);
+ printf("Parsing...\n"); // TODO : fichier d'entrée
+ yyparse();
+ printf("Closing...\n");
+ closeDestFiles();
+ printf("Linking...\n");
+ linker(argv[1],0); // TODO tester autre que 0
+
+ return 0;
+}
+
+// TODO : passer &tableSym en param
+struct symbolEntry * addSym(char *varName, int contextProf, int readOnly)
+{
+ struct symbolEntry *sym = NULL;
+
+ if ( symbolFind(tableSym, varName, contextProf, contextProf) == NULL )
+ {
+ sym = malloc(1*sizeof(struct symbolEntry));
+
+ sym->symName = malloc(strlen(varName) * sizeof(char));
+ strcpy(sym->symName,varName);
+ sym->address = SP++;
+ sym->readOnly = readOnly;
+ sym->initialized = 0;
+ sym->contextProf = contextProf;
+
+
+ symbolPush(&tableSym,sym);
+ } /* else return NULL */
+
+
+ return sym;
+}
+
+void genCode(int opcode, int op1, int op2, int op3)
+{
+ writeCode(opcode,op1,op2,op3);
+}
+
+void genCodeJump(int opcode, int op1, int op2, int op3, char *targetLabel)
+{
+ int addr=writeCode(opcode,op1,op2,op3);
+ switch (opcode) {
+ case I_JMP:
+ writeHole(addr+1, targetLabel);
+ break;
+ case I_JMF:
+ writeHole(addr+2, targetLabel);
+ break;
+ default:
+ yyerror("Internal error : genCodeJump called whiout a I_JMP or I_JMF opcode");
+ /* YYERROR; TODO : dégager...*/
+ break;
+ }
+}
+
+void genLabel(char *lbl, char *prefix, int id)
+{
+ sprintf(lbl, "!%s%d", prefix, id);
+}
+
+struct symbolEntry * createTempo()
+{
+ char tempoName[MAX_LABEL_LEN];
+ struct symbolEntry *sym = NULL;
+
+ sprintf(tempoName, "!tempo%d", tempCount++); // TODO : si tempo trop long, bug
+ sym = addSym(tempoName, contextProf, 1);
+ if ( sym == NULL ) {
+ yyerror("Error while declaring a temp variable");
+ /*YYERROR;*/
+ }
+ return sym;
+}
+
+// TODO : variable globales en dehors du main ?
diff --git a/misc-test/compilateur_c_en_c/reloc.c b/misc-test/compilateur_c_en_c/reloc.c
new file mode 100644
index 0000000..511a4ec
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/reloc.c
@@ -0,0 +1,141 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "reloc.h"
+
+FILE *fdObj, *fdLbl, *fdHol, *fdBin;
+
+
+
+void findLabelAddress(char *label, char *buf);
+
+int openWriteDestFiles(char fileName[])
+{
+ char *fnObj = malloc(strlen(fileName)+4+1);
+ char *fnLbl = malloc(strlen(fileName)+4+1);
+ char *fnHol = malloc(strlen(fileName)+4+1);
+
+ strcpy(fnObj, fileName);
+ strcpy(fnLbl, fileName);
+ strcpy(fnHol, fileName);
+
+ strcat(fnObj, EXT_CODE);
+ strcat(fnLbl, EXT_LABELS);
+ strcat(fnHol, EXT_HOLES);
+
+ fdObj = fopen(fnObj, "w");
+ fdLbl = fopen(fnLbl, "w");
+ fdHol = fopen(fnHol, "w");
+
+ return (fdObj!=NULL) && (fdLbl!=NULL) && (fdHol!=NULL);
+}
+
+int writeCode(int opcode, int op1, int op2, int op3)
+{
+ char ins[4];
+ int currAddr;
+
+ ins[0]=opcode & 0xFF;
+ ins[1]=op1 & 0xFF;
+ ins[2]=op2 & 0xFF;
+ ins[3]=op3 & 0xFF; // TODO : est-ce bien propre ? Little ou big endian ?
+
+ currAddr = (int) ftell(fdObj);
+ fwrite(ins, sizeof(char), 4, fdObj);
+
+ return currAddr;
+}
+
+void writeLabel(char *label)
+{
+ fprintf(fdLbl, "0x%02x\t%s\n", (int)ftell(fdObj), label);
+}
+
+void writeHole(int holeAddr, char *label)
+{
+ fprintf(fdHol, "0x%02x\t%s\n", holeAddr, label);
+}
+
+void closeDestFiles()
+{
+ fclose(fdObj); fclose(fdLbl); fclose(fdHol);
+}
+
+/*
+int ftellCode(){
+ return ftell(fdObj);
+}*/
+
+void linker(char fileName[], int baseAddress) // Génère le .bin a partir des .obj, .lbl, .hol
+{
+ char *fnObj = malloc(strlen(fileName)+4+1);
+ char *fnLbl = malloc(strlen(fileName)+4+1);
+ char *fnHol = malloc(strlen(fileName)+4+1);
+ char *fnBin = malloc(strlen(fileName)+4+1);
+
+ strcpy(fnObj, fileName);
+ strcpy(fnLbl, fileName);
+ strcpy(fnHol, fileName);
+ strcpy(fnBin, fileName);
+
+ strcat(fnObj, EXT_CODE);
+ strcat(fnLbl, EXT_LABELS);
+ strcat(fnHol, EXT_HOLES);
+ strcat(fnBin, EXT_EXEC);
+
+ fdObj = fopen(fnObj, "r");
+ fdLbl = fopen(fnLbl, "r");
+ fdHol = fopen(fnHol, "r");
+ fdBin = fopen(fnBin, "w");
+
+ int holeAddr=0, i;
+ char label[MAX_LABEL_LEN];
+ char buf;
+
+ while ( fscanf(fdHol, "0x%02x\t%s\n", &holeAddr, label) == 2 )
+ {
+ int targetAddr = ftell(fdObj);
+
+ for(i=0; i<holeAddr-targetAddr; i++)
+ {
+ fread(&buf, 1, 1, fdObj);
+ fwrite(&buf, 1, 1, fdBin);
+ }
+ fread(&buf, 1, 1, fdObj); // Saute le trou dans le fichier d'entrée
+
+ findLabelAddress(label, &buf);
+
+ fwrite(&buf, 1, 1, fdBin); // Bouche le trou dans le fichier de sortie
+
+ }
+
+ while (fread(&buf, 1, 1, fdObj)) // Ecrit la fin du fichier
+ {
+ fwrite(&buf, 1, 1, fdBin);
+ }
+
+ fclose(fdObj);
+ fclose(fdLbl);
+ fclose(fdHol);
+ fclose(fdBin);
+}
+
+void findLabelAddress(char *label, char *buf) {
+
+ int relAddr, found=0;
+ char currLabel[MAX_LABEL_LEN];
+
+ fseek(fdLbl, 0, SEEK_SET);
+
+ while ( !found && fscanf(fdLbl, "0x%02x\t%s\n", &relAddr, currLabel) == 2 )
+ {
+ found = ( strcmp(currLabel, label) == 0 );
+ *buf = (char) (relAddr & 0xFF);
+ }
+
+ if (!found)
+ {
+ fprintf(stderr, "linker: ERROR : '%s' not found in .lbl file\n", label);
+ }
+}
diff --git a/misc-test/compilateur_c_en_c/reloc.h b/misc-test/compilateur_c_en_c/reloc.h
new file mode 100644
index 0000000..684030b
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/reloc.h
@@ -0,0 +1,37 @@
+#ifndef RELOC_H
+#define RELOC_H
+
+#define EXT_CODE ".obj"
+#define EXT_LABELS ".lbl"
+#define EXT_HOLES ".hol"
+#define EXT_EXEC ".bin"
+#define MAX_LABEL_LEN 16
+
+#include "table_sym.h"
+#include <stdio.h>
+
+struct labels {
+ char *label;
+ int relAddr;
+};
+
+struct holes {
+ int holeAddr;
+ char *label;
+};
+
+int openWriteDestFiles(char fileName[]);
+
+
+int writeCode(int opcode, int op1, int op2, int op3); // Retourne l'adresse relative du debut de l'instruction
+void writeLabel(char *label);
+void writeHole(int holeAddr, char *label);
+
+void closeDestFiles();
+
+//int ftellCode(); // Retourne l'adresse relative de la prochaine instruction à écrire dans le fichier .obj
+
+void linker(char fileName[], int baseAddress); // Génère le .bin a partir des .obj, .lbl, .hol
+
+
+#endif /* RELOC_H */
diff --git a/misc-test/compilateur_c_en_c/table_sym.c b/misc-test/compilateur_c_en_c/table_sym.c
new file mode 100644
index 0000000..9fa3803
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/table_sym.c
@@ -0,0 +1,71 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "table_sym.h"
+
+void symbolPush(symbolStack *symStack, struct symbolEntry *sym)
+{
+ struct symbolStackCell *newCell = malloc(sizeof(struct symbolStackCell));
+ newCell->symbol = sym;
+ newCell->next = *symStack;
+ *symStack=newCell;
+}
+
+struct symbolEntry * symbolFind(symbolStack symStack, char *symName, int contextMinProf, int contextMaxProf)
+{
+ struct symbolEntry *res = NULL;
+ int trouve = 0;
+ while (!trouve && symStack != NULL)
+ {
+ if ( strcmp(symStack->symbol->symName,symName) == 0
+ && symStack->symbol->contextProf >= contextMinProf
+ && symStack->symbol->contextProf <= contextMaxProf )
+ {
+ trouve=1;
+ res=symStack->symbol;
+ } else {
+ symStack=symStack->next;
+ }
+ }
+ return res;
+}
+
+void printSymTable(symbolStack symStack)
+{
+ printf("DEBUG :Table des symboles\n");
+ printf("const?\t nom variable\taddress\tinit?\tcontextProf\n");
+ for(;symStack!=NULL;symStack=symStack->next)
+ {
+ if ( symStack->symbol->readOnly )
+ {
+ printf("const\t%20s\t%x\t%i\t%i\n", symStack->symbol->symName,
+ symStack->symbol->address,
+ symStack->symbol->initialized,
+ symStack->symbol->contextProf);
+ } else {
+ printf("\t%20s\t%x\t%i\t%i\n", symStack->symbol->symName,
+ symStack->symbol->address,
+ symStack->symbol->initialized,
+ symStack->symbol->contextProf);
+ }
+ }
+
+ printf("FIN DEBUG\n");
+}
+
+void cleanSymStack(symbolStack *symStack, int contextProf)
+{
+ printf("void cleanSymStack(symbolStack *symStack, %i)\n", contextProf);
+ while ((*symStack)!=NULL && ((*symStack)->symbol->contextProf > contextProf))
+ {
+ symbolStack next = (*symStack)->next;
+
+ free( (*symStack)->symbol->symName );
+ free( (*symStack)->symbol );
+ free( (*symStack) );
+
+ *symStack = next;
+ }
+}
+
diff --git a/misc-test/compilateur_c_en_c/table_sym.h b/misc-test/compilateur_c_en_c/table_sym.h
new file mode 100644
index 0000000..e26977f
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/table_sym.h
@@ -0,0 +1,32 @@
+#ifndef TABLE_SYM_H
+#define TABLE_SYM_H
+
+struct symbolEntry {
+ char * symName;
+ unsigned int address;
+ int readOnly;
+ int initialized; // 0 : non , 1: oui, 2: peut-être ^^
+ unsigned int contextProf;
+};
+
+
+// TODO : déclarer liste chainée d'instructions
+struct instruction {
+// unsigned int numi; // Numéro d'instruction
+ char *label; // Label de la ligne courante (0 = pas de label)
+ unsigned int opcode; // Code operation (cf table correspondance pour avoir la forme textuelle)
+ unsigned int op1, op2, op3; // Operandes
+};
+
+struct symbolStackCell {
+ struct symbolEntry *symbol;
+ struct symbolStackCell *next;
+};
+
+typedef struct symbolStackCell* symbolStack;
+
+void symbolPush(symbolStack *symStack, struct symbolEntry *sym);
+struct symbolEntry * symbolFind(symbolStack symStack, char *symName, int contextMinProf, int contextMaxProf);
+void printSymTable(symbolStack symStack);
+void cleanSymStack(symbolStack *symStack, int contextProf);
+#endif /*TABLE_SYM_H*/
diff --git a/misc-test/compilateur_c_en_c/test.sh b/misc-test/compilateur_c_en_c/test.sh
new file mode 100755
index 0000000..df83422
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/test.sh
@@ -0,0 +1 @@
+make clean && make && ./compil out < tests_parse/test4.c && disasm/disasm out.bin
diff --git a/misc-test/compilateur_c_en_c/tests_parse/test.c b/misc-test/compilateur_c_en_c/tests_parse/test.c
new file mode 100644
index 0000000..9cd70a5
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/tests_parse/test.c
@@ -0,0 +1,4 @@
+main ( ) {
+ int a = 3, b, c=4;
+ const int d = 3, e=5, c=6;
+}
diff --git a/misc-test/compilateur_c_en_c/tests_parse/test2.c b/misc-test/compilateur_c_en_c/tests_parse/test2.c
new file mode 100644
index 0000000..1b5f66c
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/tests_parse/test2.c
@@ -0,0 +1,8 @@
+main ( ) {
+ int a = 3, b, c=4;
+/* const int d = 3, e=5, c=6;
+ * blabla
+ */
+ const int d = 3, e=5, c=6;
+
+}
diff --git a/misc-test/compilateur_c_en_c/tests_parse/test3.c b/misc-test/compilateur_c_en_c/tests_parse/test3.c
new file mode 100644
index 0000000..2905795
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/tests_parse/test3.c
@@ -0,0 +1,29 @@
+// Coucou
+main ( ) {
+ int a = 3, b, c=4;
+/* const int d = 3, e=5, c=6;
+ * blabla
+ */
+ const int d = 3, e=5, c=6, f=3;
+ int a = 6;
+ int za = 6;
+
+ printf(a);
+ // Pas clop
+ printf(b);
+ printf(d);
+ printf(za);
+
+ a=c;
+ //a=b;
+ b=a;
+ a=b;
+
+ if ( 0 ) {
+ int c=7;
+ b=a;
+ printf(b); // On ne peut pas simplement gérer ce cas pour ne pasafficher de Warning
+ }
+ printf(b);// Car ce cas est possible ^^
+
+}
diff --git a/misc-test/compilateur_c_en_c/tests_parse/test4.c b/misc-test/compilateur_c_en_c/tests_parse/test4.c
new file mode 100644
index 0000000..0102947
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/tests_parse/test4.c
@@ -0,0 +1,13 @@
+// Coucou
+main ( ) {
+ if ( 0 ) {
+ printf(1);
+ }
+ printf(2);
+ if ( 0 ) {
+ printf(3);
+ } else {
+ printf(4);
+ }
+ printf(5);
+}
diff --git a/misc-test/compilateur_c_en_c/tests_parse/test5.c b/misc-test/compilateur_c_en_c/tests_parse/test5.c
new file mode 100644
index 0000000..9afb03c
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/tests_parse/test5.c
@@ -0,0 +1,12 @@
+// Coucou
+main ( ) {
+ if ( 1 ) {
+ printf(1);
+ if (2) { printf(2); }
+ printf(3);
+ } else {
+ printf(4);
+ if (5) { printf(5); } else { printf(6); }
+ printf(7);
+ }
+}
diff --git a/misc-test/compilateur_c_en_c/tests_parse/test6.c b/misc-test/compilateur_c_en_c/tests_parse/test6.c
new file mode 100644
index 0000000..f177284
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/tests_parse/test6.c
@@ -0,0 +1,16 @@
+// Coucou
+main ( ) {
+ if ( 0 ) {
+ printf(1);
+ }
+ printf(2);
+ while ( 0 ) {
+ printf(3);
+ }
+
+ do {
+ printf(4);
+ } while (0);
+
+ printf(5);
+}
diff --git a/misc-test/compilateur_c_en_c/tests_parse/test7.c b/misc-test/compilateur_c_en_c/tests_parse/test7.c
new file mode 100644
index 0000000..926dad3
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/tests_parse/test7.c
@@ -0,0 +1,6 @@
+// Coucou
+main ( ) {
+ int a = 1+2-3*2/2<12*8+4;
+ a = a*2-a>a*a*a;
+ printf(a);
+}
diff --git a/misc-test/compilateur_c_en_c/vm/compil.sh b/misc-test/compilateur_c_en_c/vm/compil.sh
new file mode 100755
index 0000000..42d7087
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/vm/compil.sh
@@ -0,0 +1,2 @@
+gcc -Wall -o vm vm.c
+gcc -Wall -g -lpanel -lncurses -o vm_ncurses vm_ncurses.c
diff --git a/misc-test/compilateur_c_en_c/vm/pgcd.bin b/misc-test/compilateur_c_en_c/vm/pgcd.bin
new file mode 100644
index 0000000..d627e98
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/vm/pgcd.bin
Binary files differ
diff --git a/misc-test/compilateur_c_en_c/vm/toto.bin b/misc-test/compilateur_c_en_c/vm/toto.bin
new file mode 100644
index 0000000..0c72cb1
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/vm/toto.bin
Binary files differ
diff --git a/misc-test/compilateur_c_en_c/vm/vm b/misc-test/compilateur_c_en_c/vm/vm
new file mode 100755
index 0000000..88697bb
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/vm/vm
Binary files differ
diff --git a/misc-test/compilateur_c_en_c/vm/vm.c b/misc-test/compilateur_c_en_c/vm/vm.c
new file mode 100644
index 0000000..4e1cf24
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/vm/vm.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../asm_defs.h"
+
+#define MEM_SIZE 256
+
+
+int main(int argc, char *argv[])
+{
+ FILE *fdBin;
+ char buf[4];
+ char *mem = calloc(MEM_SIZE, sizeof(char));
+
+ if ( argc !=2 )
+ {
+ fprintf(stderr, "Usage : %s <bin_file>\n", argv[0]);
+ return -1;
+ }
+
+ fdBin = fopen(argv[1], "r");
+ if ( fdBin == NULL )
+ {
+ fprintf(stderr, "ERROR : can't open file '%s'\n", argv[1]);
+ return -1;
+ }
+
+ while (fread(buf, 4, 1, fdBin))
+ {
+ //TODO : vérification pour l'opCode, ne pas aller en dehors de la table si code erroné
+ printf("@0x%02x:\t%s\t0x%02x\t0x%02x\t0x%02x\n",
+ (int) ftell(fdBin),
+ instructionNames[(int)buf[0]],
+ (unsigned int) buf[1] & 0xFF,
+ (unsigned int) buf[2] & 0xFF,
+ (unsigned int) buf[3] & 0xFF
+ );
+
+ switch (buf[0])
+ {
+ case I_NOP:
+ break;
+ case I_ADD:
+ mem[(int)buf[1]] = mem[(int)buf[2]] + mem[(int)buf[3]];
+ break;
+ case I_MUL:
+ mem[(int)buf[1]] = mem[(int)buf[2]] * mem[(int)buf[3]];
+ break;
+ case I_SOU:
+ mem[(int)buf[1]] = mem[(int)buf[2]] - mem[(int)buf[3]];
+ break;
+ case I_DIV:
+ mem[(int)buf[1]] = mem[(int)buf[2]] / mem[(int)buf[3]];
+ break;
+ case I_COP:
+ mem[(int)buf[1]] = mem[(int)buf[2]];
+ break;
+ case I_AFC:
+ mem[(int)buf[1]] = buf[2];
+ break;
+ case I_JMP:
+ fseek(fdBin, (long)buf[1], SEEK_SET);
+ break;
+ case I_JMF:
+ if (!mem[(int)buf[1]]) { fseek(fdBin, (long)buf[2]&0xFF, SEEK_SET); }
+ break;
+ case I_INF:
+ mem[(int)buf[1]] = mem[(int)buf[2]] < mem[(int)buf[3]];
+ break;
+ case I_SUP:
+ mem[(int)buf[1]] = mem[(int)buf[2]] > mem[(int)buf[3]];
+ break;
+ case I_EQU:
+ mem[(int)buf[1]] = mem[(int)buf[2]] == mem[(int)buf[3]];
+ break;
+ case I_PRI:
+ printf("PRI : %x\n", (int) mem[(int)buf[1]]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ fclose(fdBin);
+
+ return 0;
+}
diff --git a/misc-test/compilateur_c_en_c/vm/vm_ncurses b/misc-test/compilateur_c_en_c/vm/vm_ncurses
new file mode 100755
index 0000000..f60ca8e
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/vm/vm_ncurses
Binary files differ
diff --git a/misc-test/compilateur_c_en_c/vm/vm_ncurses.c b/misc-test/compilateur_c_en_c/vm/vm_ncurses.c
new file mode 100644
index 0000000..8ce9be8
--- /dev/null
+++ b/misc-test/compilateur_c_en_c/vm/vm_ncurses.c
@@ -0,0 +1,325 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <panel.h> // apt-get install libncurses5-dev et ajouter -lpanel -lncurses pour linker
+#include <unistd.h> // sleep()
+
+#include "../asm_defs.h"
+
+#define MEM_SIZE 256
+#define APP_TITLE "MyCPU Emulator - INSA Toulouse 2009 - Ludovic POUZENC"
+#define MIN_COLS 64
+#define MIN_LINES 32
+#define NB_WINS 3
+
+struct rect { int w,h,x,y; };
+struct rect wins_coords[NB_WINS];
+struct hint { char *name, key; };
+struct hint hints[] = { {"Help",'H'}, {"Menu",'M'},{"Memory",'e'},{"Code",'C'},{"Step",'S'},{"Quit",'Q'} };
+
+FILE *fdBin;
+char *mem;
+int i_count=0;
+
+void init_curse();
+void init_wins(WINDOW **wins);
+void init_panels(PANEL ** panels, WINDOW **wins);
+void win_show(WINDOW *win, char *label, int label_color);
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
+void draw_head_and_foot();
+void print_hints(struct hint hints[], int n);
+void wprinthls(WINDOW *win, char text[]);
+void wprintline(WINDOW *win, int lineno, char text[], int text_len);
+
+
+void do_exec_step(WINDOW *dest_win);
+void refresh_mem_display(WINDOW *dest_win);
+
+
+int main(int argc, char *argv[])
+{
+ WINDOW *my_wins[NB_WINS];
+ PANEL *my_panels[NB_WINS];
+ int ch;
+
+ mem = calloc(MEM_SIZE, sizeof(char));
+
+ if ( argc !=2 )
+ {
+ fprintf(stderr, "Usage : %s <bin_file>\n", argv[0]);
+ return -1;
+ }
+
+ fdBin = fopen(argv[1], "r");
+ if ( fdBin == NULL )
+ {
+ fprintf(stderr, "ERROR : can't open file '%s'\n", argv[1]);
+ return -1;
+ }
+
+ init_curse();
+
+ if ( COLS < MIN_COLS || LINES < MIN_LINES ) {
+ endwin();
+ fprintf(stderr, "ERROR : This application requires at least a %dx%d chars terminal\n", MIN_COLS, MIN_LINES);
+ return -1;
+ }
+
+ init_wins(my_wins);
+ init_panels(my_panels, my_wins);
+ update_panels();
+ draw_head_and_foot();
+ doupdate();
+
+ while((ch = getch()) != 'q')
+ {
+ switch(ch)
+ {
+ case 's':
+ do_exec_step(my_wins[2]);
+ refresh_mem_display(my_wins[1]);
+ break;
+ default:
+ flash(); beep();
+ }
+ update_panels();
+ doupdate();
+ }
+
+
+ fclose(fdBin);
+
+ fflush(stdin);
+ getch();
+ endwin();
+
+ return 0;
+}
+
+void init_curse()
+{
+
+ /* Initialize curses */
+ initscr();
+ start_color();
+ cbreak();
+ noecho();
+ keypad(stdscr, TRUE);
+
+
+ /* Initialize all the colors */
+ init_pair(1, COLOR_RED, COLOR_BLACK);
+ init_pair(2, COLOR_GREEN, COLOR_BLACK);
+ init_pair(3, COLOR_CYAN, COLOR_BLACK);
+ init_pair(4, COLOR_WHITE, COLOR_BLUE);
+}
+
+void init_wins(WINDOW **wins)
+{
+ int i;
+
+ /* Menu */
+ wins_coords[0].h = LINES-2;
+ wins_coords[0].w = COLS/5;
+ wins_coords[0].x = 1;
+ wins_coords[0].y = COLS - COLS/5;
+ wins_coords[0].y = COLS - COLS/5;
+ /* Memory */
+ wins_coords[1].h = LINES-2-(LINES-2)/3;
+ wins_coords[1].w = COLS - COLS/5;
+ wins_coords[1].x = 1;
+ wins_coords[1].y = 0;
+ /* Code */
+ wins_coords[2].h = (LINES-2)/3;
+ wins_coords[2].w = COLS - COLS/5;
+ wins_coords[2].x = 1+LINES-2-(LINES-2)/3;
+ wins_coords[2].y = 0;
+
+ for(i=0;i<NB_WINS;i++) { wins[i] = newwin(wins_coords[i].h, wins_coords[i].w, wins_coords[i].x,wins_coords[i].y); }
+
+ scrollok(wins[2], TRUE);
+ wsetscrreg(wins[2],3, wins_coords[2].h-2);
+
+ win_show(wins[0], "Menu", 3);
+ win_show(wins[1], "Memory", 2);
+ win_show(wins[2], "Executed Code", 1);
+}
+
+void init_panels(PANEL ** panels, WINDOW **wins)
+{
+ int i;
+ /* Attach a panel to each window */ /* Order is bottom up */
+ for(i=0;i<NB_WINS;i++) panels[i] = new_panel(wins[i]);
+}
+
+/* Show the window with a border and a label */
+void win_show(WINDOW *win, char *label, int label_color)
+{
+ int startx, starty, height, width;
+ getbegyx(win, starty, startx);
+ getmaxyx(win, height, width);
+ box(win, 0, 0);
+ mvwaddch(win, 2, 0, ACS_LTEE);
+ mvwhline(win, 2, 1, ACS_HLINE, width - 2);
+ mvwaddch(win, 2, width - 1, ACS_RTEE);
+ print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
+ wmove(win,3,0);
+}
+
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
+{
+ int length, x, y;
+ float temp;
+
+ if(win == NULL)
+ win = stdscr;
+ getyx(win, y, x);
+ if(startx != 0)
+ x = startx;
+ if(starty != 0)
+ y = starty;
+ if(width == 0)
+ width = 80;
+
+ length = strlen(string);
+ temp = (width - length)/ 2;
+ x = startx + (int)temp;
+ wattron(win, color);
+ mvwprintw(win, y, x, "%s", string);
+ wattroff(win, color);
+ refresh();
+}
+
+void print_hints(struct hint hints[], int n)
+{
+ int i;
+ for(i=0;i<n;i++)
+ {
+ char *currc = hints[i].name;
+ while(*currc)
+ {
+ int out = *currc;
+ if ( out == hints[i].key ) { out |= A_STANDOUT; }
+ addch(out);
+ currc++;
+ }
+ addch(' ');
+ }
+}
+
+void draw_head_and_foot()
+{
+ attron(COLOR_PAIR(4));
+ attron(A_BOLD);
+ mvhline(0,0,' ', COLS);
+ mvhline(LINES-1,0,' ', COLS);
+ mvprintw(0, (COLS-strlen(APP_TITLE))/2, APP_TITLE, 'H' | A_STANDOUT, 'M', 'E', 'C', 'S');
+ mvaddch(LINES-1,0,' ');
+ print_hints(hints, sizeof(hints)/sizeof(struct hint));
+ attroff(A_BOLD);
+ attroff(COLOR_PAIR(4));
+}
+
+void wprinthls(WINDOW *win, char text[])
+{
+ int i, maxx=getmaxx(win);
+
+ chtype *line=malloc(sizeof(chtype)*(maxx+1));
+
+ line[0]=ACS_VLINE;
+ for(i=1;i<maxx-1;i++){line[i]=' ' | A_STANDOUT ;}
+ line[maxx]=0;
+
+ for(i=0;i<maxx-4 && text[i]!=0;i++) { line[i+2] = text[i] | A_STANDOUT; }
+ line[maxx-1]=ACS_VLINE;
+
+ mvwchgat(win,3,1,maxx-2, 0, 0, NULL);
+ wscrl(win,-1);
+ mvwaddchstr(win,3,0,line);
+}
+
+void wprintline(WINDOW *win, int lineno, char text[], int text_len)
+{
+ int i, maxx=getmaxx(win);
+
+ chtype *line=malloc(sizeof(chtype)*(maxx+1));
+ line[0]=ACS_VLINE;
+ for(i=1;i<maxx-1;i++){line[i]=' ';}
+ line[maxx]=0;
+
+ for(i=0;i<maxx-4 && i<text_len;i++) { line[i+2] = text[i]; }
+ line[maxx-1]=ACS_VLINE;
+ mvwaddchstr(win,3+lineno,0,line);
+}
+
+void do_exec_step(WINDOW *dest_win)
+{
+ char *instr = malloc(sizeof(char)*(getmaxx(dest_win)-4));
+ char buf[4];
+
+ if (fread(buf, 4, 1, fdBin))
+ {
+ sprintf(instr, "%7d @0x%02x: %s 0x%02x 0x%02x 0x%02x",
+ ++i_count,
+ (int) ftell(fdBin)-4,
+ instructionNames[(int)buf[0]],
+ (unsigned int) buf[1] & 0xFF,
+ (unsigned int) buf[2] & 0xFF,
+ (unsigned int) buf[3] & 0xFF
+ );
+ wprinthls(dest_win, instr);
+
+ switch (buf[0])
+ {
+ case I_NOP:
+ break;
+ case I_ADD:
+ mem[(int)buf[1]] = mem[(int)buf[2]] + mem[(int)buf[3]];
+ break;
+ case I_MUL:
+ mem[(int)buf[1]] = mem[(int)buf[2]] * mem[(int)buf[3]];
+ break;
+ case I_SOU:
+ mem[(int)buf[1]] = mem[(int)buf[2]] - mem[(int)buf[3]];
+ break;
+ case I_DIV:
+ mem[(int)buf[1]] = mem[(int)buf[2]] / mem[(int)buf[3]];
+ break;
+ case I_COP:
+ mem[(int)buf[1]] = mem[(int)buf[2]];
+ break;
+ case I_AFC:
+ mem[(int)buf[1]] = buf[2];
+ break;
+ case I_JMP:
+ fseek(fdBin, (long)buf[1], SEEK_SET);
+ break;
+ case I_JMF:
+ if (!mem[(int)buf[1]]) { fseek(fdBin, (long)buf[2]&0xFF, SEEK_SET); }
+ break;
+ case I_INF:
+ mem[(int)buf[1]] = mem[(int)buf[2]] < mem[(int)buf[3]];
+ break;
+ case I_SUP:
+ mem[(int)buf[1]] = mem[(int)buf[2]] > mem[(int)buf[3]];
+ break;
+ case I_EQU:
+ mem[(int)buf[1]] = mem[(int)buf[2]] == mem[(int)buf[3]];
+ break;
+ case I_PRI:
+ printf("PRI : %x\n", (int) mem[(int)buf[1]]); // TODO : fenetre out !
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void refresh_mem_display(WINDOW *dest_win)
+{
+ int i, disp_width=16;
+ char *memline = malloc(sizeof(char)*3*MEM_SIZE);
+
+ for (i=0;i<MEM_SIZE;i++) sprintf(memline+3*i, "%02x ", (unsigned int) mem[i] & 0xFF);
+ for (i=0;i<MEM_SIZE/disp_width;i++) wprintline(dest_win, i, memline+3*disp_width*i, 3*disp_width);
+}