Re: Jeux de caractères, notamment UT F-8

Thomas De Contes <[email protected]> Mon, 7 Dec 2020 22:36:56 +0100
Newsgroups gmane.comp.lang.ada.france
Message-ID <[email protected]>
Salut :-)
merci beaucoup pour ta réponse :-)


je me suis quelques fois emmêlé les pinceaux dans mes réponses, et en relisant je n'arrive pas à tout démêler,
et ça m'embête aussi quelques fois d'effacer quelque chose que je trouve juste même si ça ne correspond pas parfaitement à ce que t'as écrit au dessus

j'espère que tu ne m'en veux pas pour ça et que tu voudras bien continuer à me lire :-)


je me suis un peu éparpillé, mais en gros, ce qui m'importe, c'est de savoir ce que je peux faire aujourd'hui de raisonnable :
par exemple,

avoir son code source en UTF-8 et dire à gnat que c'est en Latin-1, pour pouvoir remplir un UTF_8_String avec un littéral,
- est ce qu'on peut le faire pour se simplifier la vie des maintenant, en anticipant la prochaine version du langage, parce qu'il n'y aura que des changements marginaux à faire pour rendre ça du "code propre",
- ou bien est ce qu'il ne faut surtout pas le faire, parce que c'est "coder salement" pour toujours, et que c'est aller dans la mauvaise direction parce que la manière dont Ada nous permettra d'utiliser UTF-8 de façon à la fois simple et propre sera différente ?



Le 11 sept. 2020 à 16:25, Jean-Pierre Rosen a écrit :

> Le 08/09/2020 à 19:34, Thomas De Contes a écrit :
> 
>> 1
>> quand je faisais des sites web, à un moment donné je me suis penché sur la question du "meilleur" jeu de caractères à utiliser, que ça soit pour :
>> - la compatibilité avec le maximum de navigateurs
>> - la compatibilité avec mon ordinateur et mes outils d'édition de html
>> - le nombre et la pertinence des caractères disponibles, de sorte qu'il y ait besoin de revenir le moins souvent possible sur le jeu de caractères que j'aurai choisi pour cause de caractère manquant, avec toutes les questions que ça implique pour en choisir un autre (et jongler avec plusieurs)
>> 
>> j'ai choisi UTF-8,
>> à l'époque sur le 1er point c'etait pas tout à fait le meilleur, par exemple Latin-1 était meilleur,
>> mais sur le 3ème il était imbattable ! universel ! tout en étant compatible ASCII !
>> 
>> et à en croire le choix majoritaire des "collègues", c'était le bon choix :-)
>> (c'était pas le cas dans tous les domaines : par exemple j'ai choisi le xhtml, qui apparemment a été laissé tomber)
> Attention, UTF-8 n'est pas un jeu de caractères, mais un encodage. Le
> jeu de caractères (le seul qui importe pour ton point 3) est Unicode.

ah oui, j'ai tendance à m'emmêler les pinceaux avec ces 2 notions :-)

apparemment, il faut appeler ça "jeu de caractères codés" et "forme de codage" :
https://fr.wikipedia.org/wiki/Codage_des_caract%C3%A8res#Différence_entre_jeu_de_caractères_codés_et_forme_de_codage

un peu au dessus, il y a aussi la notion de "répertoire de caractères",
et dans d'autres pages, au lieu de "forme de codage" ils parlent de "codage de caractères", que je trouve plus proche de ton terme "encodage" ...

bon, je crois que à la fois j'ai pas encore fait le tour du sujet,
et que wikipedia c'est très pratique pour beaucoup de choses, mais pas toujours très rigoureux :-)
heureusement je commence à avoir le réflexe de lire la norme ada, il me reste à persévérer pour aller jusqu'aux autres normes ;-)


> 
> Perso, je colle tout avec des codes HTML ("&eacute;"), comme ça il n'y a
> pas de problème d'encodage (avec un petit sed, ou emacs) pour
> transformer les caractères accentués).

