ときどきの雑記帖 倒行逆施編

最新ページへのリンク
目次ページへのリンク

一つ前へ 2016年3月(上旬)
一つ後へ 2016年3月(下旬)

ホームへ

2016年03月20日

■_

ENIX移植プログラマー戦記 ~TOKYO NAMPA STREETからドラクエ2まで~
ENIX移植プログラマー戦記 ~TOKYO NAMPA STREETからドラクエ2まで~ を読んでるんだけどすげー読みづらい。 「~しない」の「ない」まで漢字にしちゃうとか、 自分で「ここは伏線ですあとででてきます」みたいな書き方とか。 後者はまあそういう「おふざけ」ととれなくはないけど 笑いを取ろうとやってるなら痛々しいし、 本気で「伏線」をそう言うものだと思ってるのなら以下略。 いずれにしてもきちんとした編集さんか、最低でもそれなりの第三者に見てもらうべきだったんじゃないかなあ。

■_

2016年03月19日

■_

今月号のソフトウェアデザイン、 特集「今すぐ実践できる良いプログラムの書き方」で対象のプログラミング言語が C Java C# Ruby JavaScript てのはどうなんだろう…… ソフトウェアデザイン 2016年 04 月号 [雑誌]
ソフトウェアデザイン 2016年 04 月号 [雑誌]

エルミタージュ秋葉原 – レトロが台所に襲来!あっと驚くニキシー管のキッチンタイマー登場 あ、これってもしや… 昨年12月に開催された「コミックマーケット89」で少量頒布され、今月よりホームページにて再版が開始されているものだ。 やはり。

Gradual Typing の訳語ってこれに固まってきてんでしょうか。 漸進的型付け (Gradual Typing) について語る会 - connpass

■_

2016年03月18日

■_

さて4月からの番組で観ておきたいものは… 年間番組 | 放送大学 - テレビ・ラジオで学ぶ通信制大学

アド・アストラ 9巻。

■_

2016年03月17日

■_

long long
むかーーーしのGNU ダイジェスト(か Think GNU)で、gcc がこれをサポートするときの ちょっとした話が載ってたような記憶があるんだけどさてどこだ。

代入を表す記号としての = について

■_

■_

なぞのわんらいなあ

>ruby -rbigdecimal -e "puts BigDecimal('1').div(BigDecimal('9801'), 200).to_s('F').scan(/../)"
0.
00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
99
00
01

へー。

2016年03月16日

■_

本屋で平積みにされてたグラハム・ハンコックの新刊見てかなりびっくりした。 まだ(作家として)生きてたのか… Amazon.co.jp: 神々の魔術 (上) 失われた古代文明の叡智: グラハム・ハンコック, 大地 舜: 本 Amazon.co.jp: 神々の魔術 (下) 失われた古代文明の叡智: グラハム・ハンコック, 大地 舜: 本 神々の指紋は(少なくとも一つ)「大穴」あるのに気づいて 興ざめしちゃったんだよね。

■_

■_

完結編。

  for (go = jumps; go; go = release_label(go))
    {
      for (lbl = labels; lbl; lbl = lbl->next)
	if (strcmp(lbl->name, go->name) == 0)
	  break;
      if (lbl)
	{
	  program->v[go->v_index].x.jump_index = lbl->v_index;
	}
      else
	{
	  if (*go->name)
	    panic(_("can't find label for jump to `%s'"), go->name);
	  program->v[go->v_index].x.jump_index = program->v_length;
	}
    }
  jumps = NULL;

外側の for ループでは分岐命令(b とか t とか)にぶら下がっているラベルを 一つ一つ取り出して、 内側の for ループで : を使って定義されたラベルと突き合わせて ジャンプ先の解決をバックパッチしている。 のだけど、b や t のあとにラベルがない、つまりスクリプトの最後へ飛ぶ場合は for のあとの else 部分を実行するのが期待されているのに、 「空のラベルが登録されている」ために then part が実行されてしまう。ということはつまり……

ちなみに FreeBSD の sed では空のラベル定義ができないようになってました。

2016年03月15日

■_

■_

■_

で。

/* Read a program (or a subprogram within `{' `}' pairs) in and store
   the compiled form in `*vector'.  Return a pointer to the new vector.  */
static struct vector *compile_program P_((struct vector *));
static struct vector *
compile_program(vector)
  struct vector *vector;
{
  struct sed_cmd *cur_cmd;
  struct buffer *b;
  int ch;

