/* *** ** *** asm-simulateur ** * * */ #include #include #include #include #include #include #include #include #include #include /* Clé : nom de la commande ou du label (char *) * Valeur : numéro associé en héxadécimal (char *) */ GHashTable *table_decode; /* Retourne -1 si la fin du fichier a été atteinte 0 si aucun caractère n'a été lu ou si # est le premier caractère lu (toute la phrase suivante est ignorée) 1 si le séparateur est un espace 2 si le séparateur est un retour de ligne */ int lit_mot (FILE *f, char *mot) { int lu = 0; for (;;) { char car; int nbre_lu = fread (&car, 1, 1, f); mot [lu] = 0; if (nbre_lu == 0) { if (lu == 0) return -1; else return 0; } if (car == '#' && nbre_lu == 1) { fgets (mot, 256, f); return 0; } if (car == ' ') return 1; if (car == '\n') return 2; mot [lu] = car; lu += nbre_lu; } } /* Tansforme un entier < 256 en un nombre héxa de 2 caractères */ static char* number_to_char (int c) { char val0[3]; char *val = malloc (3); if (c < 16) sprintf (val0, "0%x", c); else sprintf (val0, "%x", c); val[0] = val0[0]; val[1] = val0[1]; return val; } /* Initalise les noms des commandes avec leur numéro */ void remplit_table () { char *mot_fin = "__NO_MORE_OP__"; int com[2]; pipe (com); if (fork () > 0) { char mot1[256]; char mot2[256]; FILE *in = fdopen (com[0], "r"); fgets (mot1, 256, in); for (;;) { char *valeur = malloc (2); char *clef; lit_mot (in, mot1); // numéro de l'opération en héxa lit_mot (in, mot2); // nom de l'opération if (!strcmp (mot2, mot_fin)) break; clef = malloc (strlen (mot2) + 1); sprintf (clef, "%s", mot2); valeur[0] = mot1[0]; valeur[1] = mot1[1]; g_hash_table_insert (table_decode, clef, valeur); } fclose (in); } else { /* la sortie standard va vers com[1] */ dup2 (com[1], STDOUT_FILENO); system ("cat instruction-decoder | expand | tr -s ' ' | cut -f3,5 -d' '"); printf ("%s\n", mot_fin); printf ("%s\n", mot_fin); exit (EXIT_SUCCESS); } } int is_digit_word (char *w) { int i; for (i = 0; i < strlen (w); i++) if (!isdigit (w[i])) return 0; return 1; } /* Ecrit dans out la valeur associée à clef à moins que clef ne soit un * nombre auquel cas ce nombre est écrit. * Si la clef n'est pas trouvée dans la table, le programme s'arrête si * erreur_si_introuvable est à 1 ; sinon la clef simplement est écrite. */ void transcrit_un_mot (FILE *out, char *clef, int ligne, int erreur_si_introuvable) { char *valeur; if (!is_digit_word (clef)) valeur = g_hash_table_lookup (table_decode, clef); else { // Ajoute un 0 devant le nombre si nécessaire if (strlen (clef) == 1) { char *valeur_tmp = malloc (3); sprintf (valeur_tmp, "0%s", clef); valeur = valeur_tmp; } else valeur = clef; } if (valeur == NULL) { if (erreur_si_introuvable) { fprintf (stderr, "Erreur : commande '%s' inconnue...\n", clef); exit (EXIT_FAILURE); } else valeur = clef; } fprintf (out, "%s #%2s %s\n", valeur, number_to_char (ligne), clef); } void assemble (char *in_name, char *out_name) { int i; /* Le premier tour sert à associer les labels à leur numéro de ligne */ /* Le second tour (i == 1) écrit dans le flux de sortie */ for (i = 0; i < 2; i++) { FILE *in = fopen (in_name, "r"); FILE *out; char mot[512]; int ligne = 0; if (i) { out = (out_name == NULL ? stdout : fopen (out_name, "w")); fprintf (out, "MAIN-MEMORY\n"); } while (1) { int rep = lit_mot (in, mot); if (rep == -1) break; if (rep == 1) { if (i) transcrit_un_mot (out, mot, ligne, 1); ligne++; rep = lit_mot (in, mot); // second mot de la ligne if (i) transcrit_un_mot (out, mot, ligne, 0); ligne++; } else if (rep == 2) { if (mot[strlen (mot) - 1] == ':') // déclaration d'un label { if (!i) { char *valeur; char *clef; mot[strlen (mot) - 1] = 0; if (g_hash_table_lookup (table_decode, mot)) { fprintf (stderr, "Erreur : label '%s' dupliqué...\n", mot); exit (1); } valeur = number_to_char (ligne); clef = malloc (strlen (mot) + 1); sprintf (clef, "%s", mot); g_hash_table_insert (table_decode, clef, valeur); //printf ("Label %s trouvé ligne %s\n", clef, valeur); } } else { if (i) transcrit_un_mot (out, mot, ligne, 1); ligne++; } } } fclose (in); if (i && out_name != NULL) fclose (out); } } int main(int argc, char *argv[]) { if (argc != 3 && argc != 2) { printf ("\n Usage : %s nom_fichier_à_assembler [nom_fichier_sortie]\n" " Si nom_fichier_sortie n'est pas spécifié, la sortie s'effectue\n" " sur la sortie standard.\n" " Pour plus d'information, faire : man %s.man\n\n", *argv, *argv); exit (EXIT_FAILURE); } table_decode = g_hash_table_new (g_str_hash, g_str_equal); remplit_table (); assemble (argv[1], (argc == 3 ? argv[2] : NULL)); exit(EXIT_SUCCESS); }