lc_all - Comportamiento de bytes/caracteres extendidos en la configuración regional C/POSIX
caracteristicas de posix (4)
C y POSIX requieren que solo esté presente un conjunto muy limitado de caracteres en la configuración regional de C / POSIX, pero permiten que existan caracteres adicionales. Esto deja mucha libertad a la implementación; por ejemplo, admitir todo Unicode (como UTF-8) en la configuración regional C es un comportamiento conforme. Sin embargo, la mayoría de las implementaciones históricas consideran que la configuración regional de C tiene una codificación de caracteres de un solo byte de "limpieza de 8 bits", ya sea ISO-8859-1 (Latin-1) o una especie de "conjunto de caracteres abstractos de 8 bits" donde Los bytes no ASCII son caracteres abstractos sin una identidad particular. (Sin embargo, en el último caso, si el compilador define __STDC_ISO_10646__
, se corresponden normativamente con los caracteres Unicode, generalmente el rango Latin-1).
Otra opción de conformidad que parece ser mucho menos popular es tratar todos los bytes que no son ASCII como no caracteres, es decir, responder a ellos con un error EILSEQ
.
Lo que me interesa saber es si hay implementaciones que tomen esta o cualquier otra opción inusual para implementar la configuración regional C. ¿Existen implementaciones en las que intentar convertir "bytes altos" en la configuración regional C da como resultado EILSEQ
o algo más que tratarlos como caracteres de un solo byte (abstractos o Latin-1) o UTF-8?
"Lo que me interesa saber es si existen implementaciones que tomen esta o cualquier otra opción inusual para implementar la configuración regional de C".
Esta pregunta es muy difícil de responder porque mezcla la "configuración regional de C", que supongo que se refiere al conjunto de caracteres limitados de C Standard mencionado anteriormente, con "otras opciones inusuales", que supongo se refiere a cómo la implementación específica maneja caracteres fuera de la configuración regional C (limitada). Cada implementación de C debe implementar la configuración regional de C; No creo que haya ninguna opción inusual alrededor de eso.
Supongamos, para el argumento, que la pregunta es: "... opciones inusuales en la implementación de caracteres adicionales / extendidos más allá de la configuración regional C." Ahora esto se convierte en una pregunta que depende de la implementación y, como ya ha mencionado, "deja mucha libertad a la implementación". Entonces, sin conocer el compilador / hardware objetivo, aún sería difícil responder de manera definitiva.
Ahora la última parte:
"... intentando convertir" bytes altos "en los resultados de la configuración regional C en EILSEQ o cualquier otra cosa que no sea tratarlos como caracteres de un byte (abstractos o latín-1) o UTF-8?"
En lugar de convertir bytes altos mientras se encuentra en la configuración regional de C, es posible que pueda establecer la configuración regional en su programa como en esta pregunta SO: ¿El conjunto de caracteres subyacente depende solo de la implementación de C?
De esta manera, puede asegurarse de que sus caracteres se tratarán en la configuración regional que espera.
Tengo entendido que la configuración regional C solo se relaciona con los primeros 7 bits (de un tipo de char
8 bits), según las fuentes a continuación:
- http://www.cprogramming.com/tutorial/unicode.html
- http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap07.html
- http://www.in-ulm.de/~mascheck/locale/
Los términos "bytes altos" y "Unicode" y "UTF-8" están en la clase de codificaciones de múltiples bytes o de caracteres anchos, y son muy específicos de la localidad (y están más allá del rango de la configuración regional C mínima). No tengo claro cómo sería posible "convertir los bytes altos" en el entorno C (puro). Es bastante posible que las implementaciones escojan una configuración regional predeterminada (extendida) si no se estableció explícitamente ninguna (o se extraen de la configuración del entorno del sistema operativo como se indica en uno de los enlaces anteriores).
Curiosamente, acabo de descubrir que la implementación más utilizada, glibc, es un ejemplo de lo que estoy buscando. Considere este programa simple:
#include <stdlib.h>
#include <stdio.h>
int main()
{
wchar_t wc = 0;
int n = mbtowc(&wc, "/x80", 1);
printf("%d %.4x/n", n, (int)wc);
}
En glibc, imprime -1 0000
. Si el byte 0x80 fuera un carácter extendido en la configuración regional C / POSIX de la implementación, se imprimiría 1 seguido de un número de carácter distinto de cero.
Por lo tanto, el "conocimiento común" de que la configuración regional de C / POSIX es "8-bit-clean" en glibc es simplemente falso. Lo que está pasando es que hay una gran inconsistencia; a pesar del hecho de que todas las utilidades estándar, la concordancia de expresiones regulares, etc. están especificadas para funcionar con caracteres (multibyte) como si mbrtowc
leídos por mbrtowc
, las implementaciones de estas utilidades / funciones están tomando un atajo cuando ven MB_CUR_MAX==1
o LC_CTYPE
que contiene "C"
(o similar) y que lee valores de caracteres directamente en lugar de procesar la entrada con mbrtowc
o similar. Esto conduce a una inconsistencia entre el comportamiento especificado (que, como se define su implementación del locale C / POSIX, tendría que tratar los bytes altos como secuencias ilegales) y el comportamiento de la implementación (que está omitiendo el sistema del locale por completo).
Con todo lo dicho, todavía estoy buscando otras implementaciones con las propiedades solicitadas en la pregunta.
Desde tu comentario hasta la respuesta anterior:
Las formas en que la suposición podría ser errónea son, básicamente, que los bytes fuera del conjunto de caracteres portátiles pueden ser bytes ilegales sin caracteres (EILSEQ) o componen alguna codificación multibyte (UTF-8 o una codificación CJK heredada sin estado)
Here puedes encontrar un ejemplo.
Plan 9 solo es compatible con la configuración regional "C". Como puede ver en utf.c y rune.c , cuando encuentra una runa fuera de los caracteres portátiles, simplemente la maneja como un personaje de una codificación diferente.
Otros candidatos podrían ser Minix y la familia * BSD (en la medida en que usan citrus ). En el código fuente de Minix también encontré el comando de archivo buscando una nueva codificación cuando el tamaño del carácter no es de 8 bits.
El estándar POSIX es bastante claro a este respecto.
La introducción a los conjuntos de caracteres dice:
6.2 Codificación de caracteres
La configuración regional POSIX contendrá 256 caracteres de un solo byte, incluidos los caracteres en el conjunto de caracteres portátiles y los caracteres de control no portátiles, que tienen las propiedades enumeradas en LC_CTYPE. No se especifica si los caracteres que no figuran en esas dos tablas se clasifican como puntuales o cntrl, o ninguno. Otras configuraciones regionales contendrán los caracteres en el Conjunto de caracteres portátiles y pueden contener cualquiera o todos los caracteres de control identificados en Caracteres de control no portátiles; La presencia, el significado y la representación de cualquier carácter adicional son específicos de cada localidad.
(énfasis mío)
La página para mbtowc() dice:
La función mbtowc () fallará si:
[EILSEQ]
Se detecta una secuencia de caracteres no válida. En la configuración regional POSIX no se puede producir un error [EILSEQ] ya que todos los valores de bytes son caracteres válidos.
Tenga en cuenta que la configuración regional POSIX está definida para ser idéntica a la configuración regional C.
Por lo tanto, si un sistema operativo cumple con POSIX, mbtowc
no funciona en la configuración regional de POSIX. Los caracteres 128–255 se pasan igual que los caracteres 0–127. Las implementaciones que operan de manera diferente están en violación de la norma.