  for (;;)
    {
      struct addr a;

      while ((ch=inchar()) == ';' || ISSPACE(ch))
	;
      if (ch == EOF)
	break;

      cur_cmd = next_cmd_entry(&vector);

      cur_cmd->cmd = ch;
      switch (ch)
	{

	case ':':
	  if (cur_cmd->a1)
	    bad_prog(_(NO_COLON_ADDR));
	  labels = setup_label(labels, vector->v_length, read_label(), NULL);
	  break;
	
	case 'T':
	case 'b':
	case 't':
	  jumps = setup_label(jumps, vector->v_length, read_label(), NULL);
	  break;

	}

      /* this is buried down here so that "continue" statements will miss it */
      ++vector->v_length;
    }
  return vector;
}


説明に不要なところは削りまくってるので元のソースコードがこんな 格好ではないのですがそれはとにかく、 : や b、t コマンドが登場したときはそれに続く文字列をラベルとして処理するわけで

/* Store a label (or label reference) created by a `:', `b', or `t'
   command so that the jump to/from the label can be backpatched after
   compilation is complete, or a reference created by a `{' to be
   backpatched when the corresponding `}' is found.  */
static struct sed_label *setup_label
  P_((struct sed_label *, countT, char *, const struct error_info *));
static struct sed_label *
setup_label(list, idx, name, err_info)
  struct sed_label *list;
  countT idx;
  char *name;
  const struct error_info *err_info;
{
  struct sed_label *ret = OB_MALLOC(&obs, 1, struct sed_label);
  ret->v_index = idx;
  ret->name = name;
  if (err_info)
    MEMCPY(&ret->err_info, err_info, sizeof (ret->err_info));
  ret->next = list;
  return ret;
}

setup_label はコメントの通りで、 ラベルの読み込みはこっちの read_label の方 (setup_label の呼び出しのところで呼んでます)。

/* read in a label for a `:', `b', or `t' command */
static char *read_label P_((void));
static char *
read_label()
{
  struct buffer *b;
  int ch;
  char *ret;

  b = init_buffer();
  ch = in_nonblank();

  while (ch != EOF && ch != '\n'
	 && !ISBLANK(ch) && ch != ';' && ch != CLOSE_BRACE && ch != '#')
    ch = add_then_next (b, ch);

  savchar(ch);
  add1_buffer(b, '\0');
  ret = ck_strdup(get_buffer(b));
  free_buffer(b);
  return ret;
}

行末なり、ファイル末尾なり、空白あるいはコメント開始記号のようなものが 見つかるまでをラベルを構成するものとして取り出すと。 そしてさっきの setup_label でリストに登録しておいて

使うときにこのリストからラベルを見つけ出すのですが

/* Make any checks which require the whole program to have been read.
   In particular: this backpatches the jump targets.
   Any cleanup which can be done after these checks is done here also.  */
void
check_final_program(program)
  struct vector *program;
{
  struct sed_label *go;
  struct sed_label *lbl;


  for (go = jumps; go; go = release_label(go))
    {
      for (lbl = labels; lbl; lbl = lbl->next)
	if (strcmp(lbl->name, go->name) == 0)
	  break;
      if (lbl)
	{
	  program->v[go->v_index].x.jump_index = lbl->v_index;
	}
      else
	{
	  if (*go->name)
	    panic(_("can't find label for jump to `%s'"), go->name);
	  program->v[go->v_index].x.jump_index = program->v_length;
	}
    }
  jumps = NULL;


}

おや?

つづく?

2016年03月14日

■_

3/15 → ガイウス・ユリウス・カエサル - Wikipedia まあ暦が違うんで(同じ日だとするのは)意味ない気もするけど (この辺は日本史上のあれこれなんかも同じ)。

■_

■_

今回も sed のはなし。 GNU sedの変な挙動 - jarp, 名前を省略したラベルを設定するとなぜかそこに飛ぶ。 ということなので調べてみた。

ちなみに bやtでLABELを省略すると次にサイクルに飛ぶのはman sedやinfo sedにも書いてあるので、 GNU sedの仕様であることは間違いない。 これ、GNU sed に限った話ではなかったりします。 ってまあ「GNU sedの仕様であること」はその通りですが。

sed

sed

[2addr]t [label] 
    Test. Branch to the : command bearing the label if any substitutions have been made since
    the most recent reading of an input line or execution of a t. If label is not specified,
    branch to the end of the script.
[2addr]b [label]
    Branch to the : command bearing the label. If label is not specified, branch to the end of
    the script. The implementation supports labels recognised as unique up to at least 8 characters;
    the actual length (greater than or equal to 8) that is supported by the implementation is
    unspecified. It is unspecified whether exceeding a label length causes an error or a silent
    truncation. 

