ときどきの雑記帖″

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

一つ前へ 2014年9月(中旬)
一つ後へ 2014年10月(上旬)

ホームへ

2014年09月30日

■_

日没の時刻が早くなってきて、会社帰りに無灯火の自転車に遭遇する頻度が上昇中。

■_

■_ Perl の問題点とか

Perl's Problems - Perl Hacks

Perl's Problems - Perl Hacks

Perl’s Problems

28 September, 2014Programmingperl, problems, usage	

It’s been over six weeks since I wrote my blog post on Perl usage. I really didn’t mean to leave it so long
to write the follow-up. But real life intervened and I haven’t had time for much blogging. That’s still the
case (I should be writing a talk right now) but I thought it was worth jotting down some quick notes about
what I think is causing Perl’s decline.

Reputation
(略)

Complexity

A lot of Perl’s reputation as executable line noise is completely unwarranted. The people who were writing
those 1990s balls of mud were under such pressure to deliver that they would have almost certainly delivered
something just as unmaintainable whatever language they were using. But some of that reputation is fair. I’ve
been teaching Perl for almost fifteen years and I know that there are some parts of Perl that people find
confusing. Here are some examples:

で、挙げられた項目が

Sigils
Context
Data Structures

この三つ(それぞれの詳細(特に三つめ)は原文でよろしく)。 んー sigils 好きなんだけどなあ。

■_

これ。 生物成長曲線予測の事例 気になるページがあったのだけど

生物成長曲線予測の事例 from yoshi_flt

このフレーズで検索すると springer の本が出てきた ○| ̄|_

2014年09月29日

■_

イカサマータイム期間終わって今日から元の時間帯に。 とはいえ微妙に電車が混むんだよなあ(座れるか座れないか五分五分くらい)。

■_

2014年09月28日

■_

2015年のカレンダーが売られる時期に。

ということでこれを手配。 デザインフィル ミドリ 2015年版フラットダイアリーライト 黒 2014年10月始まり A4 27365006
デザインフィル ミドリ 2015年版フラットダイアリーライト 黒 2014年10月始まり A4 27365006 デザインフィル ミドリ 2015年版フラットダイアリーライト 黒 2014年10月始まり A5 27362006
デザインフィル ミドリ 2015年版フラットダイアリーライト 黒 2014年10月始まり A5 27362006

■_

■_

珠玉のプログラミングの訳ってどうだったっけか。 とはいえ、あれ原著の版も上がっているのではなかったっけ。

Programming Pearls (ACM Press)
Programming Pearls (ACM Press) More Programming Pearls: Confessions of a Coder (ACM Press)
More Programming Pearls: Confessions of a Coder (ACM Press) Programming Pearls (ACM Press)
Programming Pearls (ACM Press)

2014年09月27日

■_

■_

■_

InfoQ だし訳されるだろうけども。 ShellShocked - Behind the Bug

ShellShocked - Behind the Bug
(略)

The problem occurs because a feature (not a bug?) in the Bash shell allows functions to be defined in environment
variables. Functions allow commonly called code to be defined and then re-used in later places, and are available
in all shell script languages. Functions in Bash (and most other shells) can be defined as follows:

  function hello {
   echo "Hello"
  }
  hello # call the function

