mallocをdebug compileしたい

glibcをダウンロードし解凍します。 glibcのフォルダーないに入りbuildフォルダーをつくります。

cd glibc-2.21
mkdir build
cd build

glibcをインストールするフォルダーを指定してconfigureします。

../configure --prefix=/home/shingo/lib/glibc

そしてmakeです。 フラグはデバッグ用に -g3 -O0 をいれます。

make CFLAGS="-g3 -O0"

するとglibcはoptimizationなしではcompileできないとerrorがでます。

error: #error "glibc cannot be compiled without optimization" 

いろいろ調べてみると最低でも-O1でないとcompileできないようです。 しかしmallocを-O0でコンパイルできれば良いのでちょっとそこだけ変えてみましょう。 まずはこのcompileできないのerrorをコメントアウトしましょう。 バージョンによって場所が違いますがgrepして見つけましょう。 2.21の場合はbuild folder内のconfig.hにあります。

...
# error "glibc cannot be compiled without optimization"
...

そしてmallocのフォルダー内にあるMakefileを編集します。 ついでにDMALLOC_DEBUGもアクティブにしておきましょう。

malloc/Makefile

# Uncomment this for test releases.  For public releases it is too expensive.
CPPFLAGS-malloc.o += -DMALLOC_DEBUG=1
CPPFLAGS-malloc.o += -g3
CPPFLAGS-malloc.o += -O0

これでmakeするとmallocがstep実行できるlibc.aができあがります。

coffee scriptとvueを使ってelectronのappをつくりたい

ファイル構成はこんな感じです。

    my_coffee_electron
    ├── launch
    │   ├── main.js
    │   └── package.json
    ├── package.json
    ├── src
    │   ├── coffee
    │   │   └── app.coffee
    │   ├── pug
    │   │   └── index.pug
    │   └── vue
    │       ├── my_component.coffee
    │       └── my_component.vue
    └── webpack.config.js

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
	target:'electron',
  entry: './src/coffee/app.coffee',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'build')
  },
	resolve:{
		alias:{
			'vue$':'vue/dist/vue.esm.js'
		}
	},
	plugins:[
		new HtmlWebpackPlugin({
			template:'./src/pug/index.pug'
		})
	],
	module:{
		rules:[
			{
				test: /\.pug$/,
				use: ['raw-loader','pug-html-loader']
			},
			{
				test: /\.coffee$/,
				use: ['coffee-loader']
			},
			{
				test: /\.vue$/,
				use: ['vue-loader','pug-html-loader']
			}
		]
	}
};

Webpackの設定です。target はelectronになっていますが
これを入れなければwebで実行できるファイルが生成されます。
htmlにpugテンプレートを使うためにHtmlWebpackPluginで設定しています。
resolve alias のところはこれが無いとvueがワーニングを出してくるのでいれます。
entryのapp.coffeeがルートになりDomLoad時に実行されます。
これでwebpackはbuildフォルダーの中にindex.htmlとbundle.jsを生成します。

launch/package.json

{
  "name": "electron-test",
  "main": "main.js"
}
 

Webpackが生成したファイルをelectronで実行するための設定です。
main.js では

 ...
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, '../build/index.html'),
    protocol: 'file:',
    slashes: true
  }))
 ...

build/index.htmlを読み込んでwindowを作っています。
これでcoffee script と vue js を使って electron app を作れます。

github.com

electronでvue.jsのエラー

もしvue js で

You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build 

 と言われてwebpack使っていないという時は

node_modules/vue/package.json内の"main"を"dist/vue.runtime.common.js"から"dist/vue.js"にするとうまくいく。どっかでoverwrite的に出来ないのかな?

Fortran 千本ノック

1本目 Int の配列をつくって1,2,3を入れる!

 
integer,dimension(3)::arr = (/1,2,3/)
 

2本目 Int の10個の配列をつくって2から5まで1あとは0に!

 
integer,dimension(10)::arr
arr = 0
arr(2:5) = 1
 

