ときどきの雑記帖 RE* (新南口)
The only neat things what to do
ことよろ。
2022年
退かぬ媚びぬ省みぬ(違)
2023年
その1
備
その2
最近は以下のものをタネにつらつら考えているのだけど特に結論はない。
- The End of Programming | Hacker News
- The End of Programming | January 2023 | Communications of the ACM
- Peter Norvig reviews AlphaCode’s code quality : programming
- pytudes/AlphaCode.ipynb at main · norvig/pytudes
- GitHub CEO トーマス・ドムケ氏が来日。いずれコードの80%がAIで作成されるようになると予言 - Publickey
- It’s the end of programming as we know it – again | ZDNET
その3
出てすぐに買ったのに積んだままの 塩野七生のシリーズ本が何冊もあるので (文庫版も出てしまった😓) 読み進めておきたい。
プログラマー脳
例によって新刊近刊チェックをしていて見つけた。
オランダのライデン大学で准教授を務め、長年プログラミング教育を研究している著者が、「認知科学」に基づいて、 プログラミングの際のミスを減らし、効率的なプログラミング学習法を教える。 コードを書いたり読んだりするときに「プログラマーの脳」がどのように働くかという認知プロセスを理解し、 それを最適化することで可能となる「コードを読みやすくする方法」「コードを速く書く方法」 「新しい言語を短い時間で習得する方法」などを解説する。それ以外にも、複雑なコードを解読して美しく書き直す方法、 新しく参加したチームメンバーを素早く合流させて生産的にするといった手法なども説明する。
一瞬「スマホ脳」のような本かと思ったが
の翻訳本のようだ。 これも秀和からなのかあ。
そういや秀和から出るmanningの翻訳本には以前言及した
がありますな。
Googleのテックリードを務める筆者が、プロのソフトウェアエンジニアとして、信頼性が高く、 保守しやすいコードを作成するための概念と具体的な手法を紹介している。また、 指導する立場のエンジニアがアドバイスする際のリソース(情報源)となることも考慮されている。
こっちは今月か。
M4
Michael Breen © 2008
ES2023
【JavaScript】ES2023の新機能 - Qiita を読んでいて
Hashbang Grammar
ファイルの先頭行にある#!のみコメントとして扱います。
#! hoge ←これはコメント #! fuga ←シンタックスエラー
なるほどと思いつつ、Perl(など)で使われていた shebang対応していない環境で動かすためのあれこれを思い出すなど。
そう言えば大昔のsedにはコメントというものがなかったとか、 ただし1行目が
#n
だったら-n
オプションが指定されたのと同じ動作になる。
とかいうのがあったような記憶があるんだけど、
実際どうだったんだろう?
E2BIG
[Q&A] xargsコマンドの引数分割のおかしな挙動についての質問 - Qiita
すでに解決してるけどChangeLogからE2BIGを探すとこんなのがある。
で、linuxカーネルのコードからE2BIGを探してみると結構ある。
if (i >= max)
return -E2BIG;
++i;
for (i = 0; argv[i]; ++i) {
if (i >= MAX_ARG_STRINGS)
return -E2BIG;
if (fatal_signal_pending(current))
return -ERESTARTNOHAND;
cond_resched();
}
if (rp->data_size > KRETPROBE_MAX_DATA_SIZE)
return -E2BIG;
r = -EFAULT;
if (copy_from_user(&msrs, user_msrs, sizeof(msrs)))
goto out;
r = -E2BIG;
if (msrs.nmsrs >= MAX_IO_MSRS)
goto out;
いくつかその周りを見るとこんな感じ。 ひとつひとつ確かめていく気力なんてものは当然ないので、 方針を変えてexecve(2)のマニュアルでE2BIGを返した場合の 解説を探す(先にこっちを見るべきだった)。
と、やっぱりあった。 以下マニュアルから。
引数と環境変数の合計サイズの上限 (Man page of EXECVE)
ほとんどの UNIX の実装は、新しいプログラムに渡すことができる コマンドライン引数 (argv) と環境変数 (envp) の文字列群の 合計サイズに何らかの上限を設けている。 POSIX.1 は、 ARG_MAX 定数を使ってこの上限を決める実装を認めている (ARG_MAX は <limits.h> で定義されるか、実行時に sysconf(_SC_ARG_MAX) の呼び出しで入手できるかのいずれかである)。
カーネル 2.6.23 より前の Linux では、環境変数と引数の文字列群を 格納するのに使用されるメモリーは 32 ページに制限されていた (32 ページというのはカーネル定数 MAX_ARG_PAGES で定義される)。したがって、 ページサイズが 4 kB のアーキテクチャーでは、 最大サイズは 128 kB ということになる。
On kernel 2.6.23 and later, most architectures support a size limit derived from the soft RLIMIT_STACK resource limit (see getrlimit(2)) that is in force at the time of the execve() call. (Architectures with no memory management unit are excepted: they maintain the limit that was in effect before kernel 2.6.23.) This change allows programs to have a much larger argument and/or environment list. For these architectures, the total size is limited to 1/4 of the allowed stack size. (Imposing the 1/4-limit ensures that the new program always has some stack space.) Additionally, the total size is limited to 3/4 of the value of the kernel constant _STK_LIM (8 Mibibytes). Since Linux 2.6.25, the kernel also places a floor of 32 pages on this size limit, so that, even when RLIMIT_STACK is set very low, applications are guaranteed to have at least as much argument and environment space as was provided by Linux 2.6.23 and earlier. (This guarantee was not provided in Linux 2.6.23 and 2.6.24.) Additionally, the limit per string is 32 pages (the kernel constant MAX_ARG_STRLEN), and the maximum number of strings is 0x7FFFFFFF.
肝心なところが英語のままですな。 まあ自分で訳しておいてもいんだけど、 この部分が訳されているのもある(ただし元にした文章のバージョンが違うのか いくつか違う点がある。たとえば_STK_LIM に関する記述がない)。
カーネル 2.6.23 以降では、ほとんどのアーキテクチャにおいて、 execve() が呼び出された時点で適用されているリソースのソフト上限 RLIMIT_STACK に基づいたサイズ上限が使われる (メモリ管理ユニット (MMU) を持たないアーキテクチャは上記の変更の例外であり、 これらのアーキテクチャではカーネル 2.6.23 より前と同じ上限がそのまま使用される)。 これらのアーキテクチャでは、 合計サイズは許可されたスタックサイズの 1/4 に制限されている (1/4 の上限を設けているのは、新しいプログラムが必ずある程度の スタック空間を持てることを保証するためである)。 Linux 2.6.25 以降では、カーネルはこのサイズ上限に 32 ページの下限を設けている。 これにより、 RLIMIT_STACK が非常に小さく設定された場合でも、アプリケーションが少なくとも Linux 2.6.23 以前で 提供されていたのと同じ大きさの引き数と環境変数の空間 と同じだけは確保できることが保証されている (この最低限の保証は Linux 2.6.23 と 2.6.24 では提供されていない)。 また、各文字列の上限は 32 ページ (カーネル定数 MAX_ARG_STRLEN) で、 文字列数の最大値は 0x7FFFFFFF である。
まあこの解説でほぼ答えは出ているんだけど、せっかくなので(ry
_STK_LIM
で探してみるとヒット数が格段に少ない
Search · _STK_LIM
のでこここから辿ってみる。
static int bprm_stack_limits(struct linux_binprm *bprm)
という関数で、_STK_LIM
を参照したり
上記解説にあるような計算をしている。
しかも詳細なコメント付き。
bprm_stack_limits
static int bprm_stack_limits(struct linux_binprm *bprm)
{
unsigned long limit, ptr_size;
/*
* Limit to 1/4 of the max stack size or 3/4 of _STK_LIM
* (whichever is smaller) for the argv+env strings.
* This ensures that:
* - the remaining binfmt code will not run out of stack space,
* - the program will have a reasonable amount of stack left
* to work from.
*/
limit = _STK_LIM / 4 * 3;
limit = min(limit, bprm->rlim_stack.rlim_cur / 4);
/*
* We've historically supported up to 32 pages (ARG_MAX)
* of argument strings even with small stacks
*/
limit = max_t(unsigned long, limit, ARG_MAX);
/*
* We must account for the size of all the argv and envp pointers to
* the argv and envp strings, since they will also take up space in
* the stack. They aren't stored until much later when we can't
* signal to the parent that the child has run out of stack space.
* Instead, calculate it here so it's possible to fail gracefully.
*
* In the case of argc = 0, make sure there is space for adding a
* empty string (which will bump argc to 1), to ensure confused
* userspace programs don't start processing from argv[1], thinking
* argc can never be 0, to keep them from walking envp by accident.
* See do_execveat_common().
*/
ptr_size = (max(bprm->argc, 1) + bprm->envc) * sizeof(void *);
if (limit <= ptr_size)
return -E2BIG;
limit -= ptr_size;
bprm->argmin = bprm->p - limit;
return 0;
}
E2BIGを返すフローもある。 なお、この関数を呼び出しているのは do_execveat_common という関数で
static int do_execveat_common
static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv,
struct user_arg_ptr envp,
int flags)
{
struct linux_binprm *bprm;
int retval;
if (IS_ERR(filename))
return PTR_ERR(filename);
/*
* We move the actual failure in case of RLIMIT_NPROC excess from
* set*uid() to execve() because too many poorly written programs
* don't check setuid() return code. Here we additionally recheck
* whether NPROC limit is still exceeded.
*/
if ((current->flags & PF_NPROC_EXCEEDED) &&
is_rlimit_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
retval = -EAGAIN;
goto out_ret;
}
/* We're below the limit (still or again), so we don't want to make
* further execve() calls fail. */
current->flags &= ~PF_NPROC_EXCEEDED;
bprm = alloc_bprm(fd, filename);
if (IS_ERR(bprm)) {
retval = PTR_ERR(bprm);
goto out_ret;
}
retval = count(argv, MAX_ARG_STRINGS);
if (retval == 0)
pr_warn_once("process '%s' launched '%s' with NULL argv: empty string added\n",
current->comm, bprm->filename);
if (retval < 0)
goto out_free;
bprm->argc = retval;
retval = count(envp, MAX_ARG_STRINGS);
if (retval < 0)
goto out_free;
bprm->envc = retval;
retval = bprm_stack_limits(bprm);
if (retval < 0)
goto out_free;
retval = copy_string_kernel(bprm->filename, bprm);
if (retval < 0)
goto out_free;
bprm->exec = bprm->p;
retval = copy_strings(bprm->envc, envp, bprm);
if (retval < 0)
goto out_free;
retval = copy_strings(bprm->argc, argv, bprm);
if (retval < 0)
goto out_free;
/*
* When argv is empty, add an empty string ("") as argv[0] to
* ensure confused userspace programs that start processing
* from argv[1] won't end up walking envp. See also
* bprm_stack_limits().
*/
if (bprm->argc == 0) {
retval = copy_string_kernel("", bprm);
if (retval < 0)
goto out_free;
bprm->argc = 1;
}
retval = bprm_execve(bprm, fd, filename, flags);
out_free:
free_bprm(bprm);
out_ret:
putname(filename);
return retval;
}
MAX_ARG_STRINGS
などの制限のチェックをしている。
bprm_stack_limitsを呼び出しているのはもう一か所あって、それは kernel_execve という関数。
int kernel_execve(const char *kernel_filename, const char *const *argv, const char *const *envp)
int kernel_execve(const char *kernel_filename,
const char *const *argv, const char *const *envp)
{
struct filename *filename;
struct linux_binprm *bprm;
int fd = AT_FDCWD;
int retval;
/* It is non-sense for kernel threads to call execve */
if (WARN_ON_ONCE(current->flags & PF_KTHREAD))
return -EINVAL;
filename = getname_kernel(kernel_filename);
if (IS_ERR(filename))
return PTR_ERR(filename);
bprm = alloc_bprm(fd, filename);
if (IS_ERR(bprm)) {
retval = PTR_ERR(bprm);
goto out_ret;
}
retval = count_strings_kernel(argv);
if (WARN_ON_ONCE(retval == 0))
retval = -EINVAL;
if (retval < 0)
goto out_free;
bprm->argc = retval;
retval = count_strings_kernel(envp);
if (retval < 0)
goto out_free;
bprm->envc = retval;
retval = bprm_stack_limits(bprm);
if (retval < 0)
goto out_free;
retval = copy_string_kernel(bprm->filename, bprm);
if (retval < 0)
goto out_free;
bprm->exec = bprm->p;
retval = copy_strings_kernel(bprm->envc, envp, bprm);
if (retval < 0)
goto out_free;
retval = copy_strings_kernel(bprm->argc, argv, bprm);
if (retval < 0)
goto out_free;
retval = bprm_execve(bprm, fd, filename, 0);
out_free:
free_bprm(bprm);
out_ret:
putname(filename);
return retval;
}
FORTRAN Compiler on IBM 704
久しぶりにFORTRAN IIのソースからコード紹介。
CA100
テープからソースコードを読みだしてくるサブルーチン。 ソースコードを読みだすと言ってもプログラム丸ごとは読めないので ちまちまと。
CA100 READS NEXT SOURCE PROGRAM CARD
REM CA100,4/ CALLS=DIAG. CALLER=CA000. 4F13119
REM CA100 READS NEXT SOURCE PROGRAM CARD (1 TAPE RECORD). 4F13120
CA100 LXA TERC,2 PREPARE TO COUNT 4F13121
SXD 1G,2 TAPE READING ERRORS. 4F13122
RTT TURN OFF TAPE CHECK INDICATOR. 4F13123
NOP PROCEED TO NEXT INSTRUCTION. 4F13124
CA101 RDS 130 SELECT SOURCE TAPE FOR READING. 4F13125
LXA L(12),2 INITIALIZE INDEX B FOR 12 CYCLES OF4F13126
REM COPY LOOP. 4F13127
CA102 CPY FT+12,2 COPY INTO FT REGION 4F13128
TRA CA103 NEXT SOURCE PROGRAM CARD. 4F13129
TRA CA120 END OF FILE, GO FINISH LAST STATEM.4F13130
CA130 LXD 1G,2 TEST TAPE ERROR COUNTER 4F13131
TIX CA131,2,1 BY TRYING TO REDUCE BY 1. 4F13132
TSX DIAG,4 * FAILED 5 TIMES IN READING TAPE 2. 4F13133
CA131 SXD 1G,2 SAVE REDUCED VALUE IN COUNTER. 4F13134
BST 130 BACKSPACE FORMULA TAPE, 4F13135
TRA CA101 AND GO BACK TO READ AGAIN. 4F13136
CA103 TIX CA102,2,1 TEST EXIT FROM LOOP. 4F13137
IOD DELAY UNTIL TAPE DISCONNECTS. 4F13138
RTT CHECK READING OF TAPE. 4F13139
TXI CA130,0 IF INCORRECT, GO CHECK ERROR C0UNT.4F13140
LXA L(12),2 PREPARE TO SCAN 12 WORDS OF CARD. 4F13141
CA112 CLA BLANKS TEST 4F13142
SUB FT+12,2 FOR 4F13143
TNZ CA113 BLANK 4F13144
TIX CA112,2,1 CARD. 4F13145
TRA CA100 IF BLANK, GO TO READ NEXT CARD. 4F13146
CA113 CAL FT IF NOT BLANK, 4F13147
ARS 30 EXAMINE FIRST 4F13148
SUB L(C) CHARACTER TO 4F13149
TZE CA100 TEST FOR COMMENT CARD. 4F13150
TRA 1,4 * EXIT IF NEITHER BLANK NOR COMMENT. 4F13151
CA120 STZ FT INDICATE THAT FINAL 4F13152
SXD ENDWRD,0 STATEMENT HAS BEEN READ IN. 4F13153
TRA 1,4 * EXIT TO MAIN ROUTINE TO FINISH. 4F13154
REM END OF PROGRAM CA100. 4F13155
読みだし先はというとこう。
FT BSS 12 SOURCE PROGRAM INPUT BUFFER. 4F10285
1ワードに6文字入るので、12ワードでは12×6で72文字。 よく見るあの数字が出てきました。 カード一枚には80文字入るけど、 カードからテープに転記する際に最後の8文字は捨てている模様 (まあ必要ないし)。
ところでこのサブルーチンのコードを読んでいて しばらく悩んだのが
LXA L(12),2 INITIALIZE INDEX B FOR 12 CYCLES OF4F13126
で、12をインデックスレジスターの2番にロードして
CA102 CPY FT+12,2 COPY INTO FT REGION 4F13128
で読み込み&書き込み。そして
TIX CA131,2,1 BY TRYING TO REDUCE BY 1. 4F13132
でレジスターの値をデクリメント。
…バッファの後ろから書き込んでる?
しかしよく考えたら、 704のインデックスレジスターは その内容を加算するのではなくて 減算する(2の補数を加算する)ので、
最初に
CA102 CPY FT+12,2 COPY INTO FT REGION 4F13128
に来たときはFT+12-12
の位置に書き込むことになり、
以降
FT+12-11
FT+12-10
FT+12-9
...
となるので、FT番地からアドレスが増える方向に書き込みが進む。と。
あと72文字(12ワード)読み込んでそれで終わりかというとそうではなくて、 読み込んだ内容がオールブランクだったりコメント行だったりした場合には 次の読み込みを行う(つまり振出しに戻る)。
CA112 CLA BLANKS TEST 4F13142
SUB FT+12,2 FOR 4F13143
TNZ CA113 BLANK 4F13144
TIX CA112,2,1 CARD. 4F13145
TRA CA100 IF BLANK, GO TO READ NEXT CARD. 4F13146
CA113 CAL FT IF NOT BLANK, 4F13147
ARS 30 EXAMINE FIRST 4F13148
SUB L(C) CHARACTER TO 4F13149
TZE CA100 TEST FOR COMMENT CARD. 4F13150
このCA100
に飛ぶところね。
ところでこの時期のIBMのマシンにはI/Oバッファーはなかったんですかね? まあシステム全体のメモリ容量を考えると そんなものをつけている余裕はなかったのかもしれない。
このサブルーチンで使用しているワークエリアは以下の通り
- TERC
- 1G
- L(12)
- FT (FT+12)
- BLANKS
- L(C)
- ENDWRD
それぞれは以下のように定義されている。
TERC SYN L(5) TAPE ERROR COUNTER. 4F15958
L(5) BCD 1000005 5 4F10326
1G BSS 1 COMMON WORKING STORAGE. 4F10265
L(12) SYN MINUS 4F15933
MINUS OCT 14 - 4F10331
FT BSS 12 SOURCE PROGRAM INPUT BUFFER. 4F10285
BLANKS BCD 1 606060606060 4F10401
L(C) BCD 100000C C 4F10332
ENDWRD TIX SR6DC4,0,-1 (DECR= END OF PROBLEM INDICATOR) 4F11015
SYNという疑似命令は要するに「別名」をつけること。 なぜこういうことをするかというと、 「定数」を使うにも1ワード用意しなければならないのだけど 内容が同じ定数に対して別のワードを用意する余裕はないが 名前は異なるものにして目的(属性)を明確にしておきたい といったところか。
Hugo メモ
GA4
とりあえず使っているテーマ(ananke)の layouts/partial/analytics.html を書き換えて対処(コード直埋め)。
「きちんとした」対処ではないのだけど、 まずは動かすのが先決なので(とか書いてると以下略)。
変更点
0.108.0リリース時の記事 0.109.0リリース時の記事 の補足的な何か
0.108
Release v0.108.0 · gohugoio/hugo
With Hugo v0.108.0 you can render standalone Markdown images without a surrounding paragraph. Both the HTML- and CommonMark-specification defines image as an inline element. For Markdown, this has meant that if you put an image on its own (not inlined in another paragraph), it would be wrapped in
tags, even if you provide your own Render Hook Template.
イメージ(画像)に関する話のようなのでスルー。 たぶんこれで嬉しくなるような画像の使い方はしないと思うし。
0.109
Release v0.109.0 · gohugoio/hugo
Pass variables to SCSS/SASS
Hugo has had great SCSS/SASS support, but passing variables (e.g. theme colours from config) down to the transpiler has been much harder than it should.
In Hugo v0.109.0 we added a new vars option and you can finally just do:
{{ $vars := dict "color1" "blue" "color2" "green" "font_size" "24px" }} {{ $opts := (dict "transpiler" "dartsass" "outputStyle" "compressed" "vars" $vars ) }} {{ $r := resources.Get "scss/main.scss" | toCSS $opts }}
ふむ。これもあまり自分(の使い方)には関係なさげ。
Hugo Module Workspaces
Breadcrumbs
The path to /public now available in PostCSS
同上?
例の踏切
スラムダンク好きが集まる江ノ電鎌倉高校前踏切。
— ZIPP齋藤@10/8 Life on Wheels展示会 (@Swash_Zipp) December 31, 2022
線路内に入るヤツらを撃退するためかに設置されたトラップが笑えるんだな。#ぢぷさんぽ pic.twitter.com/H4m5X3chVK
次に鎌倉方面いくときにでも見てみるかな😄
2023
Happy Cube Year Everyone! 🥳
— Tamás Görbe (@TamasGorbe) December 31, 2022
2️0️2️3️
Just two more years and we have a beautiful sum of cubes.#HappyNewYear2023 pic.twitter.com/ObzUXhWKSh
最後の-
を+
にすると
2年後にも使えるのでは?
と思ったら同様の指摘のリプライがついていた。