ときどきの雑記帖 RE* (新南口)
お茶がうまい
頂き物のお茶をいただくなど。
そう言えば去年の今頃だったか紅茶の産地が大変なことに。 とか聞いた覚えがあるけどその後どうなったんだろう。
画材屋行きて―
って特に買いたいものがあるわけではないけど。
メモ
Conditional Expressions with Omitted Middle-Operands
GNU C/C++ (GCCによる拡張) では、三項演算子の第二項を省略することができる[4]。GCC 2.95.3より使用可能[5] (March 2001)。
とあるんだけど、2.95.3 よりもずっと前から使えていたと思うがなあ
と書いたけど、Index of /gnu/gcc で確認できるもっとも古いもの(1.4.2。1992年リリース)のドキュメントを確認したところ 以下の記述を発見。
texinfo フォーマットそのままで。
@node Conditionals, Zero-Length, Lvalues, Extensions
@section Conditional Expressions with Omitted Middle-OperandsThe middle operand in a conditional expression may be omitted. Then if the first operand is nonzero, its value is the value of the conditional expression.
Therefore, the expression
@example
x ? : y
@end example@noindent
has the value of @code{x} if that is nonzero; otherwise, the value of @code{y}.This example is perfectly equivalent to
@example
x ? x : y
@end example@noindent
In this simple case, the ability to omit the middle operand is not especially useful. When it becomes useful is when the first operand does, or may (if it is a macro argument), contain a side effect. Then repeating the operand in the middle would perform the side effect twice. Omitting the middle operand uses the value already computed without the undesirable effects of recomputing it.
ということで、少なくともこの時点でもう使えてたわけですね。
本当に最初に入ったバージョンがいくつなのかまでは(とりあえずは)調べない。
glob(そのn+1)
今回も本題(ってなんですか)は進みません。
makearg(args)
REG STRING args;
{
args->argnxt=gchain;
gchain=args;
}
これ、一見よくあるlinked listの処理のコードに見えるのだけど、 args の型であるところの STRING がどういったものなのか確認するとですね
v7unix/mode.h at ed636a47207476db76d53b7869447889dee3bbad · v7unix/v7unix
TYPE char CHAR;
TYPE char BOOL;
TYPE int UFD;
TYPE int INT;
TYPE float REAL;
TYPE char *ADDRESS;
TYPE long int L_INT;
TYPE int VOID;
TYPE unsigned POS;
TYPE char *STRING;
char へのポインター。何故にそこからメンバー参照を…という話なんですが、 これはもう「当時はそういう書き方が許されていたし使われていた」 としか言いようがないですね。よく知らんけど。
argnxt はこんな定義(上記の部分のちょっと先)。
/* dummy for access only */
struct argnod {
ARGPTR argnxt;
CHAR argval[1];
};
ANSI(ISO)以前のいわゆるK&R Cだと構造体のメンバー名は「プログラム全体で一意でなければならない」 ってのがあって、さらにそれを活用してか ある構造体に対してまったく関係ないメンバー名を使えるということもできたりして それはこの sh でも各所で使われているし、 さらに遡って pre K&R では整数からでもこの種のメンバー参照ができてしまった (v6のカーネルのコードでも使われている)というのは知っていたけど v7でもそういうことをやっていたとは。
もうちょっと先を見るとこんなのもあって二度びっくり。
/* the following nonsense is required
* because casts turn an Lvalue
* into an Rvalue so two cheats
* are necessary, one for each context.
*/
union { int _cheat;};
#define Lcheat(a) ((a)._cheat)
#define Rcheat(a) ((int)(a))
これらのマクロはたとえばこんな感じに使われている (ここでのLcheatはコメントアウトされているけど)。
STRING *scan(argn)
INT argn;
{
REG ARGPTR argp = Rcheat(gchain)&~ARGMK;
REG STRING *comargn, *comargm;
comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS;
WHILE argp
DO *--comargn = argp->argval;
IF argp = argp->argnxt
THEN trim(*comargn);
FI
IF argp==0 ORF Rcheat(argp)&ARGMK
THEN gsort(comargn,comargm);
comargm = comargn;
FI
/* Lcheat(argp) &= ~ARGMK; */
argp = Rcheat(argp)&~ARGMK;
OD
return(comargn);
}
「古いC」について興味のある向きは以下に挙げるリンク先などを参照してくだされ。
struct または union のメンバーの名前空間
メンバー選択演算子を使用する struct、union、および算術型は、他の struct または union のメンバーを操作できる。
すべての一意な struct または union は、独自の一意な名前空間を持たなければならない。
すなわち、左辺は構造体へのポインターでなくてもよいのはもちろん、ポインターである必要すらない。 整数型はともかく文字型でもよいのである。
リンク
上記最後の引用部の元サイトにはほかにも関連した面白いページがあるので ついでにその辺のリンクも貼っておく。
そういやv6 のカーネルのコード云々と言えばこういう本も出てましたね。 今でも楽に買えるんだろうか?
それはそれとして、カーネルやコンパイラーはともかく、 ユーティリティの類の(それも大昔の)ソースコードを読もうという人は あまり(ほとんど?)いねえだろうなあ(笑)
余話
Cに入門したての頃、「構造体のメンバー名はプログラム全体で一意でなければならない」 という仕様に苦しんだことがある。
一応「ANSI対応」(「準拠」だったかも)のCコンパイラーだったはずなんだけど、 規格としてまだきっちり決まった時期ものでなかったとか色々な理由で 対応が中途半端だったのね。で、構造体のメンバー名の扱いもその一つ。
他には関数のプロトタイプで引数の名前を書くとエラーになるとか。 つまり
int func(int, int);
はコンパイルされるけど
int func(int x, int y);
こっちだとエラーになる。
とある「最新」のソースコードをもらって、手元でコンパイルしようとしたら 見事にこの「仕様」に引っかかって泣きながら手作業で修正したという。
番外
ひょっとして、ワイルドカード展開は(UNIXでは)コマンドを呼び出すシェルがやっているのってあまり知られてなかったりする?
【初心者向け】これだけでもデータ処理が随分捗る(と思っている)シェルコマンドたち - Qiita
grep
検索コマンド。基本形は grep <検索文字列> <ファイル名>となり、「ファイルの中身に検索文字列が含まれているかを確認し、含まれる行を返す」。 ファイル名の指定はワイルドカード(*)が使えるので、複数ファイルの中身を横断的に調べることが可能。
そして、最近本にまとまったらしいここではどうなのかと見てみると
【 grep 】コマンド――特定の文字を含む行を抽出する:Linux基本コマンドTips(9) - @IT
grepコマンドの書式
grep [オプション] 検索パターン ファイル
コマンド | grep [オプション] 検索パターン
あー。
正しくは。というか実際はこう。
書式
grep [OPTIONS] PATTERN [FILE…]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE…]
検索対象のファイルは複数個指定できる。 逆に一個も与えなくてもよくて、その場合は村の掟に従って標準入力が対象になる。
autoconf
書こうと思いつつ放置が続いている話題がいくつかあるのだけど、これもその一つ。 今年の2月分の更新リストに autoconf があったのだけど (February GNU Spotlight with Mike Gerwitz: 23 new releases)、
artanis-0.5
autoconf-archive-2021.02.19
binutils-2.36.1
freeipmi-1.6.7
freeipmi-1.6.8
glibc-2.33
gnuhealth-3.8.0
gwl-0.3.0
help2man-1.48.1
inetutils-2.0
intlfonts-1.4.1
libgcrypt-1.9.2
libredwg-0.12.1
libredwg-0.12.2
linux-libre-5.11
mailutils-3.12
nano-5.6
nettle-3.7.1
octave-6.2.0
parallel-20210222
tar-1.34
unifont-13.0.06
xorriso-1.5.4.pl02
とアーカイブの名前が見慣れない書式だったのでちょっと調べてみると、 まあなんか色々あったらしい。
というところからあれやこれや話題を広げて…と思っているのだけどなかなか進んでいない次第。
明治5年のカレンダー
【ゆるぼ】1852 年 12 月の日本のカレンダー表示 (グレゴリオ暦導入直前) ができるサイト https://t.co/nl5rsBoqbB
— yoh2 (@yoh2_sdj) May 22, 2021
「1852年12月」は1872年12月の間違いかな?
明治 5 年 12 月
— yoh2 (@yoh2_sdj) May 22, 2021
曜日も入れたけどこの頃はあまり使われてないんだっけ? pic.twitter.com/RFKHwcyA6T