3本目 Int の3x3の配列をつくって真ん中は1あとは0に!

 
integer,dimension(3,3)::arr
arr = 0
arr(2,2) = 1
! 0 0 0
! 0 1 0
! 0 0 0


4本目 Int の1x4の配列をつくって2x2の配列に!

 
integer,dimension(4)::arr
integer,dimension(2,2)::arr2
arr = (/1,2,3,4/)
arr2 = reshape(arr,(/2,2/))

! 1 2
! 3 4

5本目 文字を連結!

 
character(5) a
character(5) b

a = "hello"
b = "world"
 
print *,a//b ! helloworld
 

6本目 最初の2文字を交換!

 
character(5) a
character(5) b
character(5) tmp

a = "hello"
b = "world"

tmp(1:2) = a(1:2)
a(1:2)=b(1:2)
b(1:2)=tmp(1:2)
 
print *,a//b ! wolloherld
 

7本目 文字の配列!

 
character(5),dimension(2)::ch_arr

ch_arr(1) = 'abc'
ch_arr(2) = 'def'

8本目 文字を検索!

 
a = "hello"
 
print *, scan(a,'l') ! <--- 3

9本目 namelistを活用!

data

&data
a=1
b=2
/

data.f90

  integer::a
  integer::b
  integer,parameter::f=10
   
  namelist/data/a,b
  open(unit=f, file='data')
  read(unit=f, nml=data)
   
  print *, a, b ! <-- 1, 2
  close(unit=f)

10本目 subroutineを使う!

subroutine my_sub(b)
   integer b
   b = b + 1
end subroutine
 
program main
  implicit none
  integer::a
  a = 1
  call my_sub(a)
  print *, a
end program

Lapackをコンパイルしてみる

Lapackのコードを読んでみたいと思います。
まずはgithub Lapackからダウンロードします。
LapackのfortranのコードはSRCフォルダーに入っているのでそれをコンパイルしてみましょう。
SRCフォルダーをどこかにコピーします。
そのときmake.inc.exampleもコピーしてmake.incに名前を変えておきましょう。
SRCの中にMakefileがあるのでmakeしてみましょう。

cd SRC
make

すると最後にarコマンドでエラーがでました。
MakefileをみてみるとINSTALLフォルダーのオブジェクトファイルを探して失敗しているようです。

 ALLAUX = ilaenv.o ieeeck.o lsamen.o xerbla.o xerbla_array.o iparmq.o iparam2stage.o \
    ilaprec.o ilatrans.o ilauplo.o iladiag.o chla_transtype.o \
    ../INSTALL/ilaver.o ../INSTALL/lsame.o ../INSTALL/slamch.o
 
 SCLAUX = \
    sbdsdc.o \
    sbdsqr.o sdisna.o slabad.o slacpy.o sladiv.o slae2.o  slaebz.o \
    slaed0.o slaed1.o slaed2.o slaed3.o slaed4.o slaed5.o slaed6.o \
    slaed7.o slaed8.o slaed9.o slaeda.o slaev2.o slagtf.o \
    slagts.o slamrg.o slanst.o \
    slapy2.o slapy3.o slarnv.o \
    slarra.o slarrb.o slarrc.o slarrd.o slarre.o slarrf.o slarrj.o \
    slarrk.o slarrr.o slaneg.o \
    slartg.o slaruv.o slas2.o  slascl.o \
    slasd0.o slasd1.o slasd2.o slasd3.o slasd4.o slasd5.o slasd6.o \
    slasd7.o slasd8.o slasda.o slasdq.o slasdt.o \
    slaset.o slasq1.o slasq2.o slasq3.o slasq4.o slasq5.o slasq6.o \
    slasr.o  slasrt.o slassq.o slasv2.o spttrf.o sstebz.o sstedc.o \
    ssteqr.o ssterf.o slaisnan.o sisnan.o \
    slartgp.o slartgs.o \
    ../INSTALL/second_$(TIMER).o
 
 DZLAUX = \
    dbdsdc.o \
    dbdsqr.o ddisna.o dlabad.o dlacpy.o dladiv.o dlae2.o  dlaebz.o \
    dlaed0.o dlaed1.o dlaed2.o dlaed3.o dlaed4.o dlaed5.o dlaed6.o \
    dlaed7.o dlaed8.o dlaed9.o dlaeda.o dlaev2.o dlagtf.o \
    dlagts.o dlamrg.o dlanst.o \
    dlapy2.o dlapy3.o dlarnv.o \
    dlarra.o dlarrb.o dlarrc.o dlarrd.o dlarre.o dlarrf.o dlarrj.o \
    dlarrk.o dlarrr.o dlaneg.o \
    dlartg.o dlaruv.o dlas2.o  dlascl.o \
    dlasd0.o dlasd1.o dlasd2.o dlasd3.o dlasd4.o dlasd5.o dlasd6.o \
    dlasd7.o dlasd8.o dlasda.o dlasdq.o dlasdt.o \
    dlaset.o dlasq1.o dlasq2.o dlasq3.o dlasq4.o dlasq5.o dlasq6.o \
    dlasr.o  dlasrt.o dlassq.o dlasv2.o dpttrf.o dstebz.o dstedc.o \
    dsteqr.o dsterf.o dlaisnan.o disnan.o \
    dlartgp.o dlartgs.o \
    ../INSTALL/dlamch.o ../INSTALL/dsecnd_$(TIMER).o

