ときどきの雑記帖 RE* (新南口)
Ghost in the Machine
夏休み
ではあるのだが以下略
つれづれなる数学日記
読んだ。
日記が3/2から始まって翌年の3/1までなのは何か深い意味があるんだろうか? いくつか気になる記述があったけどまあそれはそれ。
特に印象に残ったのはこの二つかな。
12/25 100以下の素数は25個
4/2
まず平面上に3つの点を打つ。 これをA, B, C と名付けよう。 A, B,Cは正三角形に近い形にするとよい。 そうやってできあがる三角形ABCの内部に4つ目の点 (Dとしよう)を打つ。 そしてA, B, Cの中から好きに1つ選んで、 Dとの中点を打つ。 こんどはそうやってできた中点と A, B, C のいずれかとの中点を打つ。 さらに新しく作られた中点と A, B, C のいずれかから選んで中点を打つ。 これを何度も繰り返す。
するとなんと 「シェルピンスキーのギャスケット」ができることが知られている。
Ghostscript
Ghostscript 9.56.1で新しいPDFインタプリタが採用へ。-dNEWPDF=falseを指定することで古い物も利用継続が可能。古い物はPostScriptで記述されていたが今回はCで書き直されている。PDFはPostScriptの発展であり相似性があったためにPSの採用は不思議でも無かったが新しいエンジニアの採用等に難がw https://t.co/0KusQzTLZ8
— 高梨陣平 (@jingbay) July 31, 2022
w
をつける意図がよくわからんけどそれはそれとして、
Ghostscript : PDFI
からソースコードをダウンロードして眺めてみる。
ghostscript-9.56.1/pdfにあるのがpdf関連のファイルかな (9.56から増えているらしいので、それより前のバージョンのアーカイブで このディレクトリがあるか確かめればはっきりするのだろうけど)。
ghostscript-9.56.1\pdf のディレクトリ
2022/04/04 22:48 74,553 ghostpdf.c
2022/04/04 22:48 18,867 ghostpdf.h
2022/04/04 22:48 16,043 pdf.mak
2022/04/04 22:48 1,008 pdfromfs.mak
2022/04/04 22:48 28,776 pdftop.c
(略)
2022/04/04 22:48 4,401 pdf_utf8.c
2022/04/04 22:48 768 pdf_utf8.h
2022/04/04 22:48 3,677 pdf_warnings.h
2022/04/04 22:48 39,096 pdf_xref.c
2022/04/04 22:48 692 pdf_xref.h
89 個のファイル 3,666,126 バイト
結構な分量だ(ファイルの中身までは見てない)。 話のついでに これまでのPostScriptで書かれていたというバージョンはどんなものだろうかと調べてみた。
まずはpdf
を名前に含む.psファイルを探す。
>dir *pdf*ps /s
ghostscript-9.56.1\devices\vector のディレクトリ
2022/04/04 22:48 151,696 opdfread.ps
1 個のファイル 151,696 バイト
ghostscript-9.56.1\lib のディレクトリ
2022/04/04 22:48 8,063 pdf2dsc.ps
2022/04/04 22:48 909 pdf2ps
2022/04/04 22:48 3,055 PDFA_def.ps
2022/04/04 22:48 3,864 PDFX_def.ps
2022/04/04 22:48 15,152 pdf_info.ps
5 個のファイル 31,043 バイト
ghostscript-9.56.1\Resource\Init のディレクトリ
2022/04/04 22:48 33,195 gs_pdfwr.ps
2022/04/04 22:48 1,556 gs_pdf_e.ps
2022/04/04 22:48 61,431 pdf_base.ps
2022/04/04 22:48 192,499 pdf_draw.ps
2022/04/04 22:48 99,477 pdf_font.ps
2022/04/04 22:48 177,245 pdf_main.ps
2022/04/04 22:48 76,597 pdf_ops.ps
2022/04/04 22:48 20,480 pdf_rbld.ps
2022/04/04 22:48 27,865 pdf_sec.ps
9 個のファイル 690,345 バイト
ふむ。pdf2psというのがいかにも変換に使いますという名前に見える。
今回の目当ては逆(PostScript→PDF)なので
同じディレクトリから
ps2pdf
を探してみる。
ghostscript-9.56.1\lib のディレクトリ
2022/04/04 22:48 272 ps2pdf
2022/04/04 22:48 586 ps2pdf.bat
2022/04/04 22:48 909 ps2pdf.cmd
2022/04/04 22:48 215 ps2pdf12
2022/04/04 22:48 404 ps2pdf12.bat
2022/04/04 22:48 272 ps2pdf12.cmd
2022/04/04 22:48 215 ps2pdf13
2022/04/04 22:48 404 ps2pdf13.bat
2022/04/04 22:48 272 ps2pdf13.cmd
2022/04/04 22:48 215 ps2pdf14
2022/04/04 22:48 404 ps2pdf14.bat
2022/04/04 22:48 272 ps2pdf14.cmd
2022/04/04 22:48 1,078 ps2pdfwr
2022/04/04 22:48 1,442 ps2pdfxx.bat
14 個のファイル 6,960 バイト
お、それっぽいものが。
ps2pdfはバージョンに応じて対応する ps2pdf{12,13,14}というシェルスクリプトを起動するだけの シェルスクリプトなので、 一番新しい(つってもいつのだっけ1.4て) ps2pdf14を見る。
すると
#!/bin/sh
# Convert PostScript to PDF 1.4 (Acrobat 5-and-later compatible).
ps2pdfwr="`dirname \"$0\"`/ps2pdfwr"
if test ! -x "$ps2pdfwr"; then
ps2pdfwr="ps2pdfwr"
fi
exec "$ps2pdfwr" -dCompatibilityLevel=1.4 "$@"
これまた別のシェルスクリプトを起動していた。 ここで呼び出しているps2pdfwrはというと
#!/bin/sh
# Convert PostScript to PDF without specifying CompatibilityLevel.
# This definition is changed on install to match the
# executable name set in the makefile
GS_EXECUTABLE=gs
gs="`dirname \"$0\"`/$GS_EXECUTABLE"
if test ! -x "$gs"; then
gs="$GS_EXECUTABLE"
fi
GS_EXECUTABLE="$gs"
OPTIONS="-P- -dSAFER"
while true
do
case "$1" in
-?*) OPTIONS="$OPTIONS $1" ;;
*) break ;;
esac
shift
done
if [ $# -lt 1 -o $# -gt 2 ]; then
echo "Usage: `basename \"$0\"` [options...] (input.[e]ps|-) [output.pdf|-]" 1>&2
exit 1
fi
infile="$1";
if [ $# -eq 1 ]
then
case "${infile}" in
-) outfile=- ;;
*.eps) base=`basename "${infile}" .eps`; outfile="${base}.pdf" ;;
*.ps) base=`basename "${infile}" .ps`; outfile="${base}.pdf" ;;
*) base=`basename "${infile}"`; outfile="${base}.pdf" ;;
esac
else
outfile="$2"
fi
# We have to include the options twice because -I only takes effect if it
# appears before other options.
exec "$GS_EXECUTABLE" $OPTIONS -q -P- -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sstdout=%stderr "-sOutputFile=$outfile" $OPTIONS "$infile"
いろいろやってるけど、要するにGhostScriptインタープリターに pdfを作成させるためのオプションを渡して起動しているようだ。
せっかくなので(ry、pdfwriteの定義と思われるところを ざっと見てみたけどパラメーターを色々設定しているだけのようで よくわからんな。
gs_pdfwr.ps
% Copyright (C) 2001-2021 Artifex Software, Inc.
% All Rights Reserved.
%
% This software is provided AS-IS with no warranty, either express or
% implied.
%
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
%
% Refer to licensing information at http://www.artifex.com or contact
% Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
% CA 94945, U.S.A., +1(415)492-9861, for further information.
%
% PDF writer additions to systemdict.
% This file should be included iff the pdfwrite "device" is included
% in the executable.
% ---------------- Predefined configurations ---------------- %
% These correspond to the 4 predefined settings in Acrobat Distiller 5,
% plus a "default" setting that doesn't downsample images.
{ /pdfwrite finddevice pop } .internalstopped
{pop pop (%END PDFWR) .skipeof} if
languagelevel 2 .setlanguagelevel
/.a2112 [2 1 1 2] readonly def
/.a1111 [1 1 1 1] readonly def
/.standardfonts [
/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique
/Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique
/Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic
/Symbol /ZapfDingbats
] readonly def
% Parameters common to all non-default configurations.
% Note that the default configuration overrides a few of these.
(ざっくり省略)
.dicttomark readonly
.dicttomark readonly def
% ---------------- End of predefined configurations ---------------- %
% ---------------- pdfmark and DSC processing ---------------- %
(以下略)
変換元のPostScriptプログラムを「PDFに描画」させることで変換しているのだろうから、 変換時の操作はもっと深いところまで潜っていかないとわからないというところか。
Zig
シフト量でトラップを発生するプロセッサはないと思うのでこれシフト操作前にチェックしてるのかな https://t.co/6t4AkKwuxK
— ほうめい マイコンで遊んでばっかりで (@houmei) August 13, 2022
同じような疑問を持ったので(ry (最初にコンパイラーのソースコードを読みにいってよくわからなかったのはナイショのハナシ)
Zigのビットシフト演算がちょっと面白い - その手の平は尻もつかめるさ
const n: u8 = 0b00000001;
const shift_amout: u3 = 7;
var shifted: u8 = n << (shift_amout);
var additional_shift_amount: u3 = 1;
var i: u3 = 0;
while (i < additional_shift_amount) {
shifted = shifted << 1;
i += 1;
}
std.debug.print("{b}\n", .{shifted}); // => 0
とは言えコンパイラーをインストールして試すのはちょっと面倒かなあと思っていたら Compiler Explorer がZigにも対応していたのでありがたく使わせてもらった。
まずは前述のコードを少しいじったこんなので。
const std = @import("std");
export fn func() void {
const n: u8 = 0b00000001;
const shift_amout: u3 = 7;
var shifted: u8 = n << (shift_amout);
var additional_shift_amount: u3 = 3;
shifted = shifted << additional_shift_amount;
shifted = shifted << additional_shift_amount;
shifted = shifted << additional_shift_amount;
//std.debug.print("{b}\n", .{shifted}); // => 0
}
これをCompiler Explorerに渡すと 出力されたアセンブリコードはこうなった。
panic:
push rbp
mov rbp, rsp
sub rsp, 16
mov qword ptr [rbp - 8], rsi
call zig_panic@PLT
func:
push rbp
mov rbp, rsp
sub rsp, 2
mov byte ptr [rbp - 1], -128
mov byte ptr [rbp - 2], 3
mov al, byte ptr [rbp - 1]
mov cl, byte ptr [rbp - 2]
shl al, cl
mov byte ptr [rbp - 1], al
mov al, byte ptr [rbp - 1]
mov cl, byte ptr [rbp - 2]
shl al, cl
mov byte ptr [rbp - 1], al
mov al, byte ptr [rbp - 1]
mov cl, byte ptr [rbp - 2]
shl al, cl
mov byte ptr [rbp - 1], al
add rsp, 2
pop rbp
ret
関数本体のものより先に出てくるpanic
というのは
ここでは呼び出している気配がないけどナニモノだろう?
それと、変数の宣言と初期化のところで設定している値は
コンパイラーがあらかじめ定数にして
(mov byte ptr [rbp - 1], -128
)
ますね、
二個目以降のシフト演算は素直に計算しているのがよくわからんけど、 今回はそっちの方が助かる(設定で変わるのかも)。 3回のシフト演算で合計9ビット左シフトしているので 1バイトの大きさを完全に超えているのに、 特に何も手当てしているようには見えない。
そこでzigのコードをこう変えると
const std = @import("std");
export fn func() void {
const n: u8 = 0b00000001;
const shift_amout: u3 = 7;
var shifted: u8 = n << (shift_amout);
var additional_shift_amount: u3 = 3;
shifted = shifted << (additional_shift_amount+1);
shifted = shifted << additional_shift_amount;
shifted = shifted << additional_shift_amount;
//std.debug.print("{b}\n", .{shifted}); // => 0
}
出力されるアセンブリにpanic
を呼び出すコード
(call panic
)が現れる。
panic:
push rbp
mov rbp, rsp
sub rsp, 16
mov qword ptr [rbp - 8], rsi
call zig_panic@PLT
func:
push rbp
mov rbp, rsp
sub rsp, 16
mov byte ptr [rbp - 1], -128
mov byte ptr [rbp - 2], 3
mov al, byte ptr [rbp - 1]
mov byte ptr [rbp - 4], al
mov cl, byte ptr [rbp - 2]
inc cl
mov al, cl
shr al, 3
mov byte ptr [rbp - 3], cl
test al, 1
jne .LBB1_1
jmp .LBB1_2
.LBB1_1:
movabs rdi, offset __unnamed_1
xor eax, eax
mov esi, eax
call panic
.LBB1_2:
mov al, byte ptr [rbp - 4]
mov cl, byte ptr [rbp - 3]
and cl, 7
shl al, cl
mov byte ptr [rbp - 1], al
mov al, byte ptr [rbp - 1]
mov cl, byte ptr [rbp - 2]
shl al, cl
mov byte ptr [rbp - 1], al
mov al, byte ptr [rbp - 1]
mov cl, byte ptr [rbp - 2]
shl al, cl
mov byte ptr [rbp - 1], al
add rsp, 16
pop rbp
ret
__unnamed_4:
.asciz "integer overflow"
__unnamed_1:
.quad __unnamed_4
.quad 16
自分で設定した左シフトの量とたまたま一緒だったので、
なぜshr al, 3
と右に3ビットシフトしている
のかがすぐには理解できなかったのだけど、これは
mov al, cl
shr al, 3
mov byte ptr [rbp - 3], cl
test al, 1
jne .LBB1_1
jmp .LBB1_2
.LBB1_1:
movabs rdi, offset __unnamed_1
xor eax, eax
mov esi, eax
call panic
.LBB1_2:
シフト量を3ビット右シフトした結果が
1以上であるかを検査して
1以上なら(つまり元々のシフト量が8以上なら)
call panic
するという流れ。
ところで
additional_shift_amount+1
を
additional_shift_amount+0
のようにしても
// Type your code here, or load an example.
const std = @import("std");
export fn func() void {
const n: u8 = 0b00000001;
const shift_amout: u3 = 7;
var shifted: u8 = n << (shift_amout);
var additional_shift_amount: u3 = 3;
shifted = shifted << (additional_shift_amount+0);
shifted = shifted << additional_shift_amount;
shifted = shifted << additional_shift_amount;
//std.debug.print("{b}\n", .{shifted}); // => 0
}
同様にcall panic
するコードが出力されるので、
シフト演算子の第2オペランドが算術式かどうかで変わるのかな?
panic:
push rbp
mov rbp, rsp
sub rsp, 16
mov qword ptr [rbp - 8], rsi
call zig_panic@PLT
func:
push rbp
mov rbp, rsp
sub rsp, 16
mov byte ptr [rbp - 1], -128
mov byte ptr [rbp - 2], 3
mov al, byte ptr [rbp - 1]
mov byte ptr [rbp - 4], al
mov cl, byte ptr [rbp - 2]
xor eax, eax
mov byte ptr [rbp - 3], cl
test al, 1
jne .LBB1_1
jmp .LBB1_2
.LBB1_1:
movabs rdi, offset __unnamed_1
xor eax, eax
mov esi, eax
call panic
.LBB1_2:
mov al, byte ptr [rbp - 4]
mov cl, byte ptr [rbp - 3]
and cl, 7
shl al, cl
mov byte ptr [rbp - 1], al
mov al, byte ptr [rbp - 1]
mov cl, byte ptr [rbp - 2]
shl al, cl
mov byte ptr [rbp - 1], al
mov al, byte ptr [rbp - 1]
mov cl, byte ptr [rbp - 2]
shl al, cl
mov byte ptr [rbp - 1], al
add rsp, 16
pop rbp
ret
__unnamed_4:
.asciz "integer overflow"
__unnamed_1:
.quad __unnamed_4
.quad 16
でもなんか変なコードだな。
$ diff -u 0.asm 1.asm
--- 0.asm
+++ 1.asm
@@ -14,7 +14,9 @@
mov al, byte ptr [rbp - 1]
mov byte ptr [rbp - 4], al
mov cl, byte ptr [rbp - 2]
- xor eax, eax
+ inc cl
+ mov al, cl
+ shr al, 3
mov byte ptr [rbp - 3], cl
test al, 1
jne .LBB1_1
ソースコードが+0
の方は
xor eax, eax
の結果に対して
test al, 1
している?
あとは単純な数式で試してみる (通常の整数型を使うとコンパイルエラー?)。
// Type your code here, or load an example.
const std = @import("std");
export fn func() void {
const n: u8 = 0b00000001;
const shift_amout: u3 = 7;
var shifted: u8 = n << (shift_amout);
var additional_shift_amount: u3 = 3;
//var additional_shift_amount: u8 = 3;
shifted = shifted << 3+3+3;
shifted = shifted << additional_shift_amount;
shifted = shifted << additional_shift_amount;
//std.debug.print("{b}\n", .{shifted}); // => 0
}
./example.zig:11:29: error: integer value 9 cannot be coerced to type 'u3'
shifted = shifted << 3+3+3;
^
./example.zig:11:23: note: referenced here
shifted = shifted << 3+3+3;
^
Compiler returned: 1
8以上になるかどうかコンパイル時に判定していた。 もうひとつ8を超えない範囲で
// Type your code here, or load an example.
const std = @import("std");
export fn func() void {
const n: u8 = 0b00000001;
const shift_amout: u3 = 7;
var shifted: u8 = n << (shift_amout);
var additional_shift_amount: u3 = 3;
//var additional_shift_amount: u8 = 3;
shifted = shifted << 3+3;
shifted = shifted << additional_shift_amount;
shifted = shifted << additional_shift_amount;
//std.debug.print("{b}\n", .{shifted}); // => 0
}
panic:
push rbp
mov rbp, rsp
sub rsp, 16
mov qword ptr [rbp - 8], rsi
call zig_panic@PLT
func:
push rbp
mov rbp, rsp
sub rsp, 2
mov byte ptr [rbp - 1], -128
mov byte ptr [rbp - 2], 3
mov al, byte ptr [rbp - 1]
shl al, 6
mov byte ptr [rbp - 1], al
mov al, byte ptr [rbp - 1]
mov cl, byte ptr [rbp - 2]
shl al, cl
mov byte ptr [rbp - 1], al
mov al, byte ptr [rbp - 1]
mov cl, byte ptr [rbp - 2]
shl al, cl
mov byte ptr [rbp - 1], al
add rsp, 2
pop rbp
ret
もっと複雑な式で試すのは読者への宿題ということで。
関数の戻り値
以前にも言及した Excel VBAのびみょいところ - Qiita の
関数の戻り値を返す方法がreturnじゃない。
に関して。
該当記事のコメント https://qiita.com/zakuroishikuro/items/81ddd7a33fb346aeb6a0#comment-0ba44082cbfa73c618ff や https://qiita.com/zakuroishikuro/items/81ddd7a33fb346aeb6a0#comment-49c72f4c66cdc0f71df8 に
Functionと同じ名前の変数に代入した値がその戻り値になる。
VBAを知ったとき、なんでこういう仕様の言語がほとんどないのか理解した。Pascalはそうなのでその辺りからの借用なんじゃないのと思ったり
訂正:
Pascalはそうなのでその辺りからの借用なんじゃないのと思ったり
Pascal以前のALGOL 60で既にそういう書き方をしてたみたいです。
Function definition - Rosetta Code
とあるのだけどALGOLは60の前に58があったわけで、 じゃあALGOL-58には値を返す手続き(関数)がなかったのか? と思って調べると58にもちゃんと(?)それはあったらしい。 それなのにRosetta CodeにALGOL-58のコードがないのは謎。
ALGOL-58と同時期のFORTRAN-IIでも 値を返すユーザー定義関数が言語仕様に追加されているのだけど、 どちらが先なのかあるいはその両方に先行する何かがあるのかは不明。
なんだけど…
Function definition - Rosetta Code
In FORTRAN I (1957), inline function could be defined at the beginning of the program. Let’s note than to specify a floating point real the name of the statement function begins with an X (no type declaration) and to specify this is a function the name ends with a F.
XMULTF(X,Y)=X*Y
And for interger multiplication:
MULTF(I,J)=I*J
In FORTRAN IV, FORTRAN 66 or later, define a function:
FUNCTION MULTIPLY(X,Y) REAL MULTIPLY, X, Y MULTIPLY = X * Y END
…あれ?
参考までに The_History_of_ALGOL.pdf のp.23(17)にこんなコードがあった。
ちょっと読みづらいけど、
関数(procedure
だけど)の戻り値を
同じ名前の変数に代入(Simps := I/3
)
することで設定している
procedure Simps(F(),a,b,delta,V);
comment a, b are the min and max, resp. of the points def. interval of integ. F() is the function to
integrated.
delta is the permissible difference between two successive Simpson sums. V is greater than
the maximum absolute value of F on a, b;
begin
Simps: Ibar := V*(b-a)
n := 1
h := (b-a)/2
J := h * (F(a)+F(b))
J1: S := 0
for k := 1 (1) n
S := S + F(a+(2*k-1)*h)
I := J+4*h*S
if (delta < abs(I-Ibar))
begin Ibar := I
J := (I+J)/4
n := 2*n; h:=h/2
go to J1 end
Simps := I/3
return
integer (k,n)
end Simps
なぜこういうやり方をしたのかは想像できなくもないけど、 それを補強する材料がない(少ない)のでまたいずれの機会にでも。
- The First Computers: History and Architectures (History of Computing Series) | Rojas, Raul, Hashagen, Ulf | Computer Design
- Comp.compilers: The History of the ALGOL Effort
People who are interested can download the thesis as a pdf file at http://www.heerdebeer.org/ALGOL/The_History_of_ALGOL.pdf (1.1 megabytes) or read the summary at http://www.heerdebeer.org/ALGOL/ .
Hugoメモ
0.101.0
0.101.0がリリースされてからしばらく間が空いているけど
- released this 31 May 2022 Release v0.100.0 · gohugoio/hugo
- released this 01 Jun 2022 Release v0.100.1 · gohugoio/hugo
- released this 08 Jun 2022 Release v0.100.2 · gohugoio/hugo
- released this 16 Jun 2022 Release v0.101.0 · gohugoio/hugo
コミットそのものはあるようだ。 Comparing v0.101.0…master · gohugoio/hugo
GA4
ところで夏休み中にGA4対応するかということで改めて調べてみたのだけど、 ここで使っているテーマ(ananke)のテンプレート ananke/layouts/partials/analytics.html を見ると
{{ if not .Site.IsServer }}
{{ with .Site.GoogleAnalytics }}
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id={{ . }}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ . }}');
</script>
{{ end }}
{{ end }}
こんな感じ(ちょっといじってるけど)。
一方で、Google Analiticsのサイトの移行ガイドによると こんなコードを挿入しろとある。
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>
config.tomlで指定しているIDだけ変えればそれでよさそうな気もするが…
実際に作成されたHTMLにどんなコードがあるかというとこう。
<script type="application/javascript">
var doNotTrack = false;
if (!doNotTrack) {
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXXXX-X', 'auto');
ga('send', 'pageview');
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-2210725-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-XXXXXXX-X');
</script>
最後のscriptブロック以外はどこで入ってきたんだろうか。
doNotTrack
云々の部分はHugoの実行ファイルに埋め込まれているものっぽい。
- respectDoNot track should be enabled by default · Issue #7403 · gohugoio/hugo
- hugo/google_analytics.html at 755d1ffe7a22d8ad83485240ff78cf25d501602f · gohugoio/hugo