Publié le 21 avril 2022 par Andrew Owen (5 minutes)
Cette semaine, je publie ce que j’espère être l’avant-dernière bêta de SE Basic IV (un interpréteur BASIC classique open source). La dernière bêta devrait contenir les fonctionnalités sonores et graphiques manquantes, avant de passer à la version candidate.
L’une des choses sur lesquelles j’ai passé beaucoup de temps à réfléchir est l’API publique. Le système d’exploitation sous-jacent possède sa propre API, mais elle est plutôt primitive et difficile à modifier pour des raisons (parce que le système d’exploitation a fait l’objet d’une ingénierie inverse et qu’il est à peine documenté).
À l’époque où j’écrivais des API à plein temps, j’utilisais Swashbuckle pour générer des documents OpenAPI à partir des commentaires du code source C#. J’avais déjà utilisé Doxygen pour faire la même chose pour C++ et Javadoc pour Java. Je voulais quelque chose qui fasse la même chose pour le langage d’assemblage. Et je l’ai trouvé, sous la forme d’un script Perl appelé asmdoc par Bogdan Drozdowski.
Le script analyse un ensemble de fichiers d’assemblage à la recherche de commentaires dans un format particulier, avec un ensemble connu de balises telles que @param, @return, @throws. Il génère un ensemble de fichiers HTML comprenant une table des matières, un index, une liste de constantes, une page d’aide, etc.
Le script a été écrit il y a longtemps et l’apparence par défaut est très web 1.0. Mais le code comprend un fichier CSS intégré que j’ai pu modifier pour donner à la sortie un aspect beaucoup plus moderne, inspiré de ReDoc. Je n’ai eu qu’une seule modification à apporter au code pour qu’il fonctionne avec la version actuelle de Perl (au moment où j’écris ces lignes).
Le script est autonome et produit tous les fichiers de sortie requis. Vous pouvez l’obtenir à l’adresse suivante: https://github.com/cheveron/sebasic4/blob/main/api/asmdoc.pl. Vous pouvez l’utiliser gratuitement dans vos propres projets. J’ai contacté Bogdan pour le remercier de son travail et lui montrer ce que j’avais fait. Il était surpris que je n’aie pas eu besoin de modifier son code.
J’ai créé une action Git pour créer la documentation de l’API et la publier chaque fois qu’il y a une modification du code dans la branche principale. Les documents de l’API sont hébergés sur les pages GitHub du projet (qui utilisent Gatsby). Voici le script:
name: API
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
asmdoc:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name:
run: |
cd api
perl asmdoc.pl -author -version ../basic/basic.inc ../basic/modules/*.asm
cd ..
mkdir ../temp
cp api/* ../temp
git config user.name github-actions
git config user.email github-actions@github.com
git fetch
git checkout gh-pages
cp ../temp/* api
git add .
git commit -m "asmdoc"
git push origin gh-pages
J’ai abordé les actions Git dans un article précédent. L’information cruciale ici se trouve à la ligne 18 où les fichiers à inclure sont spécifiés (le fichier basic.inc
et tous les fichiers avec l’extension .asm
).
Après l’exécution du script Perl, le reste de l’action récupère la sortie, puis la pousse vers le dépôt gh-pages, ce qui a pour effet de la publier ici: https://source-solutions.github.io/sebasic4/api/.
Comme le projet est open source, j’ai créé des stubs pour les routines les plus courantes. Cependant, celles-ci doivent être considérées comme faisant partie de l’API privée. L’adresse du code peut changer dans une version ultérieure, et donc le seul programme qui devrait appeler ces API est le micrologiciel lui-même.
Pour fournir une API publique que les applications peuvent appeler et dont les adresses ne changeront pas, j’ai utilisé une table vectorielle. Il s’agit d’une longue liste d’instructions JP
(sauts immédiats vers d’autres adresses). Alors que la destination des sauts peut changer d’une version à l’autre, l’emplacement dans la table est fixe en mémoire. Cela signifie que les applications peuvent l’appeler en toute sécurité sans craindre que l’adresse ne change à l’avenir.
Toutes les bases étant en place, la tâche suivante consistait à trouver un ensemble de fonctions utiles. J’ai examiné les API CP/M et MS-DOS, mais elles étaient, comme on peut le comprendre, simplistes et ne se présentaient pas dans un ordre logique (elles se sont développées avec le temps, au fur et à mesure de la sortie de nouvelles versions). Je me suis finalement inspiré de OpenStep et de BeOS.
Pour éviter toute confusion, les espaces de noms doivent toujours utiliser l’anglais américain. J’utilise donc:
SE
).File
, Folder
, Screen
, Keyboard
et ainsi de suite.Palette
.Ouverture
, Fermeture
, Lecture
, Ecriture
et ainsi de suite.Existe
.Voici quelques exemples de points de terminaison:
SEFileOpenExists
SEScreenPaletteSet
Et voici le commentaire dans le code qui génère les documents pour le premier exemple:
;;
; open a file from disk for reading if it exists
; @param IX - pointer to ASCIIZ file path
; @return file handle in <code>A</code>
; @throws sets carry flag on error
;;
SEFileOpenExists:
jp v_open_r_exists; //
Et dans la documentation de l’API, cela donne quelque chose comme ceci:
SEFileOpenExists
open a file from disk for reading if it exists
Parameter:
IX
- pointer to ASCIIZ file path
Returns:
file handle inA
Throws:
sets carry flag on error
Je ferais mieux de me remettre à la préparation de la publication.