/* ================================================================================ RPL/2 (R) version 4.1.20 Copyright (C) 1989-2015 Dr. BERTRAND Joël This file is part of RPL/2. RPL/2 is free software; you can redistribute it and/or modify it under the terms of the CeCILL V2 License as published by the french CEA, CNRS and INRIA. RPL/2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License for more details. You should have received a copy of the CeCILL License along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ #include "rpl-conv.h" /* ================================================================================ Routine de formation des données pour l'envoi de flux binaires ================================================================================ Entrées : structure sur l'état du processus et objet à afficher -------------------------------------------------------------------------------- Sorties : chaine de caractères -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ unsigned char * formateur_flux(struct_processus *s_etat_processus, unsigned char *donnees, integer8 *longueur) { unsigned char *chaine; unsigned char *ptr_ecriture; unsigned char *ptr_lecture; if ((chaine = malloc((strlen(donnees) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } ptr_lecture = donnees; ptr_ecriture = chaine; while((*ptr_lecture) != d_code_fin_chaine) { (*ptr_ecriture) = (*ptr_lecture); // Début de la séquence d'échappement if ((*ptr_lecture) == '\\') { if ((*(ptr_lecture + 1)) == '"') { ptr_lecture++; (*ptr_ecriture) = '\"'; } else if ((*(ptr_lecture + 1)) == 'b') { ptr_lecture++; (*ptr_ecriture) = '\b'; } else if ((*(ptr_lecture + 1)) == 'n') { ptr_lecture++; (*ptr_ecriture) = '\n'; } else if ((*(ptr_lecture + 1)) == 't') { ptr_lecture++; (*ptr_ecriture) = '\t'; } else if ((*(ptr_lecture + 1)) == 'x') { ptr_lecture += 2; if ((*ptr_lecture) != d_code_fin_chaine) { if ((*(ptr_lecture + 1)) != d_code_fin_chaine) { logical1 erreur; unsigned char ec; erreur = d_faux; switch(*ptr_lecture) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ec = (unsigned char) ((*ptr_lecture) - '0'); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ec = (unsigned char) (((*ptr_lecture) - 'A') + 10); break; default: ec = 0; erreur = d_vrai; break; } ec = (unsigned char) (ec * (unsigned char) 0x10); ptr_lecture++; switch(*ptr_lecture) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ec = (unsigned char) (ec + ((*ptr_lecture) - '0')); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ec = (unsigned char) (ec + (((*ptr_lecture) - 'A') + 10)); break; default: erreur = d_vrai; break; } (*ptr_ecriture) = ec; if (erreur == d_vrai) { if ((*s_etat_processus).langue == 'F') { printf("+++Information : " "Séquence d'échappement " "inconnue (\\x%c%c) [%d]\n", *ptr_lecture, *(ptr_lecture + 1), (int) getpid()); } else { printf("+++Warning : Unknown " "escape code (\\x%c%c) [%d]\n", *ptr_lecture, *(ptr_lecture + 1), (int) getpid()); } } } else { if ((*s_etat_processus).langue == 'F') { printf("+++Information : " "Séquence d'échappement " "tronquée [%d]\n", (int) getpid()); } else { printf("+++Warning : Truncated escape code " "[%d]\n", (int) getpid()); } } } else { if ((*s_etat_processus).langue == 'F') { printf("+++Information : " "Séquence d'échappement " "inconnue [%d]\n", (int) getpid()); } else { printf("+++Warning : Unknown escape code " "[%d]\n", (int) getpid()); } } } else if ((*(ptr_lecture + 1)) == '\\') { ptr_lecture++; } else { if ((*(ptr_lecture + 1)) == d_code_fin_chaine) { if ((*s_etat_processus).langue == 'F') { printf("+++Information : " "Séquence d'échappement " "tronquée [%d]\n", (int) getpid()); } else { printf("+++Warning : Truncated escape code " "[%d]\n", (int) getpid()); } } else { if ((*s_etat_processus).langue == 'F') { printf("+++Information : Séquence d'échappement " "inconnue (%c%c) [%d]\n", *ptr_lecture, *(ptr_lecture + 1), (int) getpid()); } else { printf("+++Warning : Unknown escape code (%c%c) " "[%d]\n", *ptr_lecture, *(ptr_lecture + 1), (int) getpid()); } } } } ptr_ecriture++; ptr_lecture++; } (*ptr_ecriture) = d_code_fin_chaine; if ((chaine = realloc(chaine, (((size_t) ((*longueur) = ptr_ecriture - chaine)) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } return(chaine); } /* ================================================================================ Routine de d'analyse d'un flux ================================================================================ Entrées : structure sur l'état du processus et objet à afficher -------------------------------------------------------------------------------- Sorties : chaine de caractères -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ unsigned char * analyse_flux(struct_processus *s_etat_processus, unsigned char *donnees, integer8 longueur) { integer8 longueur_courante; long offset; unsigned char *chaine; unsigned char hexadecimal[3]; unsigned char *ptr_ecriture; unsigned char *ptr_lecture; if ((chaine = malloc(((size_t) (longueur_courante = longueur + 1)) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } ptr_lecture = donnees; ptr_ecriture = chaine; while(longueur > 0) { // Début de la séquence d'échappement switch((*ptr_lecture)) { case '"': case '\b': case '\n': case '\t': case '\\': { offset = ptr_ecriture - chaine; if ((chaine = realloc(chaine, ((size_t) (++longueur_courante)) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } ptr_ecriture = chaine + offset; *ptr_ecriture++ = '\\'; switch((*ptr_lecture++)) { case '"': { *ptr_ecriture++ = '"'; break; } case '\b': { *ptr_ecriture++ = 'b'; break; } case '\n': { *ptr_ecriture++ = 'n'; break; } case '\t': { *ptr_ecriture++ = 't'; break; } case '\\': { *ptr_ecriture++ = '\\'; break; } } break; } case ' ': { *ptr_ecriture++ = *ptr_lecture++; break; } default: { if (isgraph((*ptr_lecture))) { *ptr_ecriture++ = *ptr_lecture++; } else { offset = ptr_ecriture - chaine; if ((chaine = realloc(chaine, ((size_t) (longueur_courante = longueur_courante + 3)) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } ptr_ecriture = chaine + offset; *ptr_ecriture++ = '\\'; *ptr_ecriture++ = 'x'; sprintf(hexadecimal, "%02X", *ptr_lecture++); *ptr_ecriture++ = hexadecimal[0]; *ptr_ecriture++ = hexadecimal[1]; } break; } } longueur--; } (*ptr_ecriture) = d_code_fin_chaine; return(chaine); } /* ================================================================================ Routine testant la validité d'une chaîne de caractères ================================================================================ Entrées : structure sur l'état du processus et chaîne courante -------------------------------------------------------------------------------- Sorties : pointeur sur le caractère suivant -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ logical1 validation_chaine(unsigned char *chaine) { if (chaine == NULL) { return(d_faux); } while((*chaine) != d_code_fin_chaine) { if ((*chaine) == '\\') { if ((*(chaine + 1)) == '"') { chaine += 2; } else if ((*(chaine + 1)) == 'b') { chaine += 2; } else if ((*(chaine + 1)) == 'n') { chaine += 2; } else if ((*(chaine + 1)) == 't') { chaine += 2; } else if ((*(chaine + 1)) == 'x') { if ((*(chaine + 2)) != d_code_fin_chaine) { if ((*(chaine + 3)) != d_code_fin_chaine) { switch(*(chaine + 2)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': break; default: return(d_faux); break; } switch(*(chaine + 3)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': break; default: return(d_faux); break; } } else { return(d_faux); } } else { return(d_faux); } chaine += 4; } else if ((*(chaine + 1)) == '\\') { chaine += 2; } else { // Tous les autres cas sont invalides return(d_faux); } } else { chaine++; } } return(d_vrai); } /* ================================================================================ Routine permettant de trouver le caractère suivant dans une chaîne ================================================================================ Entrées : structure sur l'état du processus et chaîne courante -------------------------------------------------------------------------------- Sorties : pointeur sur le caractère suivant -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ static inline unsigned char * prochain_caractere(struct_processus *s_etat_processus, unsigned char *chaine) { unsigned char *suivant; if (chaine == NULL) { return(NULL); } if ((*chaine) == '\\') { if ((*(chaine + 1)) == '"') { suivant = chaine + 2; } else if ((*(chaine + 1)) == 'b') { suivant = chaine + 2; } else if ((*(chaine + 1)) == 'n') { suivant = chaine + 2; } else if ((*(chaine + 1)) == 't') { suivant = chaine + 2; } else if ((*(chaine + 1)) == 'x') { if ((*(chaine + 2)) != d_code_fin_chaine) { if ((*(chaine + 3)) != d_code_fin_chaine) { logical1 erreur; erreur = d_faux; switch(*(chaine + 2)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': break; default: erreur = d_vrai; break; } switch(*(chaine + 3)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': break; default: erreur = d_vrai; break; } if (erreur == d_vrai) { if ((*s_etat_processus).langue == 'F') { printf("+++Information : " "Séquence d'échappement " "inconnue [%d]\n", (int) getpid()); } else { printf("+++Warning : Unknown " "escape code " "[%d]\n", (int) getpid()); } return(NULL); } suivant = chaine + 4; } else { if ((*s_etat_processus).langue == 'F') { printf("+++Information : " "Séquence d'échappement " "inconnue [%d]\n", (int) getpid()); } else { printf("+++Warning : Unknown escape code " "[%d]\n", (int) getpid()); } return(NULL); } } else { if ((*s_etat_processus).langue == 'F') { printf("+++Information : " "Séquence d'échappement " "inconnue [%d]\n", (int) getpid()); } else { printf("+++Warning : Unknown escape code " "[%d]\n", (int) getpid()); } return(NULL); } } else if ((*(chaine + 1)) == '\\') { suivant = chaine + 2; } else { if ((*s_etat_processus).langue == 'F') { printf("+++Information : Séquence d'échappement " "inconnue [%d]\n", (int) getpid()); } else { printf("+++Warning : Unknown escape code " "[%d]\n", (int) getpid()); } return(NULL); } } else { suivant = chaine + 1; } return(suivant); } /* ================================================================================ Routine donnant la longueur d'une chaîne de caractères ================================================================================ Entrées : structure sur l'état du processus et chaîne -------------------------------------------------------------------------------- Sorties : longueur de la chaîne -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ integer8 longueur_chaine(struct_processus *s_etat_processus, unsigned char *chaine) { integer8 nombre_caracteres; unsigned char *pointeur; pointeur = chaine; nombre_caracteres = 0; if ((*pointeur) == '\0') { return(0); } do { if ((pointeur = prochain_caractere(s_etat_processus, pointeur)) == NULL) { return(0); } nombre_caracteres++; } while((*pointeur) != 0); return(nombre_caracteres); } /* ================================================================================ Routine retournant un pointeur sur le i-ème caractère d'une chaîne ================================================================================ Entrées : structure sur l'état du processus, chaîne et position du caractère -------------------------------------------------------------------------------- Sorties : pointeur sur le caractère -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ unsigned char * pointeur_ieme_caractere(struct_processus *s_etat_processus, unsigned char *chaine, integer8 position) { integer8 i; unsigned char *pointeur; if ((pointeur = chaine) == NULL) { return(NULL); } for(i = 0; i < position; i++) { pointeur = prochain_caractere(s_etat_processus, pointeur); if ((*pointeur) == d_code_fin_chaine) { return(pointeur); } } return(pointeur); } /* ================================================================================ Routine retournant la position du caractère en fonction du pointeur dans la chaîne ================================================================================ Entrées : structure sur l'état du processus, chaîne et position -------------------------------------------------------------------------------- Sorties : quantième dans la chaîne -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ integer8 position_caractere_de_chaine(struct_processus *s_etat_processus, unsigned char *chaine, unsigned char *position) { integer8 i; i = 1; while(chaine != position) { chaine = prochain_caractere(s_etat_processus, chaine); i++; if ((*chaine) == d_code_fin_chaine) { return(0); } } return(i); } /* ================================================================================ Conversion d'une chaîne en majuscule ou en minuscule ================================================================================ Entrées : chaîne et indicateur ('M' pour majuscules, 'm' pour minuscules) -------------------------------------------------------------------------------- Sorties : néant -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void conversion_chaine(struct_processus *s_etat_processus, unsigned char *chaine, unsigned char type) { int (*fonction_1)(int); int (*fonction_2)(int); int registre; unsigned char *ptr; unsigned char *ptr2; if (type == 'M') { fonction_1 = toupper; fonction_2 = tolower; } else { fonction_1 = tolower; fonction_2 = toupper; } ptr = chaine; while((*ptr) != d_code_fin_chaine) { ptr2 = prochain_caractere(s_etat_processus, ptr); if ((ptr2 - ptr) == 1) { registre = fonction_1((*ptr)); if (fonction_2(registre) == (*ptr)) { (*ptr) = (unsigned char) registre; } } ptr = ptr2; } return; } // vim: ts=4