For context, I am trying to do some simplistic localization, as a first step into that "ocean", with limited language options. I want to be more "inclusive" than just limited to itemizing all instances of the type (three options for values of Bash environment variable LANGUAGE).
#define SPANISH 'es_MX:es'
#define FRENCH 'fr_CA:fr'
#define ENGLISH 'en_CA:en'
In AWK, I can do
MYLANG = sprintf("%2s", LANG)
I want to do something that simple, so I can do
// AWK syntax for sprintf
#define MYLANG {simple}
to obtain only the first two characters of the string LANG.
Is there something that I can use for that?
The full working script, all behaving as expected except for not having access to the environment variable LANGUAGE is the following:
#include <langinfo.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#define SPANISH 'es'
#define FRENCH 'fr'
#define ENGLISH 'en'
#ifndef LANGUAGE
#include "CIMIfrecN_MessagesTable_fr.h"
#else
#define MYLANG LANGUAGE[0],LANGUAGE[1] // Not valid
#if MYLANG == SPANISH
//#include "_cimifrecn_messagestable_es_h"
#include "CIMIfrecN_MessagesTable_es.h"
#elif MYLANG == FRENCH
//#include "_cimifrecn_messagestable_fr_h"
#include "CIMIfrecN_MessagesTable_fr.h"
#else
//#include "_cimifrecn_messagestable_en_h"
#include "CIMIfrecN_MessagesTable_en.h"
#endif
#endif
//==================================================================================================
// START OF MAIN PROGRAM
//==================================================================================================
int main() {
char yellowON[12] = "\e[93;1m";
char yellowOFF[12] = "\e[0m";
char redON[12] = "\e[91;1m";
char redOFF[12] = "\e[0m";
char blueON[12] = "\e[94;1m";
char blueOFF[12] = "\e[0m";
char ThisLOCALE[30];
sprintf(ThisLOCALE, "%s", setlocale(LC_ALL, ""));
printf("\n\t %s\n\n", ThisLOCALE);
printf("\n == %s%s%s ==\n", blueON, ScenarioSetUp, blueOFF);
return 0;
}
The outputs are displayed as follows:
That shows that the proposed method using two single-position references to LANGUAGE does not work. :-(
<Addendum 1>
So, I tried a revised version of that script, where I do compare to the full value of the LANGUAGE variable, thinking that it demonstrated that it was accessible during the pre-processing. Unfortunately, I did not realize I had English as the default fallback case, so my conclusion was incorrect. I had received a false-positive. :-(
...(deleted)...
<Addendum 2>
I revised my program again, setting English for a specific value match, and added specific strings to identify which of the invalid conditions are encountered:
#include <langinfo.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#define SPANISH 'es_MX:es' // Format reported by bash environment variable LANGUAGE
#define FRENCH 'fr_CA:fr'
#define ENGLISH 'en_CA:en'
//#define SPANISH 'es'
//#define FRENCH 'fr'
//#define ENGLISH 'en'
//#define TESTOR LANGUAGE[0],LANGUAGE[1] // Not valid
#define TESTOR LANGUAGE
//#ifndef LANG
#ifndef TESTOR
char ScenarioSetUp[30] = "TESTOR was not defined";
//#include "_cimifrecn_messagestable_es_h"
#include "CIMIfrecN_MessagesTable_es.h"
#else
#if TESTOR == NULL
char ScenarioSetUp[50] = "LANGUAGE was not obtained from the environment";
#elif TESTOR == SPANISH
//#include "_cimifrecn_messagestable_es_h"
#include "CIMIfrecN_MessagesTable_es.h"
#elif TESTOR == ENGLISH
//#include "_cimifrecn_messagestable_en_h"
#include "CIMIfrecN_MessagesTable_en.h"
#else
//#include "_cimifrecn_messagestable_fr_h"
#include "CIMIfrecN_MessagesTable_fr.h"
#endif
#endif
//==================================================================================================
// START OF MAIN PROGRAM
//==================================================================================================
//int setProgramLOCALE() {
int main() {
char yellowON[12] = "\e[93;1m";
char yellowOFF[12] = "\e[0m";
char redON[12] = "\e[91;1m";
char redOFF[12] = "\e[0m";
char blueON[12] = "\e[94;1m";
char blueOFF[12] = "\e[0m";
char ThisLOCALE[30];
sprintf(ThisLOCALE, "%s", setlocale(LC_ALL, ""));
printf("\n\t %s\n\n", ThisLOCALE);
printf("\n == %s%s%s ==\n", blueON, ScenarioSetUp, blueOFF);
return 0;
}
This time, it definitely shows specifically failure to detect LANGUAGE for the assignment to TESTOR for compiler directives, as can be seen by the message reported:
So I am still looking for a way to get at LANGUAGE during compiler directives. :-(
Please help.
Sample include file:
//==================================================================================================
// FILE: CIMIfrecN_MessagesTable_fr.h
// Header initializing context-based messages for the program
//==================================================================================================
#ifndef _cimifrecn_messagestable_fr_h
#define _cimifrecn_messagestable_fr_h
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
char ScenarioSetUp[91] = "configuration du scénario";
char EnterDesiredFrequency[91] = "Veuillez entrer la fréquence désirée";
char DesiredFrequency[91] = "Fréquence désirée";
char NumberLevelsImplied[91] = "Nombre de niveaux impliqués";
char NumberStrutsRequired[91] = "Nombre de poutres nécessaires";
char EvaluationPointRelevance[91] = "Évaluation des point du grillage pour identifier leur pertinence";
char Considering[91] = "Examinons";
char Horizontals[91] = "Horizontales";
char NoneMetCriteria[91] = "(aucunes comblait les critères)";
char Diagnonals[91] = "Diagonales";
char VerticesMinimalSet[91] = "Intersections identifiées pour un ensemble minimal contraignant entièrement la grille";
char ThereAre[91] = "Il y a";
char Vertices[91] = "Intersections";
char VerteIndexMatrix[91] = "Matrice des indices pour Intersections";
char VerticesProjectedSphere[91] = "Liste des intersections du polyhèdre projetés sur la sphère";
char EvalStrutelevance[91] = "Évaluation des poutres pour déterminer leur pertinence";
char HorizontalStruts[91] = "Poutres Horizontales";
char DiagonalStruts[91] = "Poutres Diagonales";
char PreOptimizationStruts[91] = "Groupe maximal de poutres requis à être optimisés pour l'ensemble minimum";
char StrutsAndTheirLengthsAre[91] = "poutres et leur longeurs sont";
#endif /* _cimifrecn_messagestable_fr_h */
//==================================================================================================
Script to generate language specific header file from comprehensive master message file:
#!/bin/sh
lang="${1}"
MESSAGE_TABLE="CIMIfrecN_MessagesTable_ALL.h"
MESSAGE_HEADER="CIMIfrecN_MessagesTable_${lang}.h"
Module="_"`echo "${MESSAGE_HEADER}" | tr '[A-Z]' '[a-z]' `
Module=`basename "${Module}" ".h" `"_h"
maxVar=`grep '^V|' "${MESSAGE_TABLE}" | cut -f2- -d\| |
while read msg
do
echo "${msg}" | wc -c
done | sort -r | head -1 `
maxStr=`grep '^'${lang}'|' "${MESSAGE_TABLE}" | cut -f2- -d\| |
while read msg
do
echo "${msg}" | wc -c
done | sort -r | head -1 `
#echo ${maxStr}
awk -v maxV="${maxVar}" -v maxS="${maxStr}" -v local="${lang}" -v file="${MESSAGE_HEADER}" -v module="${Module}" 'BEGIN{
var="" ;
msg=""
printf("\t local = %s\n", local ) | "cat 1>&2" ;
printf("//==================================================================================================\n") ;
printf("// FILE: %s\n", file ) ;
printf("// Header initializing context-based messages for the program\n") ;
printf("//==================================================================================================\n") ;
printf("\n") ;
printf("#ifndef %s\n", module ) ; ### Insert "header guard" to avoid double referencing by compiler
printf("#define %s\n", module ) ;
printf("\n") ;
printf("//#include <stdio.h>\n") ;
printf("//#include <stdlib.h>\n") ;
printf("//#include <string.h>\n") ;
printf("\n") ;
}{
switch( $0 ){
case /\|/ :
#printf("\n %s\n", $1 ) ;
gsub( "\015", "", $0 );
split( $0, dat, "|" ) ;
if( dat[1] == "V" ){
var=dat[2] ;
#printf("\n\t %s\n", var ) ;
}else{
#printf("\n %s\n", $1 ) ;
if( dat[1] ~ local ){
msg=dat[2] ;
#printf("\n\t %s\n", msg ) ;
} ;
} ;
if( var != "" && msg != "" ){
#printf("\n\t\t var = %s\n", var ) ;
#printf("\t\t msg = %s\n", msg ) ;
offset=maxV-length(var)+3 ;
printf("\tchar %s\133%d\135%"offset"s= %s ;\n", var, maxS, "", msg ) ;
var=""
msg=""
} ;
break ;
default :
break ;
} ;
}END{
printf("\n#endif /* %s */\n", module ) ;
printf("//==================================================================================================\n") ;
}' "${MESSAGE_TABLE}" > "${MESSAGE_HEADER}"
gvim "${MESSAGE_HEADER}"
echo "\n\t Done.\n"
#//3456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+
awk
script that does the processing you want and run it on your source code before compiling. You are not limited to using the preprocessing built into C; you can do any preprocessing you want using other programs."es_MX:es"
instead of'es_MX:es'
?sprintf("%2s",LANG)
and C/C++sprintf(buf,"%2s",LANG)
do NOT "obtain only the first 2 characters" of LANG; they give the whole value (which in the C/C++ case may overflow the buffer). Using"%.2s"
-- WITH A PERIOD character before the count -- DOES limit the result to 2 characters. In awk so doessubstr(LANG,1,2)
.SPANISH
FRENCH
macros related to extracting first 2 characters of a string? How is awk related to extarcting first 2 characters of a string? Why not justchar MYLANG[2] = {LANG[0], LANG[1]};
?that I can use for that?
For what exact do you want to use something? If you want to use awk, use awk. No, it is not possible to parse strings in preprocessor, preprocessor doesn't know about strings. Do you want to use C programming language or specifically C preprocessor?LC_LANG
orLANGAUGE
environment variable and using an existing project for that, like the amazing gnu.org/software/gettext . Gettext is very widely used both in C programming and Linux world.