[2addr]b [label]
    Branch to the : command bearing the label. If label is not specified, branch to the end of the
    script. The implementation supports labels recognised as unique up to at least 8 characters;
    the actual length (greater than or equal to 8) that is supported by the implementation is
    unspecified. It is unspecified whether exceeding a label length causes an error or a silent
    truncation.

[2addr]t [label]
    Test. Branch to the : command bearing the label if any substitutions have been made since the
    most recent reading of an input line or execution of a t. If label is not specified, branch to
    the end of the script.

[0addr]:label
    This command does nothing; it bears a label for the b and t commands to branch to.

[0addr]:label
    This command does nothing; it bears a label for the b and t commands to branch to. 

これを踏まえた上でソースを追いかけると…

■_

つづく。

2016年03月13日

■_

AlphaGo の強さを見て連想したのは 「一兆クレジット艦隊」 なぜなのか気になったそこの君は 「EURISKO」で検索だ :)

とあるSNSからのメールがspam判定され続けているので、 「なんでこのメールがspam判定されたのか」 ってのを読んでみた。 Be careful with this message. Many people marked similar messages as spam. っておいw

■_

jot のソースコードから。

	while (mask)	/* 4 bit mask has 1's where last 4 args were given */
		switch (mask) {	/* fill in the 0's by default or computation */
		case HAVE_STEP:
		case HAVE_ENDER:
		case HAVE_ENDER | HAVE_STEP:
		case HAVE_BEGIN:
		case HAVE_BEGIN | HAVE_STEP:
			reps = REPS_DEF;
			mask |= HAVE_REPS;
			break;
		case HAVE_BEGIN | HAVE_ENDER:
			s = ender > begin ? 1 : -1;
			mask |= HAVE_STEP;
			break;
		case HAVE_BEGIN | HAVE_ENDER | HAVE_STEP:
			if (randomize)
				reps = REPS_DEF;
			else if (s == 0.0)
				reps = 0;
			else
				reps = (ender - begin + s) / s;
			if (reps <= 0)
				errx(1, "impossible stepsize");
			mask = 0;
			break;
		case HAVE_REPS:
		case HAVE_REPS | HAVE_STEP:
			begin = BEGIN_DEF;
			mask |= HAVE_BEGIN;
			break;
		case HAVE_REPS | HAVE_ENDER:
			s = STEP_DEF;
			mask = HAVE_REPS | HAVE_ENDER | HAVE_STEP;
			break;
		case HAVE_REPS | HAVE_ENDER | HAVE_STEP:
			if (randomize)
				begin = BEGIN_DEF;
			else if (reps == 0)
				errx(1, "must specify begin if reps == 0");
			begin = ender - reps * s + s;
			mask = 0;
			break;
		case HAVE_REPS | HAVE_BEGIN:
			s = STEP_DEF;
			mask = HAVE_REPS | HAVE_BEGIN | HAVE_STEP;
			break;
		case HAVE_REPS | HAVE_BEGIN | HAVE_STEP:
			if (randomize)
				ender = ENDER_DEF;
			else
				ender = begin + reps * s - s;
			mask = 0;
			break;
		case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER:
			if (reps == 0)
				errx(1, "infinite sequences cannot be bounded");
			else if (reps == 1)
				s = 0.0;
			else
				s = (ender - begin) / (reps - 1);
			mask = 0;
			break;
		case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER | HAVE_STEP:
			/* if reps given and implied, */
			if (!randomize && s != 0.0) {
				long t = (ender - begin + s) / s;
				if (t <= 0)
					errx(1, "impossible stepsize");
				if (t < reps)		/* take lesser */
					reps = t;
			}
			mask = 0;
			break;
		default:
			errx(1, "bad mask");
		}

なんというか面白いことやってんな。と。

2016年03月12日

■_

双子の帝國 1 (BUNCH COMICS)
双子の帝國 1 (BUNCH COMICS) 買ってみた。

誰でもできるロビイング入門 社会を変える技術 (光文社新書)
誰でもできるロビイング入門 社会を変える技術 (光文社新書) 買ってみたそのに。

まとめてそのさん

■_

■_

21 hot programming trends -- and 21 going cold | InfoWorld

2016年03月11日

■_

とある駅の券売機スペース。 かつては10台以上券売機が置かれていたのが 今は7台になっていて、さらにそのうちの3台が PASMO(SUICA)のチャージ専用機。 何のかんの言ってかわってんだねえ。

■_

■_

sedの話のつづき。 OS X のあれこれが BSD 由来ということで、 FreeBSD の sed を眺めてみる。

/*-
 * Copyright (c) 2013 Johann 'Myrkraverk' Oskarsson.
 * Copyright (c) 1992 Diomidis Spinellis.
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Diomidis Spinellis of Imperial College, University of London.
 *
(略)
 */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1992, 1993\n\
	The Regents of the University of California.  All rights reserved.\n";