なにかの依存関係でしょう。
消しましょう。
INSTALLのあるラインをコメントしてもう一度make。

 ALLAUX = ilaenv.o ieeeck.o lsamen.o xerbla.o xerbla_array.o iparmq.o iparam2stage.o \
    ilaprec.o ilatrans.o ilauplo.o iladiag.o chla_transtype.o \
  #  ../INSTALL/ilaver.o ../INSTALL/lsame.o ../INSTALL/slamch.o
 
 SCLAUX = \
    sbdsdc.o \
    sbdsqr.o sdisna.o slabad.o slacpy.o sladiv.o slae2.o  slaebz.o \
    slaed0.o slaed1.o slaed2.o slaed3.o slaed4.o slaed5.o slaed6.o \
    slaed7.o slaed8.o slaed9.o slaeda.o slaev2.o slagtf.o \
    slagts.o slamrg.o slanst.o \
    slapy2.o slapy3.o slarnv.o \
    slarra.o slarrb.o slarrc.o slarrd.o slarre.o slarrf.o slarrj.o \
    slarrk.o slarrr.o slaneg.o \
    slartg.o slaruv.o slas2.o  slascl.o \
    slasd0.o slasd1.o slasd2.o slasd3.o slasd4.o slasd5.o slasd6.o \
    slasd7.o slasd8.o slasda.o slasdq.o slasdt.o \
    slaset.o slasq1.o slasq2.o slasq3.o slasq4.o slasq5.o slasq6.o \
    slasr.o  slasrt.o slassq.o slasv2.o spttrf.o sstebz.o sstedc.o \
    ssteqr.o ssterf.o slaisnan.o sisnan.o \
    slartgp.o slartgs.o \
  #  ../INSTALL/second_$(TIMER).o
 
 DZLAUX = \
    dbdsdc.o \
    dbdsqr.o ddisna.o dlabad.o dlacpy.o dladiv.o dlae2.o  dlaebz.o \
    dlaed0.o dlaed1.o dlaed2.o dlaed3.o dlaed4.o dlaed5.o dlaed6.o \
    dlaed7.o dlaed8.o dlaed9.o dlaeda.o dlaev2.o dlagtf.o \
    dlagts.o dlamrg.o dlanst.o \
    dlapy2.o dlapy3.o dlarnv.o \
    dlarra.o dlarrb.o dlarrc.o dlarrd.o dlarre.o dlarrf.o dlarrj.o \
    dlarrk.o dlarrr.o dlaneg.o \
    dlartg.o dlaruv.o dlas2.o  dlascl.o \
    dlasd0.o dlasd1.o dlasd2.o dlasd3.o dlasd4.o dlasd5.o dlasd6.o \
    dlasd7.o dlasd8.o dlasda.o dlasdq.o dlasdt.o \
    dlaset.o dlasq1.o dlasq2.o dlasq3.o dlasq4.o dlasq5.o dlasq6.o \
    dlasr.o  dlasrt.o dlassq.o dlasv2.o dpttrf.o dstebz.o dstedc.o \
    dsteqr.o dsterf.o dlaisnan.o disnan.o \
    dlartgp.o dlartgs.o \
  #  ../INSTALL/dlamch.o ../INSTALL/dsecnd_$(TIMER).o