si je comprend bien,
- tu ne fais que du web, pas d'interface avec Gtk par exemple ?
- en conséquence de ta "traduction", ton code ada est entierement ASCII ?

as tu un moyen de vérifier qu'aucun accent ne t'a échappé ?
a t on la possibilité de demander au compilateur de vérifier que tout le code est bien ASCII, sans aucun octet qui dépasse ?
(-gnatin ne vérifie que les identifiants, pas les littéraux)


cas pratique :

https://gcc.gnu.org/onlinedocs/gnat-style/Lexical-Elements.html
"The character set used should be plain 7-bit ASCII."

est ce que ça veut dire que -gnatg implique que ça vérifie qu'on est bien en ASCII ?
si oui, est il possible d'avoir cette fonction séparément, sans toutes les autres options induites par -gnatg ?


> 
>> 2
>> utilisation de gnat
>> 
>> j'ai un peu de mal à comprendre comment ça marche :
>> https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gnat_ugn/Character-Set-Control.html
>> 
>> par exemple, si je met les options "-gnati5 -gnatWs",
>> concrètement, comment gnat va t il lire mon code ?
>> avec Cyrillic pour les identifiants et Shift/JIS pour les littéraux de chaines de caractères ?
>> et si j'ai bien compris, dans les commentaires, tous les caractères non-ASCII sont autorisés tout le temps (sauf NEL) ?
>> 
>> (y a t il autre chose que identifiants / littéraux / commentaires, où on écrit potentiellement comme on veut ?)
> -gnati se réfère à la norme 8859, qui définit les jeux de caractères
> 8bits. Cela suppose donc le source d'entrée n'est PAS en Unicode codé
> UTF-8. Du coup, il faut avoir une méthode pour mettre quand même dans le
> texte des caractères en dehors du jeu de caractères 8 bits choisi: c'est
> le rôle de -gnatW

d'après mes essais, -gnati ne fonctionne qu'avec -gnatWb et -gnatWh, avec les autres -gnatW il est ignoré

comme -gnati ne s'occupe que les identifiants, est ce que ça veut dire que -gnatWb ou -gnatWh avec n'importe quel -gnati implique Latin-1 pour les littéraux de chaines, en même temps que c'est un autre jeu de caractères qui est utilisé pour les identifiants ?

que fait -gnatiw ? est ce que c'est pour autoriser les caractères en dehors de Latin-1 via "Hex encoding" ou "Brackets encoding", alors que sinon ils sont interdits dans les identifiants ?


