Foin des considérations météorologiques

  • La dernière fois, nous parlions du développement sur vieux micro avec un cross assembler.
  • Cette fois-ci, pour nous reposer un peu, nous allons parler basic.
  • Mais oui, le basic : beginner awfully silly idiotic code. Enfin, un truc dans dans ce goût là.
  • Il y a vingt ans, les courageux précurseurs n'avaient souvent que ça à se mettre sous la dent.
  • Me croirez-vous si je vous dit que certaines personnes ne s'en sont jamais remises et continuent à le pratiquer ?
  • Afin de vous sensibiliser aux arcanes de ce qui touche désormais à la psychiatrie, je vous ai concocté une façon plus humaine d'aborder le problème.



OpenMSX members only

  • Attention, c'est pour OpenMSX, mais ça doit être transposable facilement à BlueMSX.
  • En fait, je suis même persuadé que BlueMSX est capable lui aussi d'écrire des fichiers dans le système de fichiers de l'ordinateur hôte.


Le basic MSX

tokens
  • Le basic du MSX est tokenisé. Quand on sauve un programme basic, les instructions apparaissent sous la forme d'un code hexa, qui représente une instruction. C'est ce qu'on appelle un token.
  • Cela permet de gagner de la place dans le fichier et en mémoire.
  • On peut sauver depuis le basic un fichier au format ascii (c'est à dire sans les tokens), avec:
    • save "foo.bas",a
  • Le ",a" est important, c'est ce qui signale qu'on veut de l'ascii.
    • Autrement, on n'aurait qu'une bouillie binaire représentant les tokens.
  • Pour le charger, toujours depuis le basic bien sûr:
    • load "foo.bas"


Création d'un programme basic en dehors du MSX
  • On peut donc charger des fichiers ascii contenant des instructions basic.
    • Attention à ne pas oublier les numéros de ligne quand on tape le programme dans un éditeur externe!
  • Il faut que les lignes se terminent par le CR/LF propre à MS-Dos.
    • Le jeu de caractère ne doit pas être trop évolué (pas d'UTF-8). Latin1 fait l'affaire.
  • Si vous tapez vos sources depuis MS-Windows, pas de problèmes de ce côté là, cet OS fait partie de la famille des CR/LF. En digne héritier de MS-Dos.
  • Si vous utilisez un OS de conception plus moderne (Unix sous toutes ses saveur par exemple) il faudra convertir vos LF en CR/LF.
  • Voici l'automatisation de la manoeuvre pour Vim, l'éditeur des gens qui font pas semblant. Ajoutez ceci dans le .vimrc :

autocmd BufNewFile,BufRead *.[Bb][Aa][Ss] set ff=dos fileencoding=latin1

  • Ceci fonctionnera avec les fichiers qui ont une extension ".bas" (peu importe la casse, il y a la regexp pour ça).
  • Les fichiers seront automatiquement sauvés avec le format de fin de ligne MS-Dos, et dans un charset que le MSX comprend.



Communication simplifiée avec le système hôte
  • Les utilisateurs d'émulateurs se compliquent souvent la vie avec tout un système d'émulation de disquettes ou de disque dur.
  • Le plus simple (quand la machine et l'émulateur le permettent, ce qui est le cas ici) est de partager ses fichiers avec le système hôte.
  • Par exemple, pour partager /home/jseb/msx/coding avec le msx émulé :

openmsx -machine nms8245 -diska /home/jseb/msx/coding

  • La commande files depuis l'écran de saisie basic du MSX permet de lister les fichiers partagés entre le système hôte et le MSX émulé.
    • Toutes les manipulations de fichier habituelles sont bien sûr possibles depuis le msx (load, save , bload ...)
  • Le paramètre machine nms8245 est là car je n'utilise pas tout le temps la même machine, et qu'il n'y en a pas de configuré par défaut.
    • Selon votre configuration, vous pouvez vous en passer (si le cbios démarre par défaut, vous n'avez pas de machine de configurée).
  • L'utilitaire diskmanipulator de OpenMSX est à réserver aux manipulations d'iso de disquettes.
    • Il est idéal pour transférer les fichiers vers un vrai msx, et s'utilise depuis la console d'OpenMSX.



Les numéros de lignes
  • Reste le problème des numéros de lignes pour le basic.
  • Ces vieux basic imposent une référence permanente aux séquences d'instructions. Cette référence est symbolisée par des numéros de lignes, sans autre rêgle qu'une progression constante et croissante.
  • Taper du code en commençant chaque ligne par un numéro croissant, c'est pénible.
    • Sans parler des erreurs de renumérotations!
    • Et que faire quand on n'a plus de numéros de lignes disponibles, et qu'on voudrait encore insérer une ligne dans cet ensemble ?


Le script magique
  • Voici un script qui permet de numéroter un programme basic de 10 en 10.
  • Les lignes commençant avec un numéro de ligne sont renumérotées, et quand il n'y n'y a pas de numéro de ligne, il est ajouté. En prime, les espaces et tabulations inutiles de début de ligne sont supprimées.
  • Les lignes vides sont ignorées.
  • Les références à des lignes existantes sont bien sûr traitées, sous réserve que les lignes référencées soient déja numérotées.
    • On peut donc se contenter de numéroter ces lignes uniquement lors de la saisie.
    • Le cas de "on k goto" suivi de plusieurs numéros de lignes est traité.
  • Les cas de lignes contenant des sauts multiples est traité.
    • On peut en effet rencontrer des constructions barbares de ce type:
    • gosub 20 : goto 10
    • Beurk certes, mais le cas est géré.
  • Attention, si vous utilisez MS-Windows: vérifiez vos terminaisons de lignes pour éventuellement adapter le script si vos outils écrivent un 0xD 0xA comme terminateur. Ceci dépendra des choix par défaut de votre environnement d'origine: depuis un shell émulant Unix, ou depuis un programme utilisant directement l'api MS-Windows.

#!/bin/bash
# ce script vient de www.finiderire.com
# le blog pour les gens qui en ont dans le chausson.

if [ x"$1" == x"" ]; then
   echo $0 "[fichier à renuméroter]"
   exit 1;
fi

#simple précaution, un accident est très vite arrivé
cp "$1" "$1".bak 

#conversion au format Unix 
 (Dos 
 pose problème à awk)
#également, espacement des nombres séparés par virgule (cas de "on goto")
sed 's/
$//;s/\([0-9]\)\ *,\ *\([0-9]\)/\1 , \2/g' < "$1" > "$1".tmp
mv "$1".tmp $1

#pour l'astuce de la relecture du fichier, voir awk/multipass.awk
awk 'NR!=FNR && !reset { l=0; reset=1; } #renumérote de zéro (2nde passe)

     #enlever espaces et tabs de début de ligne, si pas de numérotation
     NR!=FNR { sub (/^[\t\ ]+/,"",$0) }

     #renumérotation des goto/gosub (la seconde passe sert à ça)
     NR!=FNR && tolower($0) ~ /.*go(to|sub).*/ {
        for (i=1; i<=NF; i++) {
           #si pattern go(to|sub) détecté, prochaine colonne est un nbr
           if ($i ~ /.*go(to|sub).*/) { next_is_nbr=1 }
           # si on avait un goto/gosub juste avant ...
           if ($i ~ /[0-9]+/ && next_is_nbr) {
              $i = t[$i] #récupère index sur nouveau label
              if ( $i == "" ) $i="NaN" #si problème
              if ( $(i+1) != "," ) next_is_nbr=0; #cas de "on k goto ..."
           }
        }
     }

     #passe 1 et 2, on doit numéroter à chaque fois.
     /^[0-9]+/ { #un numéro de ligne est présent
     if (l || l==0) {l+=10} else {l=$1};
        l=l-(l%10);
        c=l;

      #par contre, on ne printe que lors de la passe 2
        if (NR!=FNR) {
           for (i=2; i<=NF; i++) { c=c " " $i; }
           print c
        } else {
        t[$1]=l; if ($1>max) max=$1
     }
    }
    

     /^[^0-9]/ && !/^
?$/ { #pas de numéro de ligne, ni de ligne vide
        l+=10; l=l-(l%10);
        #on ne printe que lors de la passe 2
        if (NR!=FNR) {
          print l " " $0;
        }
       }


#    END { print "énumération"; for (i=0; i<=max; i++) print i " "t[i] }
    ' "$1" "$1" > "$1".tmp

#et on reconverti en 
, tout en supprimant les espaces désormais inutiles
sed 's/$/
/;s/\([0-9]\) , \([0-9]\)/\1,\2/g' < "$1".tmp > "$1"
rm "$1".tmp

  • La compréhension du script est laissée à la sagacité du lecteur.
    • Pour les lecteurs dont la sagacité s'agace, il y a les commentaires judicieusement placés devant ce qui mérite d'être commenté.



C'est la fin de l'été, mais pour le reste ?

  • Si vous en voulez encore, appuyez sur "commentaire" (1€ par appel).
  • Mais même si vous en voulez encore, je vous préviens qu'il vous faudra être fort.
    • Le manque de temps fait que je risque de me concentrer sur des billets plus utiles pour les gens qui vivent dans la modernité.
    • Et oui... finiderire pour les vieux trucs. Rendez-vous aux prochaines vacances !
  • Si vous avez simplement quelque chose à ajouter, ne vous privez pas. Et fermez la porte en partant, le temps commence à fraichir.