#endif

#ifndef lint
static const char sccsid[] = "@(#)main.c	8.2 (Berkeley) 1/3/94";
#endif

これね。

で、そのオプション解析部分。

int
main(int argc, char *argv[])
{
	int c, fflag;
	char *temp_arg;

	(void) setlocale(LC_ALL, "");

	fflag = 0;
	inplace = NULL;

	while ((c = getopt(argc, argv, "EI:ae:f:i:lnr")) != -1) ←☆☆
		switch (c) {
		case 'r':		/* Gnu sed compat */
		case 'E':
			rflags = REG_EXTENDED;
			break;
		case 'I':
			inplace = optarg;
			ispan = 1;	/* span across input files */
			break;
		case 'a':
			aflag = 1;
			break;
		case 'e':
			eflag = 1;
			if ((temp_arg = malloc(strlen(optarg) + 2)) == NULL)
				err(1, "malloc");
			strcpy(temp_arg, optarg);
			strcat(temp_arg, "\n");
			add_compunit(CU_STRING, temp_arg);
			break;
		case 'f':
			fflag = 1;
			add_compunit(CU_FILE, optarg);
			break;
		case 'i':
			inplace = optarg;  ←☆☆☆
			ispan = 0;	/* don't span across input files */
			break;
		case 'l':
			if(setlinebuf(stdout) != 0)
				warnx("setlinebuf() failed");
			break;
		case 'n':
			nflag = 1;
			break;
		default:
		case '?':
			usage();
		}
	argc -= optind;
	argv += optind;

getopt に渡しているオプション文字列は "EI:ae:f:i:lnr" なので、-i はオプションに対する引数をとり、それは省略することはできない。 実際 case 'i': のところでも GNU のとは違って問答無用で inplace = optarg; としている。

再度、GNU sed の同様の部分を見ると

int
main(argc, argv)
  int argc;
  char **argv;
{
#ifdef REG_PERL
#define SHORTOPTS "bsnrRuEe:f:l:i::V:"
#else
#define SHORTOPTS "bsnruEe:f:l:i::V:"   ←☆☆
#endif

  static struct option longopts[] = {
    {"binary",          0, NULL, 'b'},
    {"regexp-extended", 0, NULL, 'r'},
#ifdef REG_PERL
    {"regexp-perl",     0, NULL, 'R'},
#endif
    {"expression",      1, NULL, 'e'},
    {"file",            1, NULL, 'f'},
    {"in-place",        2, NULL, 'i'},  ←☆☆☆
    {"line-length",     1, NULL, 'l'},
    {"quiet",           0, NULL, 'n'},
    {"posix",           0, NULL, 'p'},
    {"silent",          0, NULL, 'n'},
    {"separate",        0, NULL, 's'},
    {"unbuffered",      0, NULL, 'u'},
    {"version",         0, NULL, 'v'},
    {"help",            0, NULL, 'h'},
#ifdef ENABLE_FOLLOW_SYMLINKS
    {"follow-symlinks", 0, NULL, 'F'},
#endif
    {NULL, 0, NULL, 0}
  };
(略)
  while ((opt = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != EOF)
    {
      switch (opt)
	{

SHORTOPTS の実体に含まれる 'i' には ':' が二つ続いているので オプションに対する引数は「省略可能」。 longopts の "in-place" の行にある 2 も同じ指示をロングオプションに行うもの。

	case 'i':
	  separate_files = true;
	  if (optarg == NULL)
	    /* use no backups */
	    in_place_extension = ck_strdup ("*");

	  else if (strchr(optarg, '*') != NULL)
	    in_place_extension = ck_strdup(optarg);

	  else
	    {
	      in_place_extension = MALLOC (strlen(optarg) + 2, char);
	      in_place_extension[0] = '*';
	      strcpy (in_place_extension + 1, optarg);
	    }

	  break;

optarg == NULL ってのが オプションに引数が渡されたかどうかの判定。

■_

前回のおまけのおまけ

$ cat >argchk.sh
echo $1
echo $2
echo $3

$ bash argchk.sh aaa '' ccc
aaa

ccc

$ bash argchk.sh aaa'' ccc
aaa
ccc


$ bash argchk.sh aaa''ccc ddd
aaaccc
ddd


$ bash argchk.sh aaa' 'ccc ddd
aaa ccc
ddd

まあこうなってるわけですよ。


一つ前へ 2016年3月(上旬)
一つ後へ 2016年3月(下旬)

ホームへ


リンクはご自由にどうぞ

メールの宛先はこちらkbk AT kt DOT rim DOT or DOT jp