(je fais court pour ne pas surcharger mon message :
on peut mettre un caractère U+C0 dans un littéral de chaine, dans un code source en UTF-8, et le relire en Latin-1 avec gnat, ce qui donne U+C3 U+80 :
c'est contradictoire avec "4.3.11 Character Set Control" et "2.6 String Literals" mais pas avec "3.2.1 Latin-1")


ça m'aurais paru plus simple d'avoir une seule option pour choisir une combinaison jeu de caractères / encodage,
- peu importe qu'il soit sur 8 bits ou "étendu" (dans tous les cas gnat le transforme en Unicode (Wide_Wide_String) avant de le traiter ?),
- mais aussi pour gérer les identifiants : je ne vois pas l'intérêt d'avoir un jeu de caractères différent pour les identifiants que pour le reste du fichier, ce qui est logique c'est que ça soit le même qui soit utilisé pour la correspondance de casse que pour décoder l'ensemble du fichier, et une fois traduit en Unicode c'est très facile à faire indépendamment du jeu de caractères de départ

(mais bon faut que j'évite de m'étaler là dessus, les 2 choses importantes pour moi sont UTF-8 et ASCII)


> 
>> 3
>> ce que je crois avoir compris, par contre, c'est comment ada et gnat
>> envisagent UTF-8 : les auteurs ont déjà fait plusieurs pas en 
>> direction d'unicode et UTF-8, notamment avec le paquetage
>> Ada.Strings.UTF_Encoding (A.4.11), mais ne sont pas encore arrivés au bout
> Un programme Ada est en Unicode/ISO10646 (cf. 2.1). On demande aux
> compilateurs de reconnaitre les sources encodés en UTF-8. Mais ça, c'est
> la représentation du code source du programme,

> ça n'a rien à voir avec
> les chaines manipulées par le programme.

et c'est là qu'il y a encore des manques, si j'ai bien compris,
puisqu'on ne peut pas encore remplir un Ada.Strings.UTF_Encoding.UTF_8_String avec un littéral sans conversion, à part en faisant croire au compilateur que le source est en Latin-1 alors que c'est pas vrai
(et je suis d'accord avec Pascal que c'est pas très propre, d'où ce fil ;-) )

j'ai ramé un peu pour comprendre comment tout ça marchais,
mais maintenant j'ai bien compris qu'il ne doit pas y avoir de lien direct entre les types chaines et l'encodage du code source :
typiquement, si on avait un type UTF_8_String parfaitement bien géré avec ses littéraux, et un code source en Latin-1, le compilateur aurais le devoir de faire la conversion Latin-1 -> UTF-8,
de la même façon qu'actuellement, avec l'option -gnatW8 il fait la conversion UTF-8 -> Latin-1 pour se conformer au jeu de caractères / encodage de Standard.Character / Standard.String


> 
>> Ada.Strings.UTF_Encoding.UTF_8_String est d'un basique type
>> String,c'est à dire basé sur Standard.Character, c'est à dire avec le
>> jeu de caractères Latin-1
> Formellement, l'UTF-8 n'est pas une suite de caractères, mais une suite
> de valeurs numériques.

toutes les combinaisons jeu de caractères / encodage commencent avec des octets, et finissent avec des caractères !
est ce que les "valeurs numériques" dont tu parles, c'est la couche intermédiaire entre UTF-8 et Unicode qu'on appelle "Point de code" ?

si je comprend bien, pour les jeux de caractères codés sur 1 seul octet, le Point de code correspond à l'octet :
https://fr.wikipedia.org/wiki/Point_de_code
(mais je ne suis pas sur de tout comprendre à cet article)


> La décision d'utiliser String est essentiellement
> pratique, pour le cas où on lit la première ligne d'un fichier, on
> reconnait un BOM, et du coup on réalise que c'est de l'UTF-8.

est-ce vraiment la seule raison ?

pour ce dont tu parles, je ne vois aucun inconvénient à construire UTF_8_String par exemple à partir de Ada.Streams.Stream_Element_Array, plutôt qu'à partir de Standard.String

ça aurais forcé des conversions explicites tout le temps, mais c'est bien dans l'esprit d'Ada avec le typage fort puisque le contenu n'est pas de même nature (il n'y a correspondance que tant qu'on reste dans ASCII)

par contre, je me rappelle t'avoir vu écrire plusieurs fois que lors des révisions du langage, une contrainte importante est l'investissement que les fabricants de compilateurs sont prêts à faire,
et je comprend cet argument, même si je regrette que ça rende Ada moins "consistant", je tache de me faire une raison :-)


(je ne sais pas si GtkAda est le meilleur exemple, c'est le seul que je connais parce que j'essaye de m'en servir depuis longtemps)

il me semble que GtkAda, au départ, utilisait Standard.String pour tous ses paramètres,
et je crois que ça devait déjà permettre d'utiliser UTF-8 (mais pas Latin-1 du coup, des qu'on sort d'ASCII), en s'alignant sur ce que proposait Gtk
(mais je crois que sans l'existence de UTF_8_String ils n'avaient pas le choix)

en fait, à la racine le fait que GtkAda ait utilisé Standard.String avec UTF-8 au lieu de Latin-1,
c'est ça qui a fait un usage d'Ada pas très propre,

puis le fait que ça soit devenu un outil très important et populaire (si je ne me trompe pas dans le déroulement etc)
c'est ça qui fait que maintenant on ne peut plus imposer aux gens de remplacer toutes leurs variables de type Standard.String par autre chose qui ne serais pas directement compatible, parce que ça serais très couteux,
et c'est ça qui fait que la situation un petit peu bancale du sous-type UTF_8_String est très dure à redresser ...

déjà jusque là, est ce que je me trompe ?


si pour UTF_8_String, au lieu d'un sous-type de String on avait fait un type dérivé de String ("type UTF_8_String is new String;", un intermédiaire entre le sous-type de String et le type basé sur Ada.Streams.Stream_Element_Array),
est ce que ça aurais été envisageable de demander à tous les usagers de simplement ajouter une conversion explicite avec le type String, sans qu'ils perdent aucune fonctionnalité, ou est ce que c'est déjà trop ?

je demande ça parce que ça me parait plus simple d'ajouter une astuce dans le langage qui permette de définir un traitement des littéraux pour UTF_8_String qui soit différent de celui qu'il y a pour String, si c'est un type dérivé que si c'est un sous-type


> La
> définition prudente du RM tient compte de cette ambiguité: "[the string]
> is assumed to contain characters whose position values correspond to a
> valid encoding sequence" (A.4.11(49/3). Il n'est pas question de jeu de
> caractères.

le mot "characters" est écrit, ça implique qu'il y en a un jeu,

simplement la définition utilise uniquement leur "position values" pour imposer une chaine UTF-8 valide ... mais ça n'empêche pas de faire des littéraux de chaines invalides, ou valides mais qui ne contiennent pas ce qu'on veut


> 
>> ça correspond à ce que j'ai testé :
>> 
>> - code source codé en UTF-8
>> - gnatmake avec l'option -gnatW8
>> - programme avec un littéral qui est transmis directement à GtkAda
>> 
>> - si on met de l'ASCII (U+00 - U+7F),
>> tout va bien
>> 
>> - si on met des caractères non Latin-1 (> U+FF),
>> gnat repond "literal out of range of type Standard.Character"
> Oui, il faut au moins un Wide_Character...

ben non, ce qu'il faut (d'après moi) c'est trouver un moyen de remplir correctement UTF_8_String
(c'est à dire en UTF-8, pas en Latin-1)

>> 
>> - si on met des caractères Latin-1 non-ASCII ("upper-half", U+80 - U+FF),
>> l'executable repond "Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()
> Si Pango attend de l'UTF-8, il faut lui passer de l'UTF-8. L'UTF-8
> utilise les caractères >7F pour son encodage, donc tu ne peux pas mettre
> des caractères au hasard

ce que j'ai fait là,
ça n'est pas mettre des caractères "au hasard",

c'est mettre des caractères codés en UTF-8, et dire à gnat que c'est de l'UTF-8,
après quoi, il convertit ça en Latin-1, mais ne le reconvertit pas au moment de le passer sous UTF_8_String !

GtkAda réclame explicitement du UTF_8_String,
simplement comme c'est un sous-type de String, même une simple conversion explicite n'est pas exigée, d'où une grosse tambouille pleine d'erreur d'affichages des qu'on sort d'ASCII ! (d'où la bienvenance (?) d'une option sur le compilateur pour vérifier qu'on est bien en ASCII, en attendant qu'UTF-8 soit plus accessible)

dans la vie de tous les jours, c'est beaucoup plus simple de "rien dire" à gnat, comme ça il croit que c'est du Latin-1, et quand on le passe sous UTF_8_String ça se retrouve "par hasard" correctement codé ...


> 
>> du coup, si on veut bénéficier du potentiel d'unicode, avec la possibilité d'utiliser n'importe quel caractère, sans avoir besoin de revenir sur aucun réglage le jour où l'envie nous prend (ou le besoin survient),
>> on doit utiliser l'option -gnatW8 combinée avec Standard.Wide_Wide_String
>> 
>> ce qui implique :
>> 
>> - quand on n'utilise que de l'ASCII (l'immense majorité du temps) ça prend 4 fois plus de mémoire que nécessaire
>> 
>> - ça dois faire 2 conversions inutiles (puisqu'elles sont symétriques) :
>>  - le compilateur doit convertir l'UTF-8 en Wide_Wide_String
>>  - le programme doit convertir le Wide_Wide_String en UTF-8, avec Ada.Strings.UTF_Encoding.Wide_Wide_Strings.Encode, pour pouvoir le passer à GtkAda
> Exact, mais la première conversion a lieu à la compilation, donc c'est
> sans effet à l'exécution.

d'un autre coté, la 2ème conversion, même si elle est optimisée à la compilation, alourdit le code et nuit à sa lisibilité

et si on veut avoir le maximum de rigueur, et respecter ce qui pourrait être un typage fort,
il faudrait convertir la quantité de minuscules littéraux, éparpillés tout le long du code, qu'on envoie à GtkAda, qui sont réputés être en Latin-1,
même quand ils ne contiennent que de l'ASCII, comme ça on peut sortir de l'ASCII sans devoir penser à rajouter la conversion systématiquement (parce que, comme dans ce cas de figure le typage est très faible avec String, si on oublie de le faire on n'est même pas prévenu !)

> Tu peux utiliser les Wide_String,

à mon humble avis, c'est un mauvais compromis (sauf erreur, un peu comme le dit Pascal dans sa proposition UXString) :
à la fois, on n'a pas tous les caractères d'Unicode, et quand on n'utilise que de l'ASCII ça prend quand même 2 fois plus de mémoire que nécessaire

> il y a peu
> de choses intéressantes en dehors du plan de base (à part les smileys ;-) )

il me semble qu'il y a aussi des alphabets étrangers, notamment asiatiques (même s'il y en a aussi dans le plan de base),
et puisqu'on a les outils pour ça (pour peu qu'on arrive à intégrer UTF-8 sans que ça soit trop casse pied), profitons en pour les respecter (et nous avec),
en leur permettant de modifier nos logiciels sans que quiconque ait à modifier un quelconque paramètre (par exemple passer de Wide_String à Wide_Wide_String)


> 
>> 4
>> l'idéal, ça serais de pouvoir écrire un programme en UTF-8, y compris des littéraux de chaines de caractères, et que ça soit interprété directement sous la forme Ada.Strings.UTF_Encoding.UTF_8_String, sans aucune conversion
>> (par exemple pour qu'on puisse le passer directement à GtkAda)
>> 
>> - est ce que dans les révisions futures, notamment la prochaine, vous continuez à vous rapprocher de ça ?
> Pas sûr que ça s'applique, mais il y a une généralisation des litéraux
> qui pourrait bien faire ça.

je ne comprend pas bien ce que tu veux dire :
- "une généralisation des littéraux", c'est à dire par exemple on pourra faire un littéral directement pour Unbounded_String ? bonne nouvelle, c'est un truc qui manquait :-)
- "Pas sûr que ça s'applique" : est ce que tu ne sais pas encore si la fonctionnalité que je demande pour UTF_8_String va être intégrée ou pas ? ou c'est autre chose dont tu n'es pas sur ?


> 
>> - y a t il un moyen de faire ça proprement des aujourd'hui ?
>> (idéalement quelque chose qui pourrais être accepté dans le code de gnat lui-même :-) bon là je crois que je rêve ;-) )
>> 
> Rien ne t'empêche de faire une constant String tout encodée, mais elle
> paraitra bizarre dans l'éditeur...

ah, tu dis ça peut-être parce que ton éditeur n'est pas en UTF-8 par défaut ...

comment ça se passe si je commence à mettre des caractères non ASCII encodés en UTF-8, et que je demande aux contributeurs d'éditer le code uniquement en UTF-8 ?
est ce qu'il va y en avoir une grosse proportion qui vont avoir du mal ?

à propos, comment ça se passe avec GPS ? (je ne l'utilise pas encore)



-- 
Téléassistance / Télémaintenance
http://invites.biocer.fr/thomas-de-contes/

_______________________________________________
Ada-france mailing list
[email protected]
https://mail.ada-france.org/cgi-bin/mailman/listinfo/ada-france