summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c
diff options
context:
space:
mode:
authorAndreas Scherer <andreas_tex@freenet.de>2022-08-20 22:43:53 +0000
committerAndreas Scherer <andreas_tex@freenet.de>2022-08-20 22:43:53 +0000
commit1f554b5e55fb76a98420dbf16db38046a8370f60 (patch)
treeb5c7a788aa6b7115a939b8e5b9ddcca16ac1be09 /Build/source/texk/web2c
parent45cea7def9ed0e1640c8c30cf361bf59a6372457 (diff)
[CWEB] Add option '+u' for CTANGLE.
Option 'ctangle +u' extends the transliteration mechanism for ``poor man's UTF-8'. Instead of extending the 'translit' table (or replacing it with a dynamic data structure), CTANGLE skips all but the last of a sequence of high-bit bytes representing a single UTF-8 character. Only the last high-bit byte is used as the index into 'translit' as before. Example: In ``classic ASCII'', the German word 'grün' was transformed into 'gruen' with the transliteration '@l fc ue' (from the Western European codepage ISO/IEC 8859-1; see file cweb_ecma94.w for context). With UTF-8 encoded input and 'ctangle +u', the first (starter) byte 'c3' (1100.0011) is skipped and the second (continuing) byte 'bc' is used to look up the transliteration for 'ü' (latin small letter u with diaeresis), so '@l bc ue' can be used to get 'gruen' in the C output. Note that this is not a general UTF-8 transliteration because there are tons of possible collisions, e.g., '¼' (vulgar fraction one quarter) is 'c2 bc' in UTF-8 and would be transformed into 'ue' as well. git-svn-id: svn://tug.org/texlive/trunk@64157 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c')
-rw-r--r--Build/source/texk/web2c/ChangeLog5
-rw-r--r--Build/source/texk/web2c/ctangleboot.cin145
-rw-r--r--Build/source/texk/web2c/cwebdir/ChangeLog7
-rw-r--r--Build/source/texk/web2c/cwebdir/ctang-w2c.ch49
-rw-r--r--Build/source/texk/web2c/cwebdir/ctangle.c6
-rw-r--r--Build/source/texk/web2c/cwebdir/ctangle.w10
-rw-r--r--Build/source/texk/web2c/cwebdir/cwebman-w2c.ch10
-rw-r--r--Build/source/texk/web2c/help.h1
-rw-r--r--Build/source/texk/web2c/man/ChangeLog4
-rw-r--r--Build/source/texk/web2c/man/cweb.man6
10 files changed, 162 insertions, 81 deletions
diff --git a/Build/source/texk/web2c/ChangeLog b/Build/source/texk/web2c/ChangeLog
index 3a918c23bac..425cffb4831 100644
--- a/Build/source/texk/web2c/ChangeLog
+++ b/Build/source/texk/web2c/ChangeLog
@@ -1,3 +1,8 @@
+2022-08-21 Andreas Scherer <https://ascherer.github.io>
+
+ * ctangleboot.cin,
+ * help.h: New option '+u' for CTANGLE.
+
2022-08-06 Andreas Scherer <https://ascherer.github.io>
* weave.ch: Rewrite 'squash' to match description in section 148.
diff --git a/Build/source/texk/web2c/ctangleboot.cin b/Build/source/texk/web2c/ctangleboot.cin
index 9b2c18acc46..cdfa9cbd733 100644
--- a/Build/source/texk/web2c/ctangleboot.cin
+++ b/Build/source/texk/web2c/ctangleboot.cin
@@ -142,6 +142,8 @@
#define translit_length 10 \
+#define transliterate_utf_eight flags['u'] \
+
#define ignore 00
#define ord 0302
#define control_text 0303
@@ -274,7 +276,7 @@ extern FILE*active_file;
extern FILE*check_file;
/*:15*//*116:*/
-#line 506 "cwebdir/ctang-w2c.ch"
+#line 555 "cwebdir/ctang-w2c.ch"
extern char cb_banner[];
@@ -357,7 +359,7 @@ static boolean output_defs_seen= false;
/*:52*//*57:*/
#line 703 "cwebdir/ctangle.w"
-static char translit[128][translit_length];
+static char translit[0200][translit_length];
/*:57*//*62:*/
#line 779 "cwebdir/ctangle.w"
@@ -512,9 +514,10 @@ cur_out_file= end_output_files= output_files+max_files;
{
int i;
-for(i= 0;i<128;i++)sprintf(translit[i],"X%02X",(unsigned int)(128+i));
+for(i= 0;i<0200;i++)sprintf(translit[i],"X%02X",(unsigned int)(0200+i));
}
+#line 180 "cwebdir/ctang-w2c.ch"
/*:58*//*63:*/
#line 782 "cwebdir/ctangle.w"
{
@@ -540,7 +543,7 @@ ccode['\'']= ord;
section_text[0]= ' ';
/*:78*//*117:*/
-#line 509 "cwebdir/ctang-w2c.ch"
+#line 558 "cwebdir/ctang-w2c.ch"
strncpy(cb_banner,banner,max_banner-1);
@@ -754,11 +757,11 @@ writeloop:/*50:*/
if(check_for_change){
fclose(C_file);C_file= NULL;
/*106:*/
-#line 389 "cwebdir/ctang-w2c.ch"
+#line 438 "cwebdir/ctang-w2c.ch"
if((C_file= fopen(C_file_name,"r"))!=NULL){
/*107:*/
-#line 396 "cwebdir/ctang-w2c.ch"
+#line 445 "cwebdir/ctang-w2c.ch"
boolean comparison= false;
@@ -767,7 +770,7 @@ fatal(_("! Cannot open output file "),check_file_name);
/*108:*/
-#line 410 "cwebdir/ctang-w2c.ch"
+#line 459 "cwebdir/ctang-w2c.ch"
do{
char x[BUFSIZ],y[BUFSIZ];
@@ -777,17 +780,17 @@ comparison= (x_size==y_size)&&!memcmp(x,y,x_size);
}while(comparison&&!feof(C_file)&&!feof(check_file));
/*:108*/
-#line 403 "cwebdir/ctang-w2c.ch"
+#line 452 "cwebdir/ctang-w2c.ch"
fclose(C_file);C_file= NULL;
fclose(check_file);check_file= NULL;
/*:107*/
-#line 391 "cwebdir/ctang-w2c.ch"
+#line 440 "cwebdir/ctang-w2c.ch"
/*109:*/
-#line 421 "cwebdir/ctang-w2c.ch"
+#line 470 "cwebdir/ctang-w2c.ch"
if(comparison)
remove(check_file_name);
@@ -797,7 +800,7 @@ rename(check_file_name,C_file_name);
}
/*:109*/
-#line 392 "cwebdir/ctang-w2c.ch"
+#line 441 "cwebdir/ctang-w2c.ch"
}else
rename(check_file_name,C_file_name);
@@ -810,7 +813,7 @@ for(an_output_file= end_output_files;an_output_file> cur_out_file;){
an_output_file--;
sprint_section_name(output_file_name,*an_output_file);
if(check_for_change)/*105:*/
-#line 380 "cwebdir/ctang-w2c.ch"
+#line 429 "cwebdir/ctang-w2c.ch"
{
if((C_file= fopen(output_file_name,"a"))==NULL)
fatal(_("! Cannot open output file "),output_file_name);
@@ -841,14 +844,14 @@ flush_buffer();
if(check_for_change){
fclose(C_file);C_file= NULL;
/*110:*/
-#line 434 "cwebdir/ctang-w2c.ch"
+#line 483 "cwebdir/ctang-w2c.ch"
if(0==strcmp("/dev/stdout",output_file_name))
/*112:*/
-#line 461 "cwebdir/ctang-w2c.ch"
+#line 510 "cwebdir/ctang-w2c.ch"
{
/*115:*/
-#line 492 "cwebdir/ctang-w2c.ch"
+#line 541 "cwebdir/ctang-w2c.ch"
char in_buf[BUFSIZ+1];
int in_size;
@@ -858,7 +861,7 @@ fatal(_("! Cannot open output file "),check_file_name);
/*:115*/
-#line 462 "cwebdir/ctang-w2c.ch"
+#line 511 "cwebdir/ctang-w2c.ch"
do{
in_size= fread(in_buf,sizeof(char),BUFSIZ,check_file);
@@ -867,7 +870,7 @@ fprintf(stdout,"%s",in_buf);
}while(!feof(check_file));
fclose(check_file);check_file= NULL;
/*111:*/
-#line 451 "cwebdir/ctang-w2c.ch"
+#line 500 "cwebdir/ctang-w2c.ch"
if(comparison)
remove(check_file_name);
@@ -877,19 +880,19 @@ rename(check_file_name,output_file_name);
}
/*:111*/
-#line 469 "cwebdir/ctang-w2c.ch"
+#line 518 "cwebdir/ctang-w2c.ch"
}
/*:112*/
-#line 436 "cwebdir/ctang-w2c.ch"
+#line 485 "cwebdir/ctang-w2c.ch"
else if(0==strcmp("/dev/stderr",output_file_name))
/*113:*/
-#line 474 "cwebdir/ctang-w2c.ch"
+#line 523 "cwebdir/ctang-w2c.ch"
{
/*115:*/
-#line 492 "cwebdir/ctang-w2c.ch"
+#line 541 "cwebdir/ctang-w2c.ch"
char in_buf[BUFSIZ+1];
int in_size;
@@ -899,7 +902,7 @@ fatal(_("! Cannot open output file "),check_file_name);
/*:115*/
-#line 475 "cwebdir/ctang-w2c.ch"
+#line 524 "cwebdir/ctang-w2c.ch"
do{
in_size= fread(in_buf,sizeof(char),BUFSIZ,check_file);
@@ -908,7 +911,7 @@ fprintf(stderr,"%s",in_buf);
}while(!feof(check_file));
fclose(check_file);check_file= NULL;
/*111:*/
-#line 451 "cwebdir/ctang-w2c.ch"
+#line 500 "cwebdir/ctang-w2c.ch"
if(comparison)
remove(check_file_name);
@@ -918,20 +921,20 @@ rename(check_file_name,output_file_name);
}
/*:111*/
-#line 482 "cwebdir/ctang-w2c.ch"
+#line 531 "cwebdir/ctang-w2c.ch"
}
/*:113*/
-#line 438 "cwebdir/ctang-w2c.ch"
+#line 487 "cwebdir/ctang-w2c.ch"
else if(0==strcmp("/dev/null",output_file_name))
/*114:*/
-#line 487 "cwebdir/ctang-w2c.ch"
+#line 536 "cwebdir/ctang-w2c.ch"
{
boolean comparison= true;
/*111:*/
-#line 451 "cwebdir/ctang-w2c.ch"
+#line 500 "cwebdir/ctang-w2c.ch"
if(comparison)
remove(check_file_name);
@@ -941,17 +944,17 @@ rename(check_file_name,output_file_name);
}
/*:111*/
-#line 489 "cwebdir/ctang-w2c.ch"
+#line 538 "cwebdir/ctang-w2c.ch"
}
/*:114*/
-#line 440 "cwebdir/ctang-w2c.ch"
+#line 489 "cwebdir/ctang-w2c.ch"
else{
if((C_file= fopen(output_file_name,"r"))!=NULL){
/*107:*/
-#line 396 "cwebdir/ctang-w2c.ch"
+#line 445 "cwebdir/ctang-w2c.ch"
boolean comparison= false;
@@ -960,7 +963,7 @@ fatal(_("! Cannot open output file "),check_file_name);
/*108:*/
-#line 410 "cwebdir/ctang-w2c.ch"
+#line 459 "cwebdir/ctang-w2c.ch"
do{
char x[BUFSIZ],y[BUFSIZ];
@@ -970,17 +973,17 @@ comparison= (x_size==y_size)&&!memcmp(x,y,x_size);
}while(comparison&&!feof(C_file)&&!feof(check_file));
/*:108*/
-#line 403 "cwebdir/ctang-w2c.ch"
+#line 452 "cwebdir/ctang-w2c.ch"
fclose(C_file);C_file= NULL;
fclose(check_file);check_file= NULL;
/*:107*/
-#line 443 "cwebdir/ctang-w2c.ch"
+#line 492 "cwebdir/ctang-w2c.ch"
/*111:*/
-#line 451 "cwebdir/ctang-w2c.ch"
+#line 500 "cwebdir/ctang-w2c.ch"
if(comparison)
remove(check_file_name);
@@ -990,7 +993,7 @@ rename(check_file_name,output_file_name);
}
/*:111*/
-#line 444 "cwebdir/ctang-w2c.ch"
+#line 493 "cwebdir/ctang-w2c.ch"
}else
rename(check_file_name,output_file_name);
@@ -1074,15 +1077,25 @@ case'\n':if(protect&&out_state!=verbatim)C_putc(' ');
if(protect||out_state==verbatim)C_putc('\\');
flush_buffer();if(out_state!=verbatim)out_state= normal;break;
/*59:*/
-#line 712 "cwebdir/ctangle.w"
+#line 206 "cwebdir/ctang-w2c.ch"
+#line 713 "cwebdir/ctangle.w"
case identifier:
if(out_state==num_or_id)C_putc(' ');
for(j= (cur_val+name_dir)->byte_start,k= (cur_val+name_dir+1)->byte_start;
j<k;j++)
-if((eight_bits)(*j)<0200)C_putc(*j);
+#line 214 "cwebdir/ctang-w2c.ch"
+if(ishigh(*j)){
-else C_printf("%s",translit[(eight_bits)(*j)-0200]);
+if(transliterate_utf_eight){
+if((eight_bits)(*j)>=0360)j+= 3;
+else if((eight_bits)(*j)>=0340)j+= 2;
+else if((eight_bits)(*j)>=0300)j+= 1;
+}
+C_printf("%s",translit[(eight_bits)(*j)-0200]);
+}
+else C_putc(*j);
+#line 720 "cwebdir/ctangle.w"
out_state= num_or_id;break;
/*:59*/
@@ -1188,7 +1201,7 @@ if(loc> limit){
if(is_long_comment){
if(get_line())return comment_continues= true;
else{
-#line 180 "cwebdir/ctang-w2c.ch"
+#line 229 "cwebdir/ctang-w2c.ch"
err_print(_("! Input ended in mid-comment"));
#line 853 "cwebdir/ctangle.w"
@@ -1203,7 +1216,7 @@ loc++;return comment_continues= false;
}
if(c=='@'){
if(ccode[(eight_bits)*loc]==new_section){
-#line 186 "cwebdir/ctang-w2c.ch"
+#line 235 "cwebdir/ctang-w2c.ch"
err_print(_("! Section name ended in mid-comment"));loc--;
#line 866 "cwebdir/ctangle.w"
@@ -1311,13 +1324,13 @@ delim= *loc++;*++id_loc= delim;
while(true){
if(loc>=limit){
if(*(limit-1)!='\\'){
-#line 192 "cwebdir/ctang-w2c.ch"
+#line 241 "cwebdir/ctang-w2c.ch"
err_print(_("! String didn't end"));loc= limit;break;
#line 1016 "cwebdir/ctangle.w"
}
if(get_line()==false){
-#line 198 "cwebdir/ctang-w2c.ch"
+#line 247 "cwebdir/ctang-w2c.ch"
err_print(_("! Input ended in middle of string"));loc= buffer;break;
#line 1020 "cwebdir/ctangle.w"
@@ -1337,7 +1350,7 @@ c= (eight_bits)*loc++;
if(++id_loc<=section_text_end)*id_loc= (char)c;
}
if(id_loc>=section_text_end){
-#line 204 "cwebdir/ctang-w2c.ch"
+#line 253 "cwebdir/ctang-w2c.ch"
fputs(_("\n! String too long: "),stdout);
#line 1038 "cwebdir/ctangle.w"
@@ -1371,14 +1384,14 @@ else if(c=='@')/*75:*/
switch(c= ccode[(eight_bits)*loc++]){
case ignore:continue;
-#line 210 "cwebdir/ctang-w2c.ch"
+#line 259 "cwebdir/ctang-w2c.ch"
case translit_code:err_print(_("! Use @l in limbo only"));continue;
#line 1053 "cwebdir/ctangle.w"
case control_text:while((c= skip_ahead())=='@');
if(*(loc-1)!='>')
-#line 216 "cwebdir/ctang-w2c.ch"
+#line 265 "cwebdir/ctang-w2c.ch"
err_print(_("! Double @ should be used in control text"));
#line 1058 "cwebdir/ctangle.w"
@@ -1394,7 +1407,7 @@ char*k= section_text;
while(true){
if(loc> limit&&get_line()==false){
-#line 234 "cwebdir/ctang-w2c.ch"
+#line 283 "cwebdir/ctang-w2c.ch"
err_print(_("! Input ended in section name"));
#line 1120 "cwebdir/ctangle.w"
@@ -1410,13 +1423,13 @@ if(c=='>'){
loc+= 2;break;
}
if(ccode[(eight_bits)c]==new_section){
-#line 246 "cwebdir/ctang-w2c.ch"
+#line 295 "cwebdir/ctang-w2c.ch"
err_print(_("! Section name didn't end"));break;
#line 1147 "cwebdir/ctangle.w"
}
if(ccode[(eight_bits)c]==section_name){
-#line 252 "cwebdir/ctang-w2c.ch"
+#line 301 "cwebdir/ctang-w2c.ch"
err_print(_("! Nesting of section names not allowed"));break;
#line 1151 "cwebdir/ctangle.w"
@@ -1434,7 +1447,7 @@ c= (eight_bits)' ';if(*(k-1)==' ')k--;
*k= (char)c;
}
if(k>=section_text_end){
-#line 240 "cwebdir/ctang-w2c.ch"
+#line 289 "cwebdir/ctang-w2c.ch"
fputs(_("\n! Section name too long: "),stdout);
#line 1133 "cwebdir/ctangle.w"
@@ -1482,7 +1495,7 @@ case string:/*81:*/
id_first= loc++;*(limit+1)= '@';*(limit+2)= '>';
while(*loc!='@'||*(loc+1)!='>')loc++;
-#line 258 "cwebdir/ctang-w2c.ch"
+#line 307 "cwebdir/ctang-w2c.ch"
if(loc>=limit)err_print(_("! Verbatim string didn't end"));
#line 1165 "cwebdir/ctangle.w"
@@ -1501,7 +1514,7 @@ if(*++loc=='\'')loc++;
while(*loc!='\''){
if(*loc=='@'){
if(*(loc+1)!='@')
-#line 222 "cwebdir/ctang-w2c.ch"
+#line 271 "cwebdir/ctang-w2c.ch"
err_print(_("! Double @ should be used in ASCII constant"));
#line 1082 "cwebdir/ctangle.w"
@@ -1509,7 +1522,7 @@ else loc++;
}
loc++;
if(loc> limit){
-#line 228 "cwebdir/ctang-w2c.ch"
+#line 277 "cwebdir/ctang-w2c.ch"
err_print(_("! String didn't end"));loc= limit-1;break;
#line 1088 "cwebdir/ctangle.w"
@@ -1615,7 +1628,7 @@ char*try_loc= loc;
while(*try_loc==' '&&try_loc<limit)try_loc++;
if(*try_loc=='+'&&try_loc<limit)try_loc++;
while(*try_loc==' '&&try_loc<limit)try_loc++;
-#line 294 "cwebdir/ctang-w2c.ch"
+#line 343 "cwebdir/ctang-w2c.ch"
if(*try_loc=='=')err_print(_("! Missing `@ ' before a named section"));
#line 1291 "cwebdir/ctangle.w"
@@ -1651,7 +1664,7 @@ store_id(a);
}
break;
-#line 282 "cwebdir/ctang-w2c.ch"
+#line 331 "cwebdir/ctang-w2c.ch"
case output_defs_code:if(t!=section_name)err_print(_("! Misplaced @h"));
#line 1263 "cwebdir/ctangle.w"
@@ -1690,7 +1703,7 @@ app_repl(a);
while(id_first<id_loc){
if(*id_first=='@'){
if(*(id_first+1)=='@')id_first++;
-#line 300 "cwebdir/ctang-w2c.ch"
+#line 349 "cwebdir/ctang-w2c.ch"
else err_print(_("! Double @ should be used in string"));
#line 1308 "cwebdir/ctangle.w"
@@ -1744,7 +1757,7 @@ break;
case'\\':c= '\\';break;
case'\'':c= '\'';break;
case'\"':c= '\"';break;
-#line 306 "cwebdir/ctang-w2c.ch"
+#line 355 "cwebdir/ctang-w2c.ch"
default:err_print(_("! Unrecognized escape sequence"));
#line 1357 "cwebdir/ctangle.w"
@@ -1764,7 +1777,7 @@ app_repl(constant);
break;
case definition:case format_code:case begin_C:if(t!=section_name)goto done;
else{
-#line 288 "cwebdir/ctang-w2c.ch"
+#line 337 "cwebdir/ctang-w2c.ch"
err_print(_("! @d, @f and @c are ignored in C text"));continue;
#line 1281 "cwebdir/ctangle.w"
@@ -1780,7 +1793,7 @@ break;
default:app_repl(a);
}
done:next_control= (eight_bits)a;
-#line 276 "cwebdir/ctang-w2c.ch"
+#line 325 "cwebdir/ctang-w2c.ch"
if(text_ptr> text_info_end)overflow(_("text"));
#line 1216 "cwebdir/ctangle.w"
cur_text= text_ptr;(++text_ptr)->tok_start= tok_ptr;
@@ -1819,7 +1832,7 @@ if(next_control==definition){
while((next_control= get_next())=='\n');
if(next_control!=identifier){
-#line 312 "cwebdir/ctang-w2c.ch"
+#line 361 "cwebdir/ctang-w2c.ch"
err_print(_("! Definition flushed, must start with identifier"));
#line 1430 "cwebdir/ctangle.w"
@@ -1930,7 +1943,7 @@ while(xisspace(*loc)&&loc<limit)loc++;
loc+= 3;
if(loc> limit||!xisxdigit(*(loc-3))||!xisxdigit(*(loc-2))
||(*(loc-3)>='0'&&*(loc-3)<='7')||!xisspace(*(loc-1)))
-#line 332 "cwebdir/ctang-w2c.ch"
+#line 381 "cwebdir/ctang-w2c.ch"
err_print(_("! Improper hex number following @l"));
#line 1529 "cwebdir/ctangle.w"
@@ -1940,9 +1953,9 @@ char*beg;
sscanf(loc-3,"%x",&i);
while(xisspace(*loc)&&loc<limit)loc++;
beg= loc;
-while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||*loc=='_'))loc++;
+while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||isxalpha(*loc)))loc++;
if(loc-beg>=translit_length)
-#line 338 "cwebdir/ctang-w2c.ch"
+#line 387 "cwebdir/ctang-w2c.ch"
err_print(_("! Replacement string in @l too long"));
#line 1539 "cwebdir/ctangle.w"
@@ -1959,12 +1972,12 @@ case format_code:case'@':break;
case control_text:if(c=='q'||c=='Q'){
while((c= (char)skip_ahead())=='@');
if(*(loc-1)!='>')
-#line 318 "cwebdir/ctang-w2c.ch"
+#line 367 "cwebdir/ctang-w2c.ch"
err_print(_("! Double @ should be used in control text"));
#line 1511 "cwebdir/ctangle.w"
break;
-#line 325 "cwebdir/ctang-w2c.ch"
+#line 374 "cwebdir/ctang-w2c.ch"
}/* otherwise fall through */
default:err_print(_("! Double @ should be used in limbo"));
#line 1515 "cwebdir/ctangle.w"
@@ -1979,7 +1992,7 @@ default:err_print(_("! Double @ should be used in limbo"));
void
print_stats(void){
-#line 351 "cwebdir/ctang-w2c.ch"
+#line 400 "cwebdir/ctang-w2c.ch"
puts(_("\nMemory usage statistics:"));
printf(_("%td names (out of %ld)\n"),
(ptrdiff_t)(name_ptr-name_dir),(long)max_names);
@@ -1992,5 +2005,5 @@ printf(_("%td tokens (out of %ld)\n"),
(ptrdiff_t)(tok_ptr-tok_mem),(long)max_toks);
}
-#line 364 "cwebdir/ctang-w2c.ch"
+#line 413 "cwebdir/ctang-w2c.ch"
/*:103*/
diff --git a/Build/source/texk/web2c/cwebdir/ChangeLog b/Build/source/texk/web2c/cwebdir/ChangeLog
index 7aa44a8a43c..23200f88c01 100644
--- a/Build/source/texk/web2c/cwebdir/ChangeLog
+++ b/Build/source/texk/web2c/cwebdir/ChangeLog
@@ -1,3 +1,10 @@
+2022-08-21 Andreas Scherer <https://ascherer.github.io>
+
+ * ctang-w2c.ch,
+ * ctangle.c,
+ * ctangle.w,
+ * cwebman-w2c.ch: New option '+u' for CTANGLE.
+
2022-07-02 Andreas Scherer <https://ascherer.github.io>
* cwebmac.tex,
diff --git a/Build/source/texk/web2c/cwebdir/ctang-w2c.ch b/Build/source/texk/web2c/cwebdir/ctang-w2c.ch
index 9b115568f4f..d12ffd85066 100644
--- a/Build/source/texk/web2c/cwebdir/ctang-w2c.ch
+++ b/Build/source/texk/web2c/cwebdir/ctang-w2c.ch
@@ -175,6 +175,55 @@ if (check_for_change)
@z
@x
+@ @<Case of an identifier@>=@t\1\quad@>
+@y
+@ Nowadays, most computer files are encoded in some form of ``Unicode''. A very
+convenient special case is ``UTF-8'', a variable-length multi-byte encoding. In
+order to avoid major surgery for the transliteration feature---as tempting as
+the extended notation \.{@@l c3bc ue} might be---, \.{CTANGLE}
+accepts the \.{+u} option to activate a ``poor man's UTF-8'' mechanism. The
+first in a sequence of up to four high-bit bytes (amounting to more than
+$2^{20}$~possible character representations) determines the number of bytes
+used to represent the next character. Instead of extending the |translit| table
+to this multi-byte scenario, we simply strip all but the last byte and use this
+as the transliteration index.
+
+% Exercise 11.6 from the TeXbook:
+\def\frac#1/#2{\leavevmode\kern.1em\raise.5ex\hbox{\the\scriptfont0 #1}
+ \kern-.1em/\kern-.15em\lower.25ex\hbox{\the\scriptfont0 #2}}
+
+\&{Example:} While in ``classic ASCII'' the German word {\it gr\"un\/} could be
+treated with transliteration \.{@@l fc ue} (from codepage ISO/IEC~8859-1) to
+get \.{gruen} as suggested above, in UTF-8 you'd be advised to use \.{@@l bc
+ue} instead, because character {\it \"u\/} (latin small letter u with
+diaeresis) is encoded as the two-byte sequence \.{c3 bc}, indicated by the
+initial three bits of byte \.{c3} (\.{1100 0011}). Note that this simple
+approach leads to the collision with character $\frac1/4$ (vulgar fraction one
+quarter) with its two-byte encoding \.{c2 bc}.
+
+@d transliterate_utf_eight flags['u']
+
+@<Case of an identifier@>=@t\1\quad@>
+@z
+
+@x
+ if ((eight_bits)(*j)<0200) C_putc(*j);
+@^high-bit character handling@>
+ else C_printf("%s",translit[(eight_bits)(*j)-0200]);
+@y
+ if (ishigh(*j)) {
+@^high-bit character handling@>
+ if (transliterate_utf_eight) {
+ if ((eight_bits)(*j)>=0360) j+=3;
+ else if ((eight_bits)(*j)>=0340) j+=2;
+ else if ((eight_bits)(*j)>=0300) j+=1;
+ }
+ C_printf("%s",translit[(eight_bits)(*j)-0200]);
+ }
+ else C_putc(*j);
+@z
+
+@x
err_print("! Input ended in mid-comment");
@y
err_print(_("! Input ended in mid-comment"));
diff --git a/Build/source/texk/web2c/cwebdir/ctangle.c b/Build/source/texk/web2c/cwebdir/ctangle.c
index 262469d6119..8f6b14e260c 100644
--- a/Build/source/texk/web2c/cwebdir/ctangle.c
+++ b/Build/source/texk/web2c/cwebdir/ctangle.c
@@ -330,7 +330,7 @@ static boolean output_defs_seen= false;
/*:52*//*57:*/
#line 703 "ctangle.w"
-static char translit[128][translit_length];
+static char translit[0200][translit_length];
/*:57*//*62:*/
#line 779 "ctangle.w"
@@ -484,7 +484,7 @@ cur_out_file= end_output_files= output_files+max_files;
{
int i;
-for(i= 0;i<128;i++)sprintf(translit[i],"X%02X",(unsigned int)(128+i));
+for(i= 0;i<0200;i++)sprintf(translit[i],"X%02X",(unsigned int)(0200+i));
}
/*:58*//*63:*/
@@ -1607,7 +1607,7 @@ char*beg;
sscanf(loc-3,"%x",&i);
while(xisspace(*loc)&&loc<limit)loc++;
beg= loc;
-while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||*loc=='_'))loc++;
+while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||isxalpha(*loc)))loc++;
if(loc-beg>=translit_length)
err_print("! Replacement string in @l too long");
diff --git a/Build/source/texk/web2c/cwebdir/ctangle.w b/Build/source/texk/web2c/cwebdir/ctangle.w
index 0c372e59ed8..af4f4e92811 100644
--- a/Build/source/texk/web2c/cwebdir/ctangle.w
+++ b/Build/source/texk/web2c/cwebdir/ctangle.w
@@ -690,8 +690,8 @@ case period_ast: C_putc('.');@+C_putc('*'); out_state=normal; break;
case minus_gt_ast: C_putc('-');@+C_putc('>');@+C_putc('*'); out_state=normal;
break;
-@ When an identifier is output to the \CEE/ file, characters in the
-range 128--255 must be changed into something else, so the \CEE/
+@ When an identifier is output to the \CEE/ file, characters in the range
+128--255 (|0200|--|0377|) must be changed into something else, so the \CEE/
compiler won't complain. By default, \.{CTANGLE} converts the
character with code $16 x+y$ to the three characters `\.X$xy$', but
a different transliteration table can be specified. Thus a German
@@ -701,12 +701,12 @@ This makes debugging a lot less confusing.
@d translit_length 10
@<Private...@>=
-static char translit[128][translit_length];
+static char translit[0200][translit_length];
@ @<Set init...@>=
{
int i;
- for (i=0;i<128;i++) sprintf(translit[i],"X%02X",(unsigned int)(128+i));
+ for (i=0;i<0200;i++) sprintf(translit[i],"X%02X",(unsigned int)(0200+i));
}
@ @<Case of an identifier@>=@t\1\quad@>
@@ -1533,7 +1533,7 @@ skip_limbo(void)
sscanf(loc-3,"%x",&i);
while(xisspace(*loc)&&loc<limit) loc++;
beg=loc;
- while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||*loc=='_')) loc++;
+ while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||isxalpha(*loc))) loc++;
if (loc-beg>=translit_length)
err_print("! Replacement string in @@l too long");
@.Replacement string in @@l...@>
diff --git a/Build/source/texk/web2c/cwebdir/cwebman-w2c.ch b/Build/source/texk/web2c/cwebdir/cwebman-w2c.ch
index fb8421349a3..73a907deb5e 100644
--- a/Build/source/texk/web2c/cwebdir/cwebman-w2c.ch
+++ b/Build/source/texk/web2c/cwebdir/cwebman-w2c.ch
@@ -182,13 +182,13 @@ more logical than indenting them.) (Has no effect on \.{CTANGLE}.)
\hfil\vskip\normallineskip
\option l This option takes the string of characters to its right as its
argument to switch between different user languages and macro packages.
-For example, if you call \.{CWEAVE} with the `\.{+ld}' (or `\.{-ld}') option,
-the German \.{CWEB} macros \.{dcwebmac.tex} will be loaded in the first line
-of output instead of the English ones. (Off by default.) (Has no effect on
-\.{CTANGLE}.)
+(Off by default.) (Has no effect on \.{CTANGLE}.)
\hfil\vskip\normallineskip
\option o Separate declarations and the first statement in a function block.
-(On by default.) (Has no effect on\break\hbox{}\qquad\.{CTANGLE}.)}
+(On by default.) (Has no effect on \.{CTANGLE}.)
+\hfil\vskip\normallineskip
+\option u Transliteration of UTF-8 multi-byte characters.
+(Off by default.) (Has no effect on \.{CWEAVE}.)}
\yskip
@z
diff --git a/Build/source/texk/web2c/help.h b/Build/source/texk/web2c/help.h
index 668d3f9f98c..df52bf7679b 100644
--- a/Build/source/texk/web2c/help.h
+++ b/Build/source/texk/web2c/help.h
@@ -65,6 +65,7 @@ const_string CTANGLEHELP[] = {
"-dN set 'kpathsea_debug' to N (0..127)",
"+k keep separators in numeric literals in the output",
"+s print usage statistics",
+ "+u transliterate UTF-8 characters in C code",
"--help display this help and exit",
"--version output version information and exit",
NULL
diff --git a/Build/source/texk/web2c/man/ChangeLog b/Build/source/texk/web2c/man/ChangeLog
index 95a11e7d444..b8a2a842f05 100644
--- a/Build/source/texk/web2c/man/ChangeLog
+++ b/Build/source/texk/web2c/man/ChangeLog
@@ -1,3 +1,7 @@
+2022-08-21 Andreas Scherer <https://ascherer.github.io>
+
+ * cweb.man: New option '+u' for CTANGLE.
+
2022-06-05 Andreas Scherer <https://ascherer.github.io>
* ctwill.man: CWEB 4.8 release.
diff --git a/Build/source/texk/web2c/man/cweb.man b/Build/source/texk/web2c/man/cweb.man
index fd481db48d4..b1d051551fe 100644
--- a/Build/source/texk/web2c/man/cweb.man
+++ b/Build/source/texk/web2c/man/cweb.man
@@ -14,7 +14,7 @@
. ftr VB CB
. ftr VBI CBI
.\}
-.TH "CWEB" "1" "July 27, 2021" "Web2c @VERSION@" "General Commands Manual"
+.TH "CWEB" "1" "August 20, 2022" "Web2c @VERSION@" "General Commands Manual"
.hy
.SH NAME
.PP
@@ -70,7 +70,7 @@ There are, however, a few differences worth noting:
.IP \[bu] 2
Options \f[B]--help\f[R], \f[B]--quiet\f[R], \f[B]--verbose\f[R],
\f[B]--version\f[R], and flags \f[B]+c\f[R], \f[B]-i\f[R], \f[B]-o\f[R],
-and \f[B]+lX\f[R] are new in CWEBbin and TeX\ Live.
+\f[B]+u\f[R], and \f[B]+lX\f[R] are new in CWEBbin and TeX\ Live.
.IP \[bu] 2
Option \f[B]+lX\f[R] is accompanied by several wrapper files for
\f[B]cwebmac.tex\f[R] with translated captions for German
@@ -120,6 +120,8 @@ The first batch of options are common to both \f[B]ctangle\f[R] and
There is one other option applicable to \f[B]ctangle\f[R] only:
.IP \[bu] 2
\f[B]+k\f[R]: keep separators in numeric literals in the output
+.IP \[bu] 2
+\f[B]+u\f[R]: transliterate UTF-8 charcters in C code
.PP
There are seven other options applicable to \f[B]cweave\f[R] only:
.IP \[bu] 2