]> git.draconx.ca Git - dxcommon.git/commitdiff
gen-strtab.awk: Work around portability problems with \\\\.
authorNick Bowler <nbowler@draconx.ca>
Wed, 4 Jan 2023 03:41:58 +0000 (22:41 -0500)
committerNick Bowler <nbowler@draconx.ca>
Wed, 4 Jan 2023 03:41:58 +0000 (22:41 -0500)
It seems that mawk, and also gawk in POSIX mode, handle backslashes
in the (g)sub replacement strings strangely.  For example:

  % echo 'hello' | mawk '{ sub(/e/, "\\\\"); print }'
  h\llo

  % echo 'hello' | gawk '{ sub(/e/, "\\\\"); print }'
  h\\llo

  % echo 'hello' | POSIXLY_CORRECT=1 gawk '{ sub(/e/, "\\\\"); print }'
  h\llo

This causes errors when the script tries to use gsub to restore
the double backslashes on these implementations.  There seems to
be no trouble substiting "\\" to get a single backslash, so we
can work around the problem by doubling up the characters being
replaced instead (which additionally requires an adjustment to
the length calculations to reverse this).

scripts/gen-strtab.awk

index 7e3de127972c066aa765bfdc3f882e7e4986d7fb..f14bda959db040f4428ee2ad6f08f4f17643d814 100755 (executable)
@@ -144,7 +144,7 @@ END {
 
   for (i = 0; i < count; i++) {
     s = sorted_strings[i]
-    gsub(/\\\\/, "\2", s)
+    gsub(/\\\\/, "\2\2", s)
     if ((n = index(strtab "\1", s "\1")) > 0) {
       offsets[sorted_strings[i]] = real_length(substr(strtab, 1, n-1));
       if (!(sorted_strings[i] in nol10n))
@@ -160,7 +160,7 @@ END {
     }
   }
 
-  gsub(/\2/, "\\\\", strtab);
+  gsub(/\2/, "\\", strtab);
   n = split(strtab, split_strtab, "\1");
   for (i = 1; i <= n; i++) {
     printf("\t%4s ", i > !!opts["zero"] ? "\"\\0\"" : "");
@@ -187,13 +187,13 @@ END {
   print "\n#define STRTAB_MAX_OFFSET " max
 }
 
-# finish_input_string(strings, ident, val)
+# finish_string_input(strings, ident, val)
 #
 # Deal with backslash-escapes and special characters in val, then set
 # strings[ident] = val.
 function finish_string_input(strings, ident, val, n, tmpval)
 {
-  gsub(/\\\\/, "\1", val)
+  gsub(/\\\\/, "\1\1", val)
   val = val (endline > startline ? "\n" : "")
   gsub(/\\\n/, "", val)
 
@@ -208,7 +208,7 @@ function finish_string_input(strings, ident, val, n, tmpval)
   gsub(/"/, "\\\"", tmpval)
   gsub(/\t/, "\\t", tmpval)
   gsub(/\n/, "\\n", tmpval)
-  gsub(/\1/, "\\\\", tmpval)
+  gsub(/\1/, "\\", tmpval)
 
   strings[ident] = tmpval
   if (!current_l10n) {
@@ -219,7 +219,7 @@ function finish_string_input(strings, ident, val, n, tmpval)
 function real_length(s, t)
 {
   t = length(s)
-  return t - gsub(/\\./, "&", s)
+  return t - gsub(/\\.|\2\2/, "&", s)
 }
 
 # bucketsort(dst, src)