liblapack.aができあがります。
なにかこの中にある関数を呼んでみましょう。
CLACRT( N, CX, INCX, CY, INCY, C, S )を呼んでみましょう。
この関数はCXとCYの配列に入っている座標を時計回りに回転させる関数です。

program main
	INTEGER            INCX, INCY, N
	INTEGER  DEG
	COMPLEX            C, S
	COMPLEX,dimension(3)::CX = sqrt(2.0)
	COMPLEX,dimension(3)::CY = 0

	REAL,PARAMETER::PI = 3.14
	print *, CX
	print *, CY

	DEG = 45 
	INCX = 1
	INCY = 1
	N = 3 
	C = cos(DEG * (PI/180))
	S = sin(DEG * (PI/180))

	call CLACRT( N, CX, INCX, CY, INCY, C, S )
	print *, CX
	print *, CY
end program main

こんな感じで3つの(√2,0)の座標を45度回転させています。 このコードをtest.f90としてコンパイルしてみます。

	gfortran -o test test.f90 SRC/clacrt.f -llapack -L.

./にあるliblapack.aファイルをリンクしています。

(  1.00039804    ,  0.00000000    ) (  1.00039804    ,  0.00000000    ) (  1.00039804    ,  0.00000000    )
(-0.999601781    ,  0.00000000    ) (-0.999601781    ,  0.00000000    ) (-0.999601781    ,  0.00000000    )

実行してみるとCX, CY が(1,-1)になってprintされました。