However, Bash also has a means to define a function using environment variables, which is unique to Bash. An
environment variable whose value starts with the characters (){ is treated as an implicitly imported function
definition, which takes only takes effect on shell start-up:

  $ export HELLO="() { echo 'Hello'; }"
  $ HELLO
  -bash: HELLO: command not found
  $ bash
  $ HELLO
  Hello

Because it only takes effect at shell start-up, most of the examples demonstrating the vulnerability have been
one-liners of the form:

  env HELLO="() { echo 'Hello'; }" bash -c HELLO

which does the same thing as the above. (The env command says 'run the following program with this environment
variable set' in a portable way; in fact, HELLO="() { echo 'Hello'; }" bash -c HELLO works just as
well.) The one-line bash command (specified with -c) is then necessary to show the execution, which has to be
in a new shell since it is only parsed at start-up.

(略)

Note that the bug didn't affect just CGI scripts and Apache — if variables were poisoned in a similar way to
other programs that pass values through (such as ssh with variables like TERM or DISPLAY) and those processes
ran a Bash script (or implicitly executed them with system() calls) then the same vulnerability could be
exploited. Unlike HTTP the requests cannot be made anonymously — a login is required to be able to trigger it
— but with code hosting providers allowing free log-on (even to a restricted shell) GitHub provided updates for
its enterprise product and Bitbucket updated its servers to remediate against any possible incursion.

以降 7169 の方にも言及しているけど略

なるほどよくわかった(気がする)。 お祭り状態で色々検証やらなんやらやってた記事は幾つもあったけど この辺きちんと書いたのはあったのかなあ。

■_

ここで取りあげられている元記事を見てみたら John Carmack email on inlined code and functional programming : programming

Jonathan Blow's home page

>Indeed, if memory serves (it's been a while since I read about this)...
>
>The fly-by-wire flight software for the Saab Gripen (a lightweight
>fighter) went a step further.  It disallowed both subroutine calls and
>backward branches, except for the one at the bottom of the main loop.
>Control flow went forward only.  Sometimes one piece of code had to leave
>a note for a later piece telling it what to do, but this worked out well
>for testing:  all data was allocated statically, and monitoring those
>variables gave a clear picture of most everything the software was doing.
>The software did only the bare essentials, and of course, they were
>serious about thorough ground testing.
>
>No bug has ever been found in the "released for flight" versions of that
>code.
>
>                                                          Henry Spencer
>                                                       henry@spsystems.net

Henry Spencer のお名前が。

2014年09月26日

■_

しばたベーカリーいつの間に終わってたんだ

■_

■_

variable.c は先にちょっと読んでたけど ↓ のツイートを見て検索したら 問題のリテラルがまんまif の条件式のところにあって大笑い。

2014年09月25日

■_

じーかーんがーなーいー

■_

■_

bashの脆弱性(CVE-2014-6271) #ShellShock の関連リンクをまとめてみた - piyolog

あとで…書かないかもしれない。

■_

これ。やってることに文句はないんだけど コード読経会報告書

コード読経会報告書 from Masahiko Toyoshi

nameが0なのは長さを自由に設定するため。こんな使い方初めて見た!すごいぞ!トーパルズ! Linus が編み出したワザじゃないよねえ… 大昔のコンパイラーでは使えないのもあったし (X-C とかなー)

■_

あ、書評が。 Amazon.co.jp: プログラミング20言語習得法 (ブルーバックス)の 宇佐美健太さんのレビュー

2014年09月24日

■_

TODO: 日経Linux を買う

一度は行ってみたいなあ Strange Loop 2014 - Julia Evans

面白かった(が、結論は面白くないかも) Rosetta Code Analysis

■_ Toyota case

wikipedia にエントリ作られてるとは知らなかった 2009–11 Toyota vehicle recalls - Wikipedia, the free encyclopedia

Case Study of Toyota Unintended Acceleration and Software Safety from Philip Koopman

そしてこれ。 reddit でこの話題が出てたので何でまた今頃と思ったのだけど、 最近またなんか発表してたのね。 新しい情報はなさげ? A Case Study of Toyota Unintended Acceleration and Software Safety : programming

■_

2014年09月23日

■_

宇宙博2014行くの忘れたー

■_

■_

最後(たぶん)

freadseek.c

/* Skipping input from a FILE stream.
   Copyright (C) 2007-2014 Free Software Foundation, Inc.

(略)

/* Increment the in-memory pointer.  INCREMENT must be at most the buffer size
   returned by freadptr().
   This is very cheap (no system calls).  */
static void
freadptrinc (FILE *fp, size_t increment)
{
  /* Keep this code in sync with freadptr!  */
#if HAVE___FREADPTRINC              /* musl libc */
  __freadptrinc (fp, increment);
#elif defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
  fp->_IO_read_ptr += increment;
#elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin */
  fp_->_p += increment;
  fp_->_r -= increment;
#elif defined __EMX__               /* emx+gcc */
  fp->_ptr += increment;
  fp->_rcount -= increment;
#elif defined __minix               /* Minix */
  fp_->_ptr += increment;
  fp_->_count -= increment;
#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, NonStop Kernel */
  fp_->_ptr += increment;
  fp_->_cnt -= increment;
#elif defined __UCLIBC__            /* uClibc */
# ifdef __STDIO_BUFFERS
  fp->__bufpos += increment;
# else
  abort ();
# endif
#elif defined __QNX__               /* QNX */
  fp->_Next += increment;
#elif defined __MINT__              /* Atari FreeMiNT */
  fp->__bufp += increment;
#elif defined EPLAN9                /* Plan9 */
  fp->rp += increment;
#elif defined SLOW_BUT_NO_HACKS     /* users can define this */
#else
 #error "Please port gnulib freadseek.c to your platform! Look at the definition of getc, getc_unlocked on your system, then report this to bug-gnulib."
#endif
}

int
freadseek (FILE *fp, size_t offset)
{
  size_t total_buffered;
  int fd;

  if (offset == 0)
    return 0;

  /* Seek over the already read and buffered input as quickly as possible,
     without doing any system calls.  */
  total_buffered = freadahead (fp);
  /* This loop is usually executed at most twice: once for ungetc buffer (if
     present) and once for the main buffer.  */
  while (total_buffered > 0)
    {
      size_t buffered;

      if (freadptr (fp, &buffered) != NULL && buffered > 0)
        {
          size_t increment = (buffered < offset ? buffered : offset);

          freadptrinc (fp, increment);
          offset -= increment;
          if (offset == 0)
            return 0;
          total_buffered -= increment;
          if (total_buffered == 0)
            break;
        }
      /* Read one byte.  If we were reading from the ungetc buffer, this
         switches the stream back to the main buffer.  */
      if (fgetc (fp) == EOF)
        goto eof;
      offset--;
      if (offset == 0)
        return 0;
      total_buffered--;
    }

  /* Test whether the stream is seekable or not.  */
(略)
  
 eof:
  /* EOF, or error before or while reading.  */
  if (ferror (fp))
    return EOF;
  else
    /* Encountered EOF.  */
    return 0;
}

freadprt.c
/* Retrieve information about a FILE stream.
   Copyright (C) 2007-2014 Free Software Foundation, Inc.

(略)

const char *
freadptr (FILE *fp, size_t *sizep)
{
  size_t size;

  /* Keep this code in sync with freadahead!  */
#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
  if (fp->_IO_write_ptr > fp->_IO_write_base)
    return NULL;
  size = fp->_IO_read_end - fp->_IO_read_ptr;
  if (size == 0)
    return NULL;
  *sizep = size;
  return (const char *) fp->_IO_read_ptr;
#elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin */
  if ((fp_->_flags & __SWR) != 0 || fp_->_r < 0)
    return NULL;
  size = fp_->_r;
  if (size == 0)
    return NULL;
  *sizep = size;
  return (const char *) fp_->_p;
(略)
#elif defined SLOW_BUT_NO_HACKS     /* users can define this */
  /* This implementation is correct on any ANSI C platform.  It is just
     awfully slow.  */
  return NULL;
#else
 #error "Please port gnulib freadptr.c to your platform! Look at the definition of fflush, fread, getc, getc_unlocked on your system, then report this to bug-gnulib."
#endif
}

ということで、cut が gawk より遅い云々はたぶんこの辺りが原因。 gawk はたしかバッファ一杯にごそっと読み込んでからレコードを切り出して、 それからごにょごにょやってるから。 あと、出力のときにもフィールド指定の具合によっては一バイトずつ読んでは…というのをやってたような。

2014年09月22日

■_

毒吐こうかなあと考えたけど思い直して止めた

Ruby Under a Microscope: An Illustrated Guide to Ruby Internals
Ruby Under a Microscope: An Illustrated Guide to Ruby Internals で、これを貼り付けるとこの本を腐そうとしたようにとられるかな? 違うよ?

あ、先越された 「制限だらけで何も出来ない公園」に行ってみたら、商業施設の敷地内だった - akiyan.com

いけね。 A Case Study of Toyota Unintended Acceleration and Software Safety : programming これのリンク先のPDF読むの忘れてた

■_

■_ gawk vs. cut

つづき。cut.c で呼び出していた getdeim2 について

getdelim.c

/* getndelim2 - Read a line from a stream, stopping at one of 2 delimiters,
   with bounded memory allocation.
(略)

/* The maximum value that getndelim2 can return without suffering from
   overflow problems, either internally (because of pointer
   subtraction overflow) or due to the API (because of ssize_t).  */
#define GETNDELIM2_MAXIMUM (PTRDIFF_MAX < SSIZE_MAX ? PTRDIFF_MAX : SSIZE_MAX)

/* Try to add at least this many bytes when extending the buffer.
   MIN_CHUNK must be no greater than GETNDELIM2_MAXIMUM.  */
#define MIN_CHUNK 64

ssize_t
getndelim2 (char **lineptr, size_t *linesize, size_t offset, size_t nmax,
            int delim1, int delim2, FILE *stream)
{
  size_t nbytes_avail;          /* Allocated but unused bytes in *LINEPTR.  */
  char *read_pos;               /* Where we're reading into *LINEPTR. */
  ssize_t bytes_stored = -1;
  char *ptr = *lineptr;
  size_t size = *linesize;
  bool found_delimiter;

  if (!ptr)
    {
      size = nmax < MIN_CHUNK ? nmax : MIN_CHUNK;
      ptr = malloc (size);
      if (!ptr)
        return -1;
    }

  if (size < offset)
    goto done;

  nbytes_avail = size - offset;
  read_pos = ptr + offset;

  if (nbytes_avail == 0 && nmax <= size)
    goto done;

  /* Normalize delimiters, since memchr2 doesn't handle EOF.  */
  if (delim1 == EOF)
    delim1 = delim2;
  else if (delim2 == EOF)
    delim2 = delim1;

  flockfile (stream);

  found_delimiter = false;
  do
    {
      /* Here always ptr + size == read_pos + nbytes_avail.
         Also nbytes_avail > 0 || size < nmax.  */

      int c IF_LINT (= 0);
      const char *buffer;
      size_t buffer_len;

      buffer = freadptr (stream, &buffer_len);
      if (buffer)
        {
          if (delim1 != EOF)
            {
              const char *end = memchr2 (buffer, delim1, delim2, buffer_len);
              if (end)
                {
                  buffer_len = end - buffer + 1;
                  found_delimiter = true;
                }
            }
        }
      else
        {
          c = getc (stream);
          if (c == EOF)
            {
              /* Return partial line, if any.  */
              if (read_pos == ptr)
                goto unlock_done;
              else
                break;
            }
          if (c == delim1 || c == delim2)
            found_delimiter = true;
          buffer_len = 1;
        }

      /* We always want at least one byte left in the buffer, since we
         always (unless we get an error while reading the first byte)
         NUL-terminate the line buffer.  */
(略)

      if (buffer && freadseek (stream, buffer_len))
        goto unlock_done;
    }
  while (!found_delimiter);

  /* Done - NUL terminate and return the number of bytes read.
     At this point we know that nbytes_avail >= 1.  */
  *read_pos = '\0';

  bytes_stored = read_pos - (ptr + offset);

 unlock_done:
  funlockfile (stream);

 done:
  *lineptr = ptr;
  *linesize = size;
  return bytes_stored ? bytes_stored : -1;
}

freadaptr と freadseek ってのはこれまた別のファイルにある関数。 んでまあそこは飛ばしてこの関数がどういったものかはここに書かれている

getdelim2.h

/* getndelim2 - Read a line from a stream, stopping at one of 2 delimiters,
   with bounded memory allocation.

(略)
/* Read into a buffer *LINEPTR returned from malloc (or NULL),
   pointing to *LINESIZE bytes of space.  Store the input bytes
   starting at *LINEPTR + OFFSET, and null-terminate them.  Reallocate
   the buffer as necessary, but if NMAX is not GETNLINE_NO_LIMIT
   then do not allocate more than NMAX bytes; if the line is longer
   than that, read and discard the extra bytes.  Stop reading after
   the first occurrence of DELIM1 or DELIM2, whichever comes first;
   a delimiter equal to EOF stands for no delimiter.  Read the
   input bytes from STREAM.
   Return the number of bytes read and stored at *LINEPTR + OFFSET (not
   including the NUL terminator), or -1 on error or EOF.  */
extern ssize_t getndelim2 (char **lineptr, size_t *linesize, size_t offset,
                           size_t nmax, int delim1, int delim2,
                           FILE *stream);

#endif /* GETNDELIM2_H */

続く。のか?

■_ プログラミング20言語習得法

というわけでこの著者の他の本をチェックすると… Amazon.co.jp: 小林 健一郎: 本 翻訳本はともかく自著はなんと言うかその…ごにょごにょ

『プログラミング20言語習得法』 初心者のための実践独習ガイド 小林健一郎=著  | ブルーバックス前書き図書館 | 現代ビジネス [講談社] にもこの本の内容について書かれていますが

『プログラミング20言語習得法』 初心者のための実践独習ガイド 小林健一郎=著  | ブルーバックス前書き図書館 | 現代ビジネス [講談社]

★取り上げている言語:

C C++ Java Perl Visual Basic

FORTRAN BASIC Pascal Ada Objective-C C# COBOL LISP(Common Lisp, Racket) 
Haskell Scala Python Ruby VBScript Smalltalk AWK Java Script PHP

という部分があります。 目次によると最初の5個(C, C++, Java, Perl, Visual Basic)は 「プログラムの世界の潮流がわかる主要5言語」で、残りは 「さらに知っておきたい特色ある15言語」 なんだそうです。

プログラミング言語の紹介で短いサンプルプログラムが結構載っているのですが このプログラムがまた何とも言い難いものだったりします。 たとえば Perl。

  open(IN, "eng.txt");
  @x = <IN>
  close(IN);
  @y = sort(@x);
  print @y;
  $x = int(rand(3));
  if ($x == 0) {
    print "大吉です\n":
  }
  elsif ($x == 1) {
    print "普通です\n";
  }
  else {
    print "凶です\n";
  }

…えーと。

他にも Ruby の紹介のところでは(p.258)

ただし、日本語を表示したい場合、「日本語の文字コード」(251ページのコラムを参照)を
指定する必要があります。たとえば、シフトJIS方式を使っている場合、実行は、

  ruby -Ks hello.rb

で行うことができます。また、EUC-JP なら -Ks ではなく -Ke、UTF-8 なら -Ku とします。
  

なんてのがあったり。 好意的に解釈すれば、Perl にしても Ruby にしても古いバージョンを使う場合を 考慮したと言えるかもしれないけど、ちょっとなあ。

Pascal では gpc を使っていますが、 gcc とのバージョンあわせ云々とか書くくらいなら (というか gpc 今メンテされないの?) FreePascal 使えばいいと思うんですけどね。 あー、Ada (GNAT)、Objective-C (GCCのやつ) を使いたいからか。 にしたってなあ…

面倒になったのでここで終わり。

2014年09月21日

■_

rubykaigi2014のはなし。 「ホールでの飲食禁止」ってのが散々アナウンスされてたのだけど、 ひじょーに目立つ外見のお方がバッグに何本もペットボトルの飲料を持ってて、数分と開けず口にしてた (直接見てたのは初日の午前中だけだけど、三日ともそうだったっぽい)。 さすがに空の容器は持って帰ってたぽいけど、ああいうのは見かけたときに注意すべきだったんだろうか。 それとも近くにいるスタッフの人に伝える?

もうひとつ書いておくと、 休憩時間の音楽の音量がちょーーーーっと大きな気がしたんだけど (音量に関して)なにか目安みたいなものはあるんだろか。 たぶん自分が過敏になってるせいだとは思うんだけど 正直ちょっと辛かったのよ。

■_ ほんやくむずかしい

Ruby嫌いがアンダースタンディングコンピュテーションを読んで - ぐるぐる~ で、

6.1.4
何か所か原文を確認したくなったところはありましたが、とても少ないです。 意味がよく分からないな、と思った個所は
一つだけです。 P.169に、

    ブール値を将来のコードが読める決まったデータとして考えるのではなく、2つの選択肢を引数として呼び出し、1番目
    と2番目の選択肢のどちらかを選ぶコードとして、直接的に実装しましょう。

とありますが、この前半部分の意味が分かりませんでした。 ただ、ここが分からなくても後半部分だけで実際にやりたい
ことはわかるため、それほど問題とも思いませんでした。

この辺を原著からちょっと広めに。

Booleans

How can we represent Booleans using only procs? Well, Booleans exist solely to be
used in conditional statements, and in general, a conditional says “if some Boolean then
this else that”:

  >> success = true
  => true
  >> if success then 'happy' else 'sad' end
  => "happy"
  >> success = false
  => false
  >> if success then 'happy' else 'sad' end
  => "sad"

So the real job of a Boolean is to allow us to choose between two options, and we can
take advantage of this by representing a Boolean as a proc that chooses one of two
values. Instead of thinking of a Boolean as a lifeless piece of data that can be read by
some future code to decide which of two options to choose, we’ll just implement it
directly as a piece of code that, when called with two options, either chooses the first
option or chooses the second option.

Implemented as methods, then, #true and #false could be:
  def true(x, y)
    x
  end

  def false(x, y)
    y
  end

TaPL でやったわーw > represent Booleans using only procs ま、それはさておき Instead of thinking of a Boolaen ~ のとことですかね。ふむ。

元記事読み返したらコメントに原文ついてた

■_

■_

ということで GNU coreutils の cut のソース読んだよ!(駆け足で)

/* cut - remove parts of lines of files
   Copyright (C) 1997-2014 Free Software Foundation, Inc.
   Copyright (C) 1984 David M. Ihnat

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* Written by David Ihnat.  */

/* POSIX changes, bug fixes, long-named options, and cleanup
   by David MacKenzie <djm@gnu.ai.mit.edu>.

   Rewrite cut_fields and cut_bytes -- Jim Meyering.  */

一番に怪しいのは入力のところだよなあ。で、

/* Read from stream STREAM, printing to standard output any selected bytes.  */

static void
cut_bytes (FILE *stream)

こっちはスルーして

/* Read from stream STREAM, printing to standard output any selected fields.  */

static void
cut_fields (FILE *stream)
{
  int c;
  size_t field_idx = 1;
  bool found_any_selected_field = false;
  bool buffer_first_field;

  current_rp = rp;

  c = getc (stream);
  if (c == EOF)
    return;

  ungetc (c, stream);
  c = 0;

  /* To support the semantics of the -s flag, we may have to buffer
     all of the first field to determine whether it is 'delimited.'
     But that is unnecessary if all non-delimited lines must be printed
     and the first field has been selected, or if non-delimited lines
     must be suppressed and the first field has *not* been selected.
     That is because a non-delimited line has exactly one field.  */
  buffer_first_field = (suppress_non_delimited ^ !print_kth (1));

  while (1)
    {
      if (field_idx == 1 && buffer_first_field)
        {
          ssize_t len;
          size_t n_bytes;

          len = getndelim2 (&field_1_buffer, &field_1_bufsize, 0,
                            GETNLINE_NO_LIMIT, delim, '\n', stream);
          if (len < 0)
            {
              free (field_1_buffer);
              field_1_buffer = NULL;
              if (ferror (stream) || feof (stream))
                break;
              xalloc_die ();
            }

          n_bytes = len;
          assert (n_bytes != 0);

          c = 0;

          /* If the first field extends to the end of line (it is not
             delimited) and we are printing all non-delimited lines,
             print this one.  */
          if (to_uchar (field_1_buffer[n_bytes - 1]) != delim)
            {
              if (suppress_non_delimited)
                {
                  /* Empty.  */
                }
              else
                {
                  fwrite (field_1_buffer, sizeof (char), n_bytes, stdout);
                  /* Make sure the output line is newline terminated.  */
                  if (field_1_buffer[n_bytes - 1] != '\n')
                    putchar ('\n');
                  c = '\n';
                }
              continue;
            }
          if (print_kth (1))
            {
              /* Print the field, but not the trailing delimiter.  */
              fwrite (field_1_buffer, sizeof (char), n_bytes - 1, stdout);

              /* With -d$'\n' don't treat the last '\n' as a delimiter.  */
              if (delim == '\n')
                {
                  int last_c = getc (stream);
                  if (last_c != EOF)
                    {
                      ungetc (last_c, stream);
                      found_any_selected_field = true;
                    }
                }
              else
                found_any_selected_field = true;
            }
          next_item (&field_idx);
        }

      int prev_c = c;

      if (print_kth (field_idx))
        {
          if (found_any_selected_field)
            {
              fwrite (output_delimiter_string, sizeof (char),
                      output_delimiter_length, stdout);
            }
          found_any_selected_field = true;

          while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
            {
              putchar (c);
              prev_c = c;
            }
        }
      else
        {
          while ((c = getc (stream)) != delim && c != '\n' && c != EOF)
            {
              prev_c = c;
            }
        }

      /* With -d$'\n' don't treat the last '\n' as a delimiter.  */
      if (delim == '\n' && c == delim)
        {
          int last_c = getc (stream);
          if (last_c != EOF)
            ungetc (last_c, stream);
          else
            c = last_c;
        }

      if (c == delim)
        next_item (&field_idx);
      else if (c == '\n' || c == EOF)
        {
          if (found_any_selected_field
              || !(suppress_non_delimited && field_idx == 1))
            {
              if (c == '\n' || prev_c != '\n' || delim == '\n')
                putchar ('\n');
            }
          if (c == EOF)
            break;
          field_idx = 1;
          current_rp = rp;
          found_any_selected_field = false;
        }
    }
}

んー、getc 使って読んでるのが引っかかるなあ。 getndelim2 でも読み込みやってるぽいけどこれは cut.c にはない関数。 でもまあそもそもどのくらい gawk と cut で変わってくるのか 具体的な数字出して欲しかったわねえ(計測計測)…

■_

この本

プログラミング20言語習得法 (ブルーバックス)
プログラミング20言語習得法 (ブルーバックス)

出る前から気になってて(ブルーバックスだし)、 残念ながらジュンク堂RubyKaigi支店には並んでいなかったので 今日某所へ出かけたついでに買った訳なんですが…

続く。


一つ前へ 2014年9月(中旬)
一つ後へ 2014年10月(上旬)

ホームへ


リンクはご自由にどうぞ

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