ときどきの雑記帖 RE* (新南口)
PERSPECTIVE
「も」
「~するも~」といった言い回しが なんか引っかかる(文法的にどうとかいう話ではなく) んだよなあ。
で、ふと検索すると同じように感じる人はいるらしい(笑)
- 逆接助詞「も」のにわかな流行 - jun-jun1965の日記
- 逆接で、もを使うの流行っているんですか?私はもを使うなんて学校で習いませんでし… - Yahoo!知恵袋
- ○○するも・・の「も」の使い方 -いまさらひとには聞きづらいけれど、ず- 日本語 | 教えて!goo
- 「○○するも~だった」という言い方がありますがこれは正しい日本語でしょうか?… - Yahoo!知恵袋
3つの徳
課題を解決できる”環境”を作る - Magnolia Tech
かつての名作『ウルティマⅣ』がアバターが8つの徳を体現するゲームだったわけですが、 プログラマが3つの徳を体現するゲームを作ればいいんじゃないかって思った。誰か作って!
TRONWARE
TRONWARE VOL.194 (TRON & IoT 技術情報マガジン) TRONWARE (TRON & IoT 技術情報マガジン) | 坂村健
もう少しで200号。
extern
超どうでもいいけどmallocとかreallocとかstrncpyとかの略し方キモいなぁって思いながら使ってる。でも当時は1文字でも短い方が正義だったんだろうなーやっぱり
— Romly@ステロイド治療 (@Romly) April 10, 2022
昔のリンカ、シンボル名の長さに制限あった気がするな。
— MURAOKA Taro (@kaoriya) April 10, 2022
8文字くらいじゃなかったっけ? と思ったので、UNIX V7のリンカー(ld)のソースで確かめた。
/* Layout of a.out file :
*
* header of 8 words magic number 405, 407, 410, 411
* text size )
* data size ) in bytes but even
* bss size )
* symbol table size
* entry point
* {unused}
* flag set if no relocation
*
*
* header: 0
* text: 16
* data: 16+textsize
* relocation: 16+textsize+datasize
* symbol table: 16+2*(textsize+datasize) or 16+textsize+datasize
*
*/
これね。
ファイル先頭付近にある構造体の定義を見ると
/* table of contents stuff */
#define TABSZ 700
struct tab
{ char cname[8];
long cloc;
} tab[TABSZ];
/* symbol management */
struct symbol {
char sname[8];
char stype;
char spare;
int svalue;
};
やはりそれっぽいものが。
関数名の前につく_
の扱いが不明だけど
(昔はつかなかったとか聞いた記憶がかすかに)、
まあそれを含めると名前の長さは7文字がmaxと。
規格(どれ?)的には最低6文字とかあったような気もするけど やる気ゲージが低空飛行しているので調べない😄
実は
struct {
char aname[14];
long atime;
char auid, agid;
int amode;
long asize;
} archdr;
というのもあるのだけどこれは外部シンボルとは無関係。
charの配列がsname[8]
とかcname[8]
なら
(有効な)シンボルの長さは(終端のNUL文字を除いた)7文字になるんじゃないの?
という意見があるかもしれませんが、
そこはそれこういう「からくり」があったりするわけで。
struct symbol **lookup()
{
int i;
int clash;
register struct symbol **hp;
register char *cp, *cp1;
i = 0;
for (cp = cursym.sname; cp < &cursym.sname[8];)
i = (i<<1) + *cp++;
for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) {
cp1 = (*hp)->sname;
clash=FALSE;
for (cp = cursym.sname; cp < &cursym.sname[8];)
if (*cp++ != *cp1++) {
clash=TRUE;
break;
}
if (clash) {
if (++hp >= &hshtab[NSYM+2])
hp = hshtab;
} else
break;
}
return(hp);
}
cp8c(from, to)
char *from, *to;
{
register char *f, *t, *te;
f = from;
t = to;
te = t+8;
while ((*t++ = *f++) && t<te);
while (t<te)
*t++ = 0;
}
このcp8cって関数、strncpyで置き換えられる?
glob bash 3
前回 glob bash 2 yyparse() の呼び出し部分まで行ったのでその続きから。
構文解析のスタートはinputunit
からで
%start inputunit
%left '&' ';' '\n' yacc_EOF
%left AND_AND OR_OR
%right '|' BAR_AND
%%
inputunit: simple_list simple_list_terminator
{
/* Case of regular command. Discard the error
safety net,and return the command just parsed. */
global_command = $1;
eof_encountered = 0;
/* discard_parser_constructs (0); */
if (parser_state & PST_CMDSUBST)
parser_state |= PST_EOFTOKEN;
YYACCEPT;
}
| '\n'
{
/* Case of regular command, but not a very
interesting one. Return a NULL command. */
global_command = (COMMAND *)NULL;
if (parser_state & PST_CMDSUBST)
parser_state |= PST_EOFTOKEN;
YYACCEPT;
}
| error '\n'
{
/* Error during parsing. Return NULL command. */
global_command = (COMMAND *)NULL;
eof_encountered = 0;
/* discard_parser_constructs (1); */
if (interactive && parse_and_execute_level == 0)
{
YYACCEPT;
}
else
{
YYABORT;
}
}
| error yacc_EOF
{
/* EOF after an error. Do ignoreeof or not. Really
only interesting in non-interactive shells */
global_command = (COMMAND *)NULL;
if (last_command_exit_value == 0)
last_command_exit_value = EX_BADUSAGE; /* force error return */
if (interactive && parse_and_execute_level == 0)
{
handle_eof_input_unit ();
YYACCEPT;
}
else
{
YYABORT;
}
}
| yacc_EOF
{
/* Case of EOF seen by itself. Do ignoreeof or
not. */
global_command = (COMMAND *)NULL;
handle_eof_input_unit ();
YYACCEPT;
}
;
ここから simple_list → simple_list1 → pipeline_command → pipeline → command → simple_command → simple_command_element のように辿っていって
/* A simple_list is a list that contains no significant newlines
and no leading or trailing newlines. Newlines are allowed
only following operators, where they are not significant.
This is what an inputunit consists of. */
simple_list: simple_list1
{
$$ = $1;
if (need_here_doc)
gather_here_documents ();
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
{
global_command = $1;
eof_encountered = 0;
rewind_input_string ();
YYACCEPT;
}
}
| simple_list1 '&'
{
if ($1->type == cm_connection)
$$ = connect_async_list ($1, (COMMAND *)NULL, '&');
else
$$ = command_connect ($1, (COMMAND *)NULL, '&');
if (need_here_doc)
gather_here_documents ();
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
{
global_command = $1;
eof_encountered = 0;
rewind_input_string ();
YYACCEPT;
}
}
| simple_list1 ';'
{
$$ = $1;
if (need_here_doc)
gather_here_documents ();
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
{
global_command = $1;
eof_encountered = 0;
rewind_input_string ();
YYACCEPT;
}
}
;
simple_list1: simple_list1 AND_AND newline_list simple_list1
{ $$ = command_connect ($1, $4, AND_AND); }
| simple_list1 OR_OR newline_list simple_list1
{ $$ = command_connect ($1, $4, OR_OR); }
| simple_list1 '&' simple_list1
{
if ($1->type == cm_connection)
$$ = connect_async_list ($1, $3, '&');
else
$$ = command_connect ($1, $3, '&');
}
| simple_list1 ';' simple_list1
{ $$ = command_connect ($1, $3, ';'); }
| pipeline_command
{ $$ = $1; }
;
pipeline_command: pipeline
{ $$ = $1; }
| BANG pipeline_command
{
if ($2)
$2->flags ^= CMD_INVERT_RETURN; /* toggle */
$$ = $2;
}
| timespec pipeline_command
{
if ($2)
$2->flags |= $1;
$$ = $2;
}
| timespec list_terminator
{
ELEMENT x;
/* Boy, this is unclean. `time' by itself can
time a null command. We cheat and push a
newline back if the list_terminator was a newline
to avoid the double-newline problem (one to
terminate this, one to terminate the command) */
x.word = 0;
x.redirect = 0;
$$ = make_simple_command (x, (COMMAND *)NULL);
$$->flags |= $1;
/* XXX - let's cheat and push a newline back */
if ($2 == '\n')
token_to_read = '\n';
else if ($2 == ';')
token_to_read = ';';
parser_state &= ~PST_REDIRLIST; /* make_simple_command sets this */
}
| BANG list_terminator
{
ELEMENT x;
/* This is just as unclean. Posix says that `!'
by itself should be equivalent to `false'.
We cheat and push a
newline back if the list_terminator was a newline
to avoid the double-newline problem (one to
terminate this, one to terminate the command) */
x.word = 0;
x.redirect = 0;
$$ = make_simple_command (x, (COMMAND *)NULL);
$$->flags |= CMD_INVERT_RETURN;
/* XXX - let's cheat and push a newline back */
if ($2 == '\n')
token_to_read = '\n';
if ($2 == ';')
token_to_read = ';';
parser_state &= ~PST_REDIRLIST; /* make_simple_command sets this */
}
;
pipeline: pipeline '|' newline_list pipeline
{ $$ = command_connect ($1, $4, '|'); }
| pipeline BAR_AND newline_list pipeline
{
/* Make cmd1 |& cmd2 equivalent to cmd1 2>&1 | cmd2 */
COMMAND *tc;
REDIRECTEE rd, sd;
REDIRECT *r;
tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
sd.dest = 2;
rd.dest = 1;
r = make_redirection (sd, r_duplicating_output, rd, 0);
if (tc->redirects)
{
register REDIRECT *t;
for (t = tc->redirects; t->next; t = t->next)
;
t->next = r;
}
else
tc->redirects = r;
$$ = command_connect ($1, $4, '|');
}
| command
{ $$ = $1; }
;
command: simple_command
{ $$ = clean_simple_command ($1); }
| shell_command
{ $$ = $1; }
| shell_command redirection_list
{
COMMAND *tc;
tc = $1;
if (tc && tc->redirects)
{
register REDIRECT *t;
for (t = tc->redirects; t->next; t = t->next)
;
t->next = $2;
}
else if (tc)
tc->redirects = $2;
$$ = $1;
}
| function_def
{ $$ = $1; }
| coproc
{ $$ = $1; }
;
simple_command: simple_command_element
{ $$ = make_simple_command ($1, (COMMAND *)NULL); }
| simple_command simple_command_element
{ $$ = make_simple_command ($2, $1); }
;
simple_command_element: WORD
{ $$.word = $1; $$.redirect = 0; }
| ASSIGNMENT_WORD
{ $$.word = $1; $$.redirect = 0; }
| redirection
{ $$.redirect = $1; $$.word = 0; }
;
とここまできてようやく終端記号のWORD
が出てきたので字句解析のyylex
へ
というところで続く。
help
Unixコマンドラインのヘルプ表示は -h, --help, -help, help, -?, --? がある。"-h"と"--help"は由緒正しいPOSIXだが、"-help"は一貫性がなく、"help"は面倒くさい。"-?"にしたヤツは一体何考えてんだ (DOS文化の名残りだと思われる)。https://t.co/xN7vwijSin
— 新山祐介 (Yusuke Shinyama) (@mootastic) April 12, 2022
POSIX には--help
のような表記はなかったんじゃあ?
と思ったが元記事がそう書いていたのか
(そしてツッコミがあったらしく追記があった)。
-h / –help
Ah, the POSIX short/long help options. These are classics. Any competent, POSIX-compliant argument parser will handle them just fine. There are command argument parsers in many, many languages that are (or claim to be) compliant. A myriad of tools use these options, so there’s a good chance your users are familiar with using them to ask for help. In my humble opinion, these are the best options to support because of how pervasive support is for them. In other words, many users have been trained with plentiful tools over considerable time, and have built these into their muscle memory. There’s a reason why emergency phone numbers don’t change arbitrarily every time some operator wants to “disrupt” the scene, thinking they know better. When it comes to asking for help, you probably want your users to get what they need quickly so they can use your tool.
[Edit 2021-04-12] Ok, I was wrong about long options being a POSIX thing, I guess they’re a GNU thing.
-h –Help -help Help –? –? | Hacker News をみるといくつか興味深い発言があった。
Ah, the POSIX short/long help options
The long arguments are not in POSIX. They were invented by RMS having seen them in TOPS-20. (The short options come from Multics). Everything uses –version, except
java -version
.
mawk is the worst, which, given the article’s claim about POSIX, is ironic, because mawk is POSIX-compliant.
But “-help” is just “-h -e -l -p” …
Which is also a gnuism
Learn to read manuals, not blogs or Q&A sites.
- POSIX.1-2017
- GNU Manuals Online
- Linux man pages online
- Ubuntu Manpage Repository
- Reading UNIX Manual Pages | Apple Developer Documentation
- Windows Commands https://docs.microsoft.com/en-us/windows-server/administrati…
A list of new(ish) command line tools
最近普及しつつある新しいUnixコマンド:
— 新山祐介 (Yusuke Shinyama) (@mootastic) April 13, 2022
- ripgrep, ag, ack (grep)
- exa, lsd (ls)
- mosh (ssh)
- bat (cat)
- fd (find)
- sd (sed)
加えてコンテナ関連、ファイル共有など、従来のUnixにはなかった新たなコマンド群も一覧されている。https://t.co/YflDV2b20U
A list of new(ish) command line tools を見るといくつか知っているものもあったけど知らないものも多かった。
その中からsedに対応(対抗?)するsdというコマンドをちょっと調べてみる。
sd
chmln/sd: Intuitive find & replace CLI (sed alternative)
Comparison to sed
While sed does a whole lot more, sd focuses on doing just one thing and doing it well.
Some cherry-picked examples, where sd shines:
Simpler syntax for replacing all occurrences: sd: sd before after sed: sed s/before/after/g Replace newlines with commas: sd: sd '\n' ',' sed: sed ':a;N;$!ba;s/\n/,/g' Extracting stuff out of strings containing slashes: sd: echo "sample with /path/" | sd '.*(/.*/)' '$1' sed: use different delimiters every time depending on expression so that the command is not completely unreadable echo "sample with /path/" | sed -E 's/.*(\\/.*\\/)/\1/g' echo "sample with /path/" | sed -E 's|.*(/.*/)|\1|g' In place modification of files: sd: sd before after file.txt sed: you need to remember to use -e or else some platforms will consider the next argument to be a backup suffix sed -i -e 's/before/after/g' file.txt
なるほど。 行うことを(単純な)置換のみにするということで 入力の表記をわかりやすいものにしたと。