今日の関数 searchit その5 (https://github.com/vim/vim)

/* With the SEARCH_END option move to the last character
 * of the match.  Don't do it for an empty match, end
 * should be same as start then. */
if ((options & SEARCH_END) && !(options & SEARCH_NOOF)
  && !(matchpos.lnum == endpos.lnum
   && matchpos.col == endpos.col))
{
 /* For a match in the first column, set the position
  * on the NUL in the previous line. */
 pos->lnum = lnum + endpos.lnum;
 pos->col = endpos.col;
 if (endpos.col == 0)
 {
  if (pos->lnum > 1)  /* just in case */
  {
   --pos->lnum;
   pos->col = (colnr_T)STRLEN(ml_get_buf(buf,
      pos->lnum, FALSE));
  }
 }
 else
 {
  --pos->col;
#ifdef FEAT_MBYTE
  if (has_mbyte
    && pos->lnum <= buf->b_ml.ml_line_count)
  {
   ptr = ml_get_buf(buf, pos->lnum, FALSE);
   pos->col -= (*mb_head_off)(ptr, ptr + pos->col);
  }
#endif
 }
}
else
{
 pos->lnum = lnum + matchpos.lnum;
 pos->col = matchpos.col;
}

search.c

matchした後でSEARCH_ENDの設定をしているところです。

if ((options & SEARCH_END) && !(options & SEARCH_NOOF)
  && !(matchpos.lnum == endpos.lnum
   && matchpos.col == endpos.col))
{

search.c

SEARCH_ENDのオプションがついていてmatchした文字が空でないかをチェックします。

pos->lnum = lnum + endpos.lnum;
pos->col = endpos.col;
if (endpos.col == 0)
{
 if (pos->lnum > 1)  /* just in case */
 {
  --pos->lnum;
  pos->col = (colnr_T)STRLEN(ml_get_buf(buf,
     pos->lnum, FALSE));
 }
}
else
{
 --pos->col;
#ifdef FEAT_MBYTE
 if (has_mbyte
   && pos->lnum <= buf->b_ml.ml_line_count)
 {
  ptr = ml_get_buf(buf, pos->lnum, FALSE);
  pos->col -= (*mb_head_off)(ptr, ptr + pos->col);
 }
#endif
}

search.c

SEARCH_ENDオプションがついているのでカーソルの位置をマッチした最後に持っていきます。
その時マッチの最後の部分が0ならば前の行の最後にカーソルを移動します。そうでなければ
マッチした最後の部分から一つ戻った位置にカーソルをおきます。

else
{
	pos->lnum = lnum + matchpos.lnum;
	pos->col = matchpos.col;
}

search.c

SEARCH_ENDオプションがない場合です。
カーソルの位置をマッチした位置に持っていきます。

#ifdef FEAT_VIRTUALEDIT
pos->coladd = 0;
#endif
found = 1;
first_match = FALSE;

/* Set variables used for 'incsearch' highlighting. */
search_match_lines = endpos.lnum - matchpos.lnum;
search_match_endcol = endpos.col;
break;
}

search.c

found, first_matchなどのフラグを調整して行ごとのループ(697行目のfor loop)から抜け出します。

line_breakcheck(); /* stop if ctrl-C typed */
if (got_int)
 break;

search.c

ここに来る場合はマッチしなかった場合です。
毎行ループするたびこの部分を通ります。
まずはctrl-cで中断されないかをチェックします。

#ifdef FEAT_SEARCH_EXTRA
 /* Cancel searching if a character was typed.  Used for
  * 'incsearch'.  Don't check too often, that would slowdown
  * searching too much. */
if ((options & SEARCH_PEEK)
  && ((lnum - pos->lnum) & 0x3f) == 0
  && char_avail())
{
 break_loop = TRUE;
 break;
}
#endif

search.c

ここではサーチしている間にまた文字入力がされていないかをチェックします。
このifの二番目の条件は
あまりに頻繁にbreakしないように間隔を空けるための条件です。
lnumはループしている行数です。それからカーソルのある行数を引いた数が
0x3f(0011 1111,10進数では63)との論理的ANDが0の時breakします。
つまり64で割り切れる数の時この条件が満たされます(0x0100 0000(64) & 0011 1111(0x3f) == 0)。

for (loop = 0; loop <= 1; ++loop)
{
 
 ...

if (loop && lnum == start_pos.lnum)
 break;     /* if second loop, stop where started */
 }
at_first_line = FALSE;

search.c

loopが0でないということは二回目のloopだということなので
その上で検索のスタート位置の行とlnumが一致しているということは
検索の結果が一周回って元に戻ってきたということです。
その時もbreakします。

/*
* Stop the search if wrapscan isn't set, "stop_lnum" is
* specified, after an interrupt, after a match and after looping
* twice.
*/
if (!p_ws || stop_lnum != 0 || got_int || called_emsg
#ifdef FEAT_SEARCH_EXTRA
   || break_loop
#endif
   || found || loop)
break;

search.c

ここに来るのは全部の行を周り終わった時です。
wrapscanでない場合、中断された時、ループを二回回った時にbreakします。

/*
 * If 'wrapscan' is set we continue at the other end of the file.
 * If 'shortmess' does not contain 's', we give a message.
 * This message is also remembered in keep_msg for when the screen
 * is redrawn. The keep_msg is cleared whenever another message is
 * written.
 */
if (dir == BACKWARD)    /* start second loop at the other end */
 lnum = buf->b_ml.ml_line_count;
 else
 lnum = 1;
if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
 give_warning((char_u *)_(dir == BACKWARD
    ? top_bot_msg : bot_top_msg), TRUE);
 }

search.c

行を全部ループし終わったのでwrapscanするために後方検索ならlnumにbufferの一番最後の行の数を入れて
前方検索ならlnumを1にして次のloopに入ります。
その際検索が最後または最初の行に戻ることをワーニングします。