<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
.readOnly {background:[[ColorPalette::TertiaryPale]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity=60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser

Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])

<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]

----
Also see [[AdvancedOptions]]
<<importTiddlers>>
!Introduction
Akka is the platform for the next generation event-driven, scalable and fault-tolerant architectures on the JVM

http://akka.io/

Scala 中的 actor 實作品之一(關於 Actor 請參考 [[Parallel computing]] 一節),是 Typesafe 這家公司的作品(Scala 多數作者所屬的公司)
支援 remote actor,可以放在網路上!

!Software Transactional Memory
因為很多事件要用多個 actor 共同完成,所以這機制用來管制,當某事完成到一定程度時才把 state commit 出去。([[supervisor|Parallel computing]] 的實作品?)

!Remote actor
初始化方式分成兩種:
*由 client 啟動
*由 server 啟動
因為 remote actor,所以 ActorRef 是 serializable,甚至可以存成檔案。
為了降低耦合,ActorRef 對應的 Actor 可能壞掉或是不在了,所以//設計某個 actor 時要考慮其它 actor 沒有回應的情況//。
!System Wide
[[Memory leak 粗淺觀測]]
[[重新掛載檔案系統]]

!Building System
[[build images and burning with fastboot]]
[[RIL daemon 的檔案產生位置]]
[[make targets|Android make targets]]
[[building system FAQ]]

!Dalvik
[[Coltrolling the Embedded VM]]

!Debug
[[八個 debug 技巧]]

!Revert Engineering
[[How to decompile *.dex to *.java]]
[[Smali: An assembler/disassembler for Android's dex format|http://code.google.com/p/smali/]]

!Misc
C++ reference system: [[RefBase]]
*{{{make sdk}}} - build the tools that are part of an SDK (adb, fastboot, etc.)
*{{{make snod}}} - build the system image from the current software binaries
*{{{make services}}}
*{{{make runtime}}}
*{{{make droid}}} - make droid is the normal build.
*{{{make all}}} - make everything, whether it is included in the product definition or not
*{{{make clean}}} - remove all built files (prepare for a new build). Same as rm -rf out/<configuration>/
*{{{make modules}}} - shows a list of submodules that can be built (List of all LOCAL_MODULE definitions)
*{{{make <local_module>}}} - make a specific module (note that this is not the same as directory name. It is the LOCAL_MODULE definition in the Android.mk file)
*{{{make clean-<local_module>}}} - clean a specific module
!Step-by-Step
#[[Install basic develop packages in Ubuntu]]
#[[Install JDK 1.5|Install JDK 1.5 after Ubuntu 9.10]].
#{{multiline{Install nessisary libraries
{{{
sudo apt-get install git-core gnupg flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev zip curl libncurses5-dev zlib1g-dev
}}}
}}}
#{{multiline{If you want to use Valgrind, you may install it
{{{
sudo apt-get install valgrind
}}}
}}}

!References
*{{multiline{Android Official Document
http://source.android.com/download#TOC-Ubuntu-Linux-32-bit-x86-
}}}
!Environment Setup
*[[Install basic develop packages in Ubuntu]]

!Frameworks
!!Android
*[[Build Android on Ubuntu 9.10]]

!Spec
*[[C/C++ 運算符優先層級表]]
*[[C/C++ function pointer]]

!Ticky
*[[Example: a wrapper to printf]]
!Definition
C:
{{{
int (*pt2Function)(float, char, char) = NULL;
}}}
C++ only:
{{{
// a member which is a function variable
int (TMyClass::*pt2Member)(float, char, char) = NULL;
// a constant member
int (TMyClass::*pt2ConstMember)(float, char, char) const = NULL;
}}}

!Usage
C:
{{{
// short form
pt2Function = someFunction;
// correct assignment
pt2Function = &someFunction;
}}}
C++:
{{{
TMyClass *myClassInstance = new TMyClass();
// assignment
myClassInstance->pt2Member = &TMyClass::pt2Member;
// function call. This may also available using "this"
myClassInstance->*pt2Member();

// static members are just like C type functions
int (*pt2Function)() = &TMyClass::doSomething;
pt2Function();
}}}
|Table 1. C++ 運算符優先層級表|c
| Priority | Operator | Description | Associativity |h
| Priority | Operator | Description | Associativity |f
| 0 | {{{::}}} |Scope resolution (C++ only)| Left-to-right |
| 1 | {{{++ --}}} |Postfix increment and decrement| Left-to-right |
|~| {{{()}}} |Function call|~|
|~| {{{[]}}} |Array subscripting|~|
|~| {{{. }}} |Element selection by reference|~|
|~| {{{->}}} |Element selection through pointer|~|
|~| {{{typeid()}}} |Run-time type information (C++ only)|~|
|~| {{{const_cast}}} |Type cast (C++ only)|~|
|~| {{{dynamic_cast}}} |Type cast (C++ only)|~|
|~| {{{reinterpret_cast}}} |Type cast (C++ only)|~|
|~| {{{static_cast}}} |Type cast (C++ only)|~|
| 2 | {{{++ --}}} |Prefix increment and decrement| Right-to-left |
|~| {{{+ -}}} |Unary plus and minus|~|
|~| {{{! ~}}} |Logical NOT and bitwise NOT|~|
|~| {{{(type)}}} |Type cast|~|
|~| {{{*}}} |Indirection (dereference)|~|
|~| {{{&}}} |Address-of (reference)|~|
|~| {{{sizeof}}} |Size-of|~|
|~| {{{new new[]}}} |Dynamic memory allocation (C++ only)|~|
|~| {{{delete delete[]}}} |Dynamic memory deallocation (C++ only)|~|
| 3 | {{{.* ->*}}} |Pointer to member (C++ only)| Left-to-right |
| 4 | {{{* / %}}} |Multiplication, division, and modulus| Left-to-right |
| 5 | {{{+ -}}} |Addition and subtraction| Left-to-right |
| 6 | {{{<< >>}}} |Bitwise left shift and right shift| Left-to-right |
| 7 | {{{<}}} |Relational “less than”| Left-to-right |
|~| {{{<=}}} |"less than or equal to"|~|
|~| {{{>}}} |“greater than”|~|
|~| {{{>=}}} |“greater than or equal to”|~|
| 8 | {{{== !=}}} |Relational “equal to” and “not equal to”| Left-to-right |
| 9 | {{{& ^ |}}} |Bitwise AND, XOR, OR| Left-to-right |
| 10 | {{{&& ||}}} |Logical AND and OR| Left-to-right |
| 11 | {{{c ? t : f}}} |Ternary conditional| Right-to-Left |
| 12 | {{{=}}} |Direct assignment (provided by default for C++ classes)| Right-to-Left<br>(Except throw) |
|~| {{{+= -=}}} |Assignment by sum and difference|~|
|~| {{{*= /= %=}}} |Assignment by product, quotient, and remainder|~|
|~| {{{<<= >>=}}} |Assignment by bitwise left shift and right shift|~|
|~| {{{&= ^= |=}}} |Assignment by bitwise AND, XOR, and OR|~|
|~| {{{throw}}} |Throw operator (exceptions throwing, C++ only)|~|
| 13 | {{{,}}} |Comma| Right-to-Left |
!Misc
Ubuntu comic viewer: Comix

!Jenkins
結合版本控制、 issue tracking、wiki
專案管理工具:Trac!!!
持續結成工具:Jenkins
{{{
$java -jar jenkins.war
}}}
可以整合各種工具來用,包括 Android Emulator plugin
可以配合 Trac!有 Android client!

!Now.in 講 Python
Flask: 一個非常輕量級的 web framework(有些地方有點髒)
Pyramid: 中量級的 web framework,官方文件非常詳細
TurboGears2: 重量級 web framework,非常難學,因為 dependency 以內部實作,無法使用 debugger
Celery: 分佈式 task queue
Twisted: 事件驅動的網路應用程式框架,已實作常見 protocol (HTTP, SMTP, DNS...)
!!伺服器管理框架
uWSGI: 高彈性、高效能伺服器框架
Supervisor: tool for running daemons,本身是一支 daemon,可以把想做的 daemon 做成其 subprocess 掛在其下,避掉寫 daemon 的困難,而且非 OS dependent
Fabric: tool for deploying,可以直接用 mercurial 部署應用
!!Q&A
Q: 為何選 TurboGear 而不選 Django?
A: Django 全部東西都自己寫,TurboGear 宣稱是選最好的來組合(但結果是使用體驗很差,而且還是一樣缺乏彈性…)

!OpenJDK7
@@G1 collector@@
@@Tiered compilation@@
Async I/O
{{{java.lang.reflection.*}}} is verrrryyyy slllllooooowwwwww,所以 OpenJDK7 加入了 InvokeDynamic

!BoF & lighting talk
@@Scrapy@@ framework

!Ubuntu BoF
AWN (Avant Window Navigator): 類似 OSX 的 dock
[[動漫花園磁力連結取得器|https://chrome.google.com/webstore/detail/hldkdmfilndibnmilinlfldlcjhogkbk?hl=zh-TW]]
chntpw: 用 Ubuntu 重設 Windows 密碼
!Misc
[[DZSlides|https://github.com/paulrouget/dzslides]]: 看起來很棒的 HTML5 slide
[[speak.js|http://syntensity.com/static/espeak.html]]: 用 JS 做 slide

!Android auto-test
Android screencast: 把 Android 螢幕內容投到 PC 上
CTS 根據 CDD (compatibility device document) 規定之行為寫成
*CTS
**Unit test: single class
**Functional test
**Reference application test
**Robustness test (TBD)
**Performance test (TBD)
Aster: 設計給非程式設計師使用的自動化測試工具(與 Sikuli 定位給設計師不同
Cramdroid: 連阿嫲都會做測試,自動化測試佈署

!AndroidVG
hardware-dependent 的向量繪圖加速 lib
相應於 Android 內建的 OpenVG

!Actor modle and Akka framework
Concurrency: 兩件事情可以並行,在同一段時間內被同一個 unit 處理
Parallelism: 多件事情可以同時被多個 unit 處理
!!平行處理的解決方案
#Functional Programming: everything is immutable
#Actor Model: keep mutable state internal to some actor.
!!Actor
每一個 actor 都是一個 thread,每一個 actor 內部自己維護自己的 state,
不同 actor 互相只能透過把訊息丟到 mail box 來溝通
多個 actor 可對應同一個 supervisor,一旦某個 actor/worker 發生問題,用來對其它受影響的 actor/worker 作出處理
!![[Akka|http://akka.io/]]
Typesafe 這家公司的作品(Scala 多數作者所屬的公司)
支援 remote actor,可以放在網路上!
Software Transactional Memory: 因為很多事件要用多個 actor 共同完成,所以這機制用來管制,當某事完成到一定程度時才把 state commit 出去。
Remote actor 分兩種:
*由 client 啟動
*由 server 啟動
因為 remote actor,所以 ActorRef 是 serializable,甚至可以存成檔案
而為了降低耦合,ActorRef 對應的 Actor 可能壞掉或是不在了,所以要考慮沒有回應的情況。

!HTC UI test
Selenium: for web UI 的 automation, rurn on IE, FireFox, Safari, Chrome, Opera。IDE 本身是 FireFox 的 plugin
Robot Framework: 自動 test case 管理,support data-driven-based testing

!GCC
162 target independent optimization passes, and about 20+ target dependent optimization passes
boundary: 如果 compiler 能打破 source file 的 scope,那麼能做一些額外的最佳化
loop unrolling optimization: 把 loop 展開
constant propagation: 把已賦常數值但未被修改的變數,在其後直接代換成該常數值
compiler 只要在最佳化的時候有可能的風險,於是它就會拒絕做最佳化

constant attribute: 在某一 function 執行過後,所有的 global variable 都不會被修改(相對於 C++ 的 constant function,這是指執行後不會修改所有成員)
pure attribute: 某一 function 在任何時候,只要帶的值相同,傳回的值也會相同;於是 GCC 可以把輸入/輸出值 cache 起來,之後每次用到就換成該值

{{{__restrict__}}}:表示這個 pointer 絕對不會與別人指向同一個實體
{{{-fstrict-aliasing}}}:只要 variable type 不同,則可視為 {{{__restrict__}}}

inter-procedure analysis (IPA):
取得兩種資訊:
#進入此函式時,有哪些變數可能被改寫
#進入此函式時,有哪些變數可能被讀
IPA in GCC is flow in-sensitive: 不會為了邏輯判斷 branch 而視為不同 case,全部視為「可能」

{{{-fipa-cp-clone}}}: clone propagation (default by {{{-O3}}})
{{{-fipa-cp}}}: constant propagation in the function (default by {{{-Oi}}} for {{{i}}} in {{{2, 3, s}}})

Inter-Module Optimization (IMO, <= 4.4)
*only for C

Link Time Optimization (LTO >= 4.5)
*only for C
*{{{-ltp}}},程式會變@@超肥@@,因為所有資訊都要塞到同一個 obj 檔
*4.6 比它好(見下)

Whole Program....(沒抄到)
*結論:用 4.6.2 最讚

!emacs
YASnippet: 仿 textmate,甚至可以直接 import textmate macro
eshell: 在 emacs 內的 shell
orgmode: 管理檔案,可以當 wiki 用,甚至還有試算表!

!Sass
兩種:
#Scss: 寫起來像 CSS
#Sass: 寫起來像 Ruby
支援巢狀
支援 import
支援數學(wryyy)

無痛轉移
{{{
sass-convert -F css -T scss your.css new.scss
}}}
甚至還有 folder 版本

debug_info: FireSass(因為 FireBug 不援援 Sass,只支援 CSS)

!lighting talk
OSS???OOS?? font
解決小字:內嵌點陣字

Micro kernel
HURD
MACH

!Introduction
Celery is an asynchronous task queue/job queue based on distributed message passing.
http://celeryproject.org/
!Service Framework
[[uWSGI]]

!Task queue
[[Celery]]

!Deployment
[[Fabric]]
Introduction (read this first!)
Extended JNI Checks
Assertions
Bytecode Verification and Optimization
Execution Mode
Deadlock Prediction
Stack Dumps
DEX File Checksums
General Flags

!Introduction (read this first!)

The Dalvik VM supports a variety of command-line arguments (use {{{adb shell dalvikvm -help}}} to get a summary), but it's not possible to pass arbitrary arguments through the Android application runtime. It is, however, possible to affect the VM behavior through certain system properties.

For all of the features described below, you would set the system property with {{{setprop}}}, issuing a shell command on the device like this:

{{{
adb shell setprop <name> <value>
}}}
@@The Android runtime must be restarted before the changes will take effect@@ ({{{adb shell stop; adb shell start}}}). This is because the settings are processed in the "zygote" process, which starts early and stays around "forever".

You may not be able to set dalvik.* properties or restart the system as an unprivileged user. You can use adb root or run the su command from the device shell on "userdebug" builds to become root first. When in doubt,
{{{
adb shell getprop <name>
}}}
will tell you if the setprop took.
If you don't want the property to evaporate when the device reboots, add a line to {{{/data/local.prop}}} that looks like:
{{{
<name> = <value>
}}}
Such changes will survive reboots, but will be lost if the data partition is wiped. (Hint: create a {{{local.prop}}} on your workstation, then {{{adb push local.prop /data}}}. Or, use one-liners like {{{adb shell "echo name = value >> /data/local.prop"}}} -- note the quotes are important.)

!Extended JNI Checks

JNI, the Java Native Interface, provides a way for code written in the Java programming language interact with native (C/C++) code. The extended JNI checks will cause the system to run more slowly, but they can spot a variety of nasty bugs before they have a chance to cause problems.

There are two system properties that affect this feature, which is enabled with the {{{-Xcheck:jni}}} command-line argument. The first is {{{ro.kernel.android.checkjni}}}. This is set by the Android build system for development builds. (It may also be set by the Android emulator unless the {{{-nojni}}} flag is provided on the emulator command line.) Because this is an "{{{ro.}}}" property, the value cannot be changed once the device has started.

To allow toggling of the CheckJNI flag, a second property, {{{dalvik.vm.checkjni}}}, is also checked. The value of this overrides the value from {{{ro.kernel.android.checkjni}}}.

If neither property is defined, or {{{dalvik.vm.checkjni}}} is set to false, the {{{-Xcheck:jni}}} flag is not passed in, and JNI checks will be disabled.

To enable JNI checking:
{{{
adb shell setprop dalvik.vm.checkjni true
}}}
You can also pass JNI-checking options into the VM through a system property. The value set for {{{dalvik.vm.jniopts}}} will be passed in as the {{{-Xjniopts}}} argument. For example:
{{{
adb shell setprop dalvik.vm.jniopts forcecopy
}}}
For more information about JNI checks, see JNI Tips.

!Assertions

Dalvik VM supports the Java programming language "assert" statement. By default they are off, but the {{{dalvik.vm.enableassertions}}} property provides a way to set the value for a {{{-ea}}} argument.

The argument behaves the same as it does in other desktop VMs. You can provide a class name, a package name (followed by "..."), or the special value "all".

For example, this:
{{{
adb shell setprop dalvik.vm.enableassertions all
}}}
enables assertions in all non-system classes.
The system property is much more limited than the full command line. It is not possible to specify more than one {{{-ea}}} entry, and there is no way to specify a {{{-da}}} entry. There is presently no equivalent for {{{-esa}}}/{{{-dsa}}}.

!Bytecode Verification and Optimization

The system tries to pre-verify all classes in a DEX file to reduce class load overhead, and performs a series of optimizations to improve runtime performance. Both of these are done by the dexopt command, either in the build system or by the installer. On a development device, dexopt may be run the first time a DEX file is used and whenever it or one of its dependencies is updated ("just-in-time" optimization and verification).

There are two command-line flags that control the just-in-time verification and optimization, {{{-Xverify}}} and {{{-Xdexopt}}}. The Android framework configures these based on the {{{dalvik.vm.dexopt-flags}}} property.

If you set:
{{{
adb shell setprop dalvik.vm.dexopt-flags v=a,o=v
}}}
then the framework will pass {{{-Xverify:all -Xdexopt:verified}}} to the VM. This enables verification, and only optimizes classes that successfully verified. This is the safest setting, and is the default.
You could also set {{{dalvik.vm.dexopt-flags}}} to {{{v=n}}} to have the framework pass {{{-Xverify:none -Xdexopt:verified}}} to disable verification. (We could pass in {{{-Xdexopt:all}}} to allow optimization, but that wouldn't necessarily optimize more of the code, since classes that fail verification may well be skipped by the optimizer for the same reasons.) Classes will not be verified by dexopt, and unverified code will be loaded and executed.

Enabling verification will make the dexopt command take significantly longer, because the verification process is fairly slow. Once the verified and optimized DEX files have been prepared, verification incurs no additional overhead except when loading classes that failed to pre-verify.

If your DEX files are processed with verification disabled, and you later turn the verifier on, application loading will be noticeably slower (perhaps 40% or more) as classes are verified on first use.

For best results you should force a re-dexopt of all DEX files when this property changes. You can do this with:
{{{
adb shell "rm /data/dalvik-cache/*"
}}}
This removes the cached versions of the DEX files. Remember to stop and restart the runtime ({{{adb shell stop; adb shell start}}}).
(Previous version of the runtime supported the boolean {{{dalvik.vm.verify-bytecode}}} property, but that has been superceded by {{{dalvik.vm.dexopt-flags}}}.)

!Execution Mode

The current implementation of the Dalvik VM includes three distinct interpreter cores. These are referred to as "{{{fast}}}", "{{{portable}}}", and "{{{debug}}}". The "fast" interpreter is optimized for the current platform, and might consist of hand-optimized assembly routines. In constrast, the "{{{portable}}}" interpreter is written in C and expected to run on a broad range of platforms. The "debug" interpreter is a variant of "portable" that includes support for profiling and single-stepping.

The VM may also support just-in-time compilation. While not strictly a different interpreter, the JIT compiler may be enabled or disabled with the same flag. (Check the output of {{{dalvikvm -help}}} to see if JIT compilation is enabled in your VM.)

The VM allows you to choose between "fast", "portable", and "jit" with an extended form of the -Xint argument. The value of this argument can be set through the dalvik.vm.execution-mode system property.

To select the "portable" interpreter, you would use:
{{{
adb shell setprop dalvik.vm.execution-mode int:portable
}}}
If the property is not specified, the most appropriate interpreter will be selected automatically. At some point this mechanism may allow selection of other modes, such as JIT compilation.
Not all platforms have an optimized implementation. In such cases, the "fast" interpreter is generated as a series of C stubs, and the result will be slower than the "portable" version. (When we have optimized versions for all popular architectures the naming convention will be more accurate.)

If profiling is enabled or a debugger is attached, the VM switches to the "debug" interpreter. When profiling ends or the debugger disconnects, the original interpreter is resumed. (The "debug" interpreter is substantially slower, something to keep in mind when evaluating profiling data.)

@@The JIT compiler can be disabled on a per-application basis by adding {{{android:vmSafeMode="true"}}} in the application tag in AndroidManifest.xml.@@ This can be useful if you suspect that JIT compilation is causing your application to behave incorrectly.

!Deadlock Prediction

If the VM is built with {{{WITH_DEADLOCK_PREDICTION}}}, the deadlock predictor can be enabled with the {{{-Xdeadlockpredict}}} argument. (The output from {{{dalvikvm -help}}} will tell you if the VM was built appropriately -- look for deadlock_prediction on the Configured with: line.) This feature tells the VM to keep track of the order in which object monitor locks are acquired. If the program attempts to acquire a set of locks in a different order from what was seen earlier, the VM logs a warning and optionally throws an exception.

The command-line argument is set based on the dalvik.vm.deadlock-predict property. Valid values are off to disable it (default), warn to log the problem but continue executing, err to cause a dalvik.system.PotentialDeadlockError to be thrown from the monitor-enter instruction, and abort to have the entire VM abort.

You will usually want to use:
{{{
adb shell setprop dalvik.vm.deadlock-predict err
}}}
unless you are keeping an eye on the logs as they scroll by.
Please note that this feature is deadlock prediction, not deadlock detection -- in the current implementation, the computations are performed after the lock is acquired (this simplifies the code, reducing the overhead added to every mutex operation). You can spot a deadlock in a hung process by sending a {{{kill -3}}} and examining the stack trace written to the log.

This only takes monitors into account. Native mutexes and other resources can also be the cause of deadlocks, but will not be detected by this.

!Stack Dumps

Like other desktop VMs, when the Dalvik VM receives a {{{SIGQUIT}}} (Ctrl-\ or {{{kill -3}}}), it dumps stack traces for all threads. By default this goes to the Android log, but it can also be written to a file.

The {{{dalvik.vm.stack-trace-file}}} property allows you to specify the name of the file where the thread stack traces will be written. The file will be created (world writable) if it doesn't exist, and the new information will be appended to the end of the file. The filename is passed into the VM via the {{{-Xstacktracefile}}} argument.

For example:
{{{
adb shell setprop dalvik.vm.stack-trace-file /tmp/stack-traces.txt
}}}
If the property is not defined, the VM will write the stack traces to the Android log when the signal arrives.

!DEX File Checksums

For performance reasons, the checksum on "optimized" DEX files is ignored. This is usually safe, because the files are generated on the device, and have access permissions that prevent modification.

If the storage on a device becomes unreliable, however, data corruption can occur. This usually manifests itself as a repeatable virtual machine crash. To speed diagnosis of such failures, the VM provides the -Xcheckdexsum argument. When set, the checksums on all DEX files are verified before the contents are used.

The application framework will provide this argument during VM creation if the {{{dalvik.vm.check-dex-sum}}} property is enabled.

To enable extended DEX checksum verification:
{{{
adb shell setprop dalvik.vm.check-dex-sum true
}}}
Incorrect checksums will prevent the DEX data from being used, and will cause errors to be written to the log file. If a device has a history of problems it may be useful to add the property to /data/local.prop.

Note also that the dexdump tool always verifies DEX checksums, and can be used to check for corruption in a large set of files.

!General Flags

In the "Honeycomb" release, a general mechanism for passing flags to the VM was introduced:
{{{
adb shell setprop dalvik.vm.extra-opts "flag1 flag2 ... flagN"
}}}
The flags are separated by spaces. You can specify as many as you want so long as they all fit within the system property value length limit (currently 92 characters).

The extra-opts flags will be added at the end of the command line, which means they will override earlier settings. This can be used, for example, to experiment with different values for -Xmx even though the Android framework is setting it explicitly.

Copyright © 2008 The Android Open Source Project
!Process virtual machine
!!Language Virtual Machine
[[OpenJVM|OpenJVM/OpenJDK]]

!!Other Process Virtual Machine
[[Font Engine]]

!Compiler
[[GCC]]
!Introduction
DZSlides is a one-page-template to build your presentation in HTML5 and CSS3.
Official website: http://paulrouget.com/dzslides/
Repository: https://github.com/paulrouget/dzslides
/***
|Name|DisableWikiLinksPlugin|
|Source|http://www.TiddlyTools.com/#DisableWikiLinksPlugin|
|Version|1.6.0|
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements|
|~CoreVersion|2.1|
|Type|plugin|
|Description|selectively disable TiddlyWiki's automatic ~WikiWord linking behavior|
This plugin allows you to disable TiddlyWiki's automatic ~WikiWord linking behavior, so that WikiWords embedded in tiddler content will be rendered as regular text, instead of being automatically converted to tiddler links.  To create a tiddler link when automatic linking is disabled, you must enclose the link text within {{{[[...]]}}}.
!!!!!Usage
<<<
You can block automatic WikiWord linking behavior for any specific tiddler by ''tagging it with<<tag excludeWikiWords>>'' (see configuration below) or, check a plugin option to disable automatic WikiWord links to non-existing tiddler titles, while still linking WikiWords that correspond to existing tiddlers titles or shadow tiddler titles.  You can also block specific selected WikiWords from being automatically linked by listing them in [[DisableWikiLinksList]] (see configuration below), separated by whitespace.  This tiddler is optional and, when present, causes the listed words to always be excluded, even if automatic linking of other WikiWords is being permitted.  

Note: WikiWords contained in default ''shadow'' tiddlers will be automatically linked unless you select an additional checkbox option lets you disable these automatic links as well, though this is not recommended, since it can make it more difficult to access some TiddlyWiki standard default content (such as AdvancedOptions or SideBarTabs)
<<<
!!!!!Configuration
<<<
<<option chkDisableWikiLinks>> Disable ALL automatic WikiWord tiddler links
<<option chkAllowLinksFromShadowTiddlers>> ... except for WikiWords //contained in// shadow tiddlers
<<option chkDisableNonExistingWikiLinks>> Disable automatic WikiWord links for non-existing tiddlers
Disable automatic WikiWord links for words listed in: <<option txtDisableWikiLinksList>>
Disable automatic WikiWord links for tiddlers tagged with: <<option txtDisableWikiLinksTag>>
<<<
!!!!!Revisions
<<<
2008.07.22 [1.6.0] hijack tiddler changed() method to filter disabled wiki words from internal links[] array (so they won't appear in the missing tiddlers list)
2007.06.09 [1.5.0] added configurable txtDisableWikiLinksTag (default value: "excludeWikiWords") to allows selective disabling of automatic WikiWord links for any tiddler tagged with that value.
2006.12.31 [1.4.0] in formatter, test for chkDisableNonExistingWikiLinks
2006.12.09 [1.3.0] in formatter, test for excluded wiki words specified in DisableWikiLinksList
2006.12.09 [1.2.2] fix logic in autoLinkWikiWords() (was allowing links TO shadow tiddlers, even when chkDisableWikiLinks is TRUE).  
2006.12.09 [1.2.1] revised logic for handling links in shadow content
2006.12.08 [1.2.0] added hijack of Tiddler.prototype.autoLinkWikiWords so regular (non-bracketed) WikiWords won't be added to the missing list
2006.05.24 [1.1.0] added option to NOT bypass automatic wikiword links when displaying default shadow content (default is to auto-link shadow content)
2006.02.05 [1.0.1] wrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals
2005.12.09 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.DisableWikiLinksPlugin= {major: 1, minor: 6, revision: 0, date: new Date(2008,7,22)};

if (config.options.chkDisableNonExistingWikiLinks==undefined) config.options.chkDisableNonExistingWikiLinks= true;
if (config.options.chkDisableWikiLinks==undefined) config.options.chkDisableWikiLinks=false;
if (config.options.txtDisableWikiLinksList==undefined) config.options.txtDisableWikiLinksList="DisableWikiLinksList";
if (config.options.chkAllowLinksFromShadowTiddlers==undefined) config.options.chkAllowLinksFromShadowTiddlers=true;
if (config.options.txtDisableWikiLinksTag==undefined) config.options.txtDisableWikiLinksTag="excludeWikiWords";

// find the formatter for wikiLink and replace handler with 'pass-thru' rendering
initDisableWikiLinksFormatter();
function initDisableWikiLinksFormatter() {
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="wikiLink"; i++);
	config.formatters[i].coreHandler=config.formatters[i].handler;
	config.formatters[i].handler=function(w) {
		// supress any leading "~" (if present)
		var skip=(w.matchText.substr(0,1)==config.textPrimitives.unWikiLink)?1:0;
		var title=w.matchText.substr(skip);
		var exists=store.tiddlerExists(title);
		var inShadow=w.tiddler && store.isShadowTiddler(w.tiddler.title);
		// check for excluded Tiddler
		if (w.tiddler && w.tiddler.isTagged(config.options.txtDisableWikiLinksTag))
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }
		// check for specific excluded wiki words
		var t=store.getTiddlerText(config.options.txtDisableWikiLinksList);
		if (t && t.length && t.indexOf(w.matchText)!=-1)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }
		// if not disabling links from shadows (default setting)
		if (config.options.chkAllowLinksFromShadowTiddlers && inShadow)
			return this.coreHandler(w);
		// check for non-existing non-shadow tiddler
		if (config.options.chkDisableNonExistingWikiLinks && !exists)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }
		// if not enabled, just do standard WikiWord link formatting
		if (!config.options.chkDisableWikiLinks)
			return this.coreHandler(w);
		// just return text without linking
		w.outputText(w.output,w.matchStart+skip,w.nextMatch)
	}
}

Tiddler.prototype.coreAutoLinkWikiWords = Tiddler.prototype.autoLinkWikiWords;
Tiddler.prototype.autoLinkWikiWords = function()
{
	// if all automatic links are not disabled, just return results from core function
	if (!config.options.chkDisableWikiLinks)
		return this.coreAutoLinkWikiWords.apply(this,arguments);
	return false;
}

Tiddler.prototype.disableWikiLinks_changed = Tiddler.prototype.changed;
Tiddler.prototype.changed = function()
{
	this.disableWikiLinks_changed.apply(this,arguments);
	// remove excluded wiki words from links array
	var t=store.getTiddlerText(config.options.txtDisableWikiLinksList,"").readBracketedList();
	if (t.length) for (var i=0; i<t.length; i++)
		if (this.links.contains(t[i]))
			this.links.splice(this.links.indexOf(t[i]),1);
};
//}}}
{{{
void logf(int log_level, const char *func_name, int line_number, const char *format, ...)
{
    va_list args;
    char log[1024];

    va_start (args, format);
    vsnprintf(log, sizeof(log), format, args);
    va_end (args);


    printf("ERROR: function: %s:%d %s", func_name, line_number, log);
}

}}}
!Introduction
Fabric is a Python (2.5 or higher) library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks.
http://docs.fabfile.org/en/1.2.0/index.html
Well-known engines:
*FreeType (Linux)
*GDI++ (Windows)

字型被縮得太小時,會發生像素破碎不美觀的問題。
解決辦法:
#內嵌點陣字
#hinting
Original post:
http://mindprod.com/jgloss/phantom.html

| Type | Purpose | Use | When GCed | Implementing Class |h
| Strong Reference |An ordinary reference. Keeps objects alive as long as they are referenced.|normal reference.|Any object not pointed to can be reclaimed.| (default) |
| Soft Reference |Keeps objects alive provided there’s enough memory. |to keep objects alive even after clients have removed their references (memory-sensitive caches), in case clients start asking for them again by key.|After a first gc pass, the JVM decides it still needs to reclaim more space.| {{{java.lang.ref.SoftReference}}} |
| Weak Reference |Keeps objects alive only while they’re in use (reachable) by clients.|Containers that automatically delete objects no longer in use.|After gc determines the object is only weakly reachable| {{{java.lang.ref.WeakReference}}}, {{{java.util.WeakHashMap}}} |
| Phantom Reference |Lets you clean up after finalization but before the space is reclaimed (replaces or augments the use of {{{finalize()}}})|Special clean up processing|After finalization.| {{{java.lang.ref.PhantomReference}}} |
!Optimization
//compiler 只要在最佳化的時候發現有可能的風險,它就會拒絕做最佳化。//

162 target independent optimization passes, and about 20+ target dependent optimization passes
boundary: 如果 compiler 能打破 source file 的 scope,那麼能做一些額外的最佳化

!!Compile-time Optimization
!!!loop unrolling optimization
直接把 loop 展開,例如
{{{
int i;
for (i = 0; i < 3; ++i) {
    foo();
    printf("%d\n", i);
}
}}}
會變成
{{{
foo();
printf("%d\n", 0);
foo();
printf("%d\n", 1);
foo();
printf("%d\n", 2);
}}}

萬一 {{{foo}}} 這個函式會修改 {{{i}}} 的值,這樣展開就爆了。因此有以下兩種資訊需要檢驗:
*constant attribute: 在某一 function 執行過後,所有的 global variable 都不會被修改(相對於 C++ 的 constant function,這是指執行後不會修改任何成員變數)
*pure attribute: 某一 function 在任何時候,只要帶的值相同,傳回的值也會相同;於是 GCC 可以把輸入/輸出值 cache 起來,之後每次用到就換成該值

!!constant propagation
把已賦常數值但未被修改的變數,在其後直接代換成該常數值

*{{{__restrict__}}}:表示這個 pointer 絕對不會與別人指向同一個實體
*{{{-fstrict-aliasing}}}:只要 variable type 不同,則可視為 {{{__restrict__}}}

!!!inter-procedure analysis (IPA):
取得兩種資訊:
#進入此函式時,有哪些變數可能被改寫
#進入此函式時,有哪些變數可能被讀
IPA in GCC is flow in-sensitive: 不會為了邏輯判斷產生的各種 branch 而視為不同 case,全部視為「會走過的 code」,因此會取最佳化手段的交集,減少最佳化的可能性。在沒有使用更好的解決辦法(更新版本的 compiler)之前,為最佳化設想,請避免 if-else 與 switch-case,改用 function。

!!Link-time Optimization
{{{-fipa-cp-clone}}}: clone propagation (default by {{{-O3}}})
{{{-fipa-cp}}}: constant propagation in the function (default by {{{-Oi}}} for {{{i}}} in {{{2, 3, s}}})

!!!Inter-Module Optimization (IMO, <= 4.4)
*only for C

!!!Link Time Optimization (LTO >= 4.5)
*only for C
*{{{-ltp}}},程式會變@@超級肥@@,因為所有資訊都要塞到同一個 obj 檔
*4.6 比它好(見下)

Whole Program....(沒抄到)
*結論:用 4.6.2 最讚
http://code.google.com/p/html5slides/
!Introduction
This is a charting library.
http://www.highcharts.com/

!How to use?
http://www.highcharts.com/documentation/how-to-use
StackOverflow: http://stackoverflow.com/questions/1249973/decompiling-dex-into-java-sourcecode

ericharlow said:
<<<
first you need a tool called [[dex2jar|http://code.google.com/p/dex2jar/]] ,which is made by a chinese student. it will translate dex to jar file. then you can use [[jd-gui|http://java.decompiler.free.fr/?q=jdgui]], the source code is quite readable as dex2jar makes some optimizations.
<<<
No matter you use Linux or OSX, PLEASE follow the official install guide:
[[http://beginrescueend.com/rvm/install/]]
And follow the {{{Single-User installations}}} to avoid shoot yourself in the foot.

Then, don't forget to modify your shell configuration. For example,
{{{
$ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.zshrc
}}}
It's better to editor your shell configuration file instead of executing the above line.
{{{
sudo apt-get install build-essential
}}}
!如何取得成員變數/靜態成員變數
#{{multiline{先取得 field ID:
{{{
jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
}}}
}}}
#{{multiline{再來才能取得其值:
{{{
NativeType GetStatic<type>Field(JNIEnv *env, jclass clazz, jfieldID fieldID);
}}}
}}}

!如何取得特定物件對應的 {{{Class}}} Class
Just try this:
{{{
jclass GetObjectClass(JNIEnv *env, jobject obj);
}}}
!Java Virtual Machine (JVM)
[[OpenJDK]]

!Frameworks
!!Android
*[[Build Android on Ubuntu 9.10]]

!Java Native Interface
[[JNI Types and Data Structures|http://download.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html]]
[[JNI Functions|http://download.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html]]
[[some notes ...|JNI Notes]]

!Garbage Collection
[[Four kinds of references: strong, soft, weak, and phantom]]
[[DZslides]] - a one-page-template to build your presentation in HTML5 and CSS3.
[[Highcharts JS]] - a powerful charting library.

[[True Table]]
!Intorduction
This is an award-winning application that monitors executions of repeated jobs, such as building a software project or jobs run by cron. 簡單來說就是一個持續結成工具,結合處理所有你在專案中常遇見的雜事。

[[這裡|https://wiki.jenkins-ci.org/display/JENKINS/Meet+Jenkins]]有官方介紹。
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
 major: 1, minor: 1, revision: 0, 
 date: new Date("mar 17, 2007"), 
 source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};

if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};

bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
 if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){ 
 url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
 }
 return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}
[[WelcomeToTiddlyspot]]
[[GettingStarted]]
----
[[Quotes]]
----
[[Reading List|http://reader-cdip.tiddlyspot.com/index.html]]
----
[[Martin's Wiki|http://www.martinswiki.com/]]
[[TiddlyWiki Unofficial Chinese Documents|http://web.nlhs.tyc.edu.tw/~lss/wiki/TiddlyWikiTutorialTW.html#]]
[[C&C++]]
[[Java]]
[[JavaScript]]
[[Scala]]
[[Python]]
[[Ruby]]
[[shell script]]
[[Android]]
[[emacs]]
----
[[git]]
----
[[UNIX-like OS / POSIX]]
#用 ps -al 定期觀察。
#先用 ps 找出對應的 process ID,而後在 {{{/proc/<PID>/fd}}} 中看看是否開了一堆沒關掉的 fd。
<<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>
!Garbage Collection (GC)
OpenJDK use @@G1@@ collector

!Just-in-Time (JIT) compilation
Tiered compilation in 7.
Reference: http://weblogs.java.net/blog/forax/archive/2010/09/05/tiered-compilation

!Misc
"Async I/O" is added in OpenJDK 7 .
{{{java.lang.reflection.*}}} is //very very slow//,所以 OpenJDK7 加入了 InvokeDynamic
<div class='header' macro='gradient vert #FFF #FFF '>
 <div class='gradient'> 
 <div class='titleLine' >
<span class='searchBar' macro='search'></span>
 <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
 <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
 </div>
<div id='topMenu' refresh='content' tiddler='MainMenu'></div>
 </div>
</div>
<div id='bodywrapper'>
<div id='sidebar'>
 <div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
 <div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
 <div id='messageArea'></div>
 <div id='tiddlerDisplay'></div>
</div>
<div id='displayFooter'></div>
</div>
!Definition
!!Concurrency 併發
同一時間可以有多個 task 正在被處理中,亦即 task 發生的時間可以彼此重疊,但在同一時間點上不保證所有 processing unit 會處理到所有的 task。e.g. 單核心 CPU 上執行多執行緒程式,這是以 OS 的 context switch 達成 concurrency。
!!Parallelism 併行
同一時間可以有多個 task 同時被處理,也就是 {{{m}}} 個 task 同時在 {{{n > m}}} 個 processing unit 上面被執行。

//parallelism// 只是 //concurrency// 的可行方案之一。

!General question: race condition, dead lock, etc ...
!!Root cause
在 threads 間共用記憶體乃是萬惡之源。

!!Solution
There are two (or more?) solutions:
#''Functional Programming'': everything is immutable
#''Actor Model'': keep mutable state internal to some actor.

!Actor
每一個 actor 都是一個 thread,每一個 actor 內部自己維護自己的 state,不同 actor 互相只能透過把訊息丟到 mail box 來溝通。

問題:如何解決 actor 間的相依性?例如,actor {{{A}}} 倚靠 actor {{{B}}} 的結果,一旦 {{{B}}} 死亡,{{{A}}} 的 state 也必須被重置。
解決:多個 actor 可對應同一個 supervisor,一旦某個 actor/worker 發生問題,用來對其它受影響的 actor/worker 作出處理。

!!Implementations
Scala: [[scala.actorsActor|http://www.scala-lang.org/api/current/scala/actors/Actor.html]], [[Akka framework]]
Erlang:(記得 scala 的 actor 是抄 erlang 的?)
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
	major: 1, minor: 0, revision: 2, 
	date: new Date("Apr 19, 2007"),
	source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
	coreVersion: '2.2.0 (Beta 5)'
};

config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");

merge(config.macros.option.types, {
	'pas': {
		elementType: "input",
		valueField: "value",
		eventName: "onkeyup",
		className: "pasOptionInput",
		typeValue: config.macros.option.passwordInputType,
		create: function(place,type,opt,className,desc) {
			// password field
			config.macros.option.genericCreate(place,'pas',opt,className,desc);
			// checkbox linked with this password "save this password on this computer"
			config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);			
			// text savePasswordCheckboxLabel
			place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
		},
		onChange: config.macros.option.genericOnChange
	}
});

merge(config.optionHandlers['chk'], {
	get: function(name) {
		// is there an option linked with this chk ?
		var opt = name.substr(3);
		if (config.options[opt]) 
			saveOptionCookie(opt);
		return config.options[name] ? "true" : "false";
	}
});

merge(config.optionHandlers, {
	'pas': {
 		get: function(name) {
			if (config.options["chk"+name]) {
				return encodeCookie(config.options[name].toString());
			} else {
				return "";
			}
		},
		set: function(name,value) {config.options[name] = decodeCookie(value);}
	}
});

// need to reload options to load passwordOptions
loadOptionsCookie();

/*
if (!config.options['pasPassword'])
	config.options['pasPassword'] = '';

merge(config.optionsDesc,{
		pasPassword: "Test password"
	});
*/
//}}}
!Tools
[[Jenkins]] - 持續結成工具
!XML
[[eTree Tutorial Example]]

!Network Development
(You may like to refer to item [[Cloud]])
[[Celery]] - a distributed task queue
[[Fabric]] - a deployment tool
[[Twisted]] - an event-driven networking engine
[[Scrapy]] - screen scraping and web crawling framework
!My Friends
!!by ColdTurnip
*無心插柳柳橙汁,一人做事薏仁湯。
*洗冷水澡才是男人的浪漫!
*做人,靠什麼都可以,就是不要靠杯。
*要背刺別人,就不要怕被別人背刺。
*回憶,是用來回憶,而不是用來堅持。
*人之所以逃避,那是人還保有他的人性的部份。
*「客觀」本質上也不過是一種主觀的概念。
*子非魚,安知雜魚之雜?
*世界上最令人感到遺憾的事情,都是在你所不知道的時候發生。
*就是因為害怕寂莫,所以才需要成為強者。
*俗世間廢柴者眾,已無吾等容身之處。
*沒有無用的知識,只有無用的人。
*死一個人是個小說,死十個人是個事件,死一百個人是個震撼,死一千個人是個悲劇,死一百萬個人是個數字,死兩億個人是自殘。
*世界上所有的誤會,都是量化雜訊造成的。

!!by 企鵝 (S.H. Lin)
*積極努力是我們唯一該做的工作,目前的煩惱和困境,在後人的眼中,將是理所當然的事情。
*寬恕–就是寬恕自己不寬恕的事情。
*千萬別教企鵝爬樹,不但教不會,而且還會惹企鵝生氣;千望別教熊貓抓魚,不但教不會,而且就算牠抓到也不愛吃。

!!by sleeper (Keifer Li)
*我謝~~~~ 你喔!
*我真是謝謝你媽媽的!

!!by unojerry (F.Y. Shie)
*我哥真的超帥的!還有女生要幫他洗衣服、煮飯給他吃耶!
*我覺得我真的長得很像我哥。
*那個苗疆殺人蛙那集真的很好笑、好笑到炸掉!
*真希望對面五個對手都是我。

!!by 867212/871308(?)
*老二不努力,奶大徒傷悲。」
*「我只想做韓琛的女人。」「什麼!!!」「唔,那麼…這樣,有沒有問題?有問題的話,我再說一次:我只想做韓琛的女人。」「什麼!!!」…
*我謝你媽媽流鼻涕!
*ㄗㄧㄠˇ 子
*恩正公有四大名產:「糙」、「幹炮」、「正妹」、「愛靠杯」。

!from Other Friends...
*寧為清白之身,勿做污泥之鞋;清清白白過一生,不怕九泉之下沒得樂。by 王尹宸
*你買了這支「檸檬伏特加」冰棒卻又希望它和伏特加一樣熱熱辣辣的話,那你買這冰棒幹麼?by 呂志謙
*帥不過舔樂,屌不過卡秋。by 楊文昊
*當你抓住夢想的那一瞬間,夢想就從你的手中消逝了。
*動不動就要人家給你最終結果,你以後怎麼做研究?by 徐詩雨
*就算是再要好的人,還是要為彼此留些空間喘息。by 許穎華
*不要因為失望而改變你平日的笑容。by 林恩正
*我數學沒有很強,只是考的題目,恰好全都會而已…by 謝宗震

!from Teachers
*我以前大學可是那個籃球健將啊,而且我還可以半場灌籃!by 張大中
*其實小美人魚很偉大,因為他還願意將聲音賣給巫婆。by 陳彥文
*網路有七層,很有趣;地獄有十八層,應該更有趣。by 張大中
*三十歲的時候,靠的是體力;四十歲的時候,靠的是腦力;五十歲的時候,靠的是人脈;等到六十了,就只能靠一張嘴,大家都要聽你的。by 許獻聰
*出社會以後,到困難要找的幫手,首先是同志,就是一起作弊、一起被抓的那種、同甘共苦的伙伴;再來就是同學;最後才考慮家人。by 許獻聰

!Internet
!!from PTT
*弱水三千,但是因為太貴了,所以只取一瓢飲。by aokman
*俗話說的好~書中自有貧民窟。by aokman
*厲鬼活捉薄倖人,弩炮殺死條頓人。by aokman
*告白不過是把自己的困擾讓別人去煩惱罷了!
*萬惡孝為首,百善蝦味先。by DDRMIX
*愚者以東為東,以西為西,以南為南,以北為北。智者不以東為東,不以西為西,不以南為南,不以北為北。賢者知東不必為東,但以東為東;知西不必為西,但以西為西;知南不必為南,但以南為南;知北不必為北,但以北為北。by seafood
*肝若壞,人生是黑白的;肝若好,考卷是空白的。by Juicetea
*不要太相信格言,因為人生沒那麼簡單。by rasheedchiu

!!from Bahamut
*拿明朝的劍,斬清朝的官;拿 d2ex 的裝備,打 CD2 的豬;拿 1925 年死掉的人,罵 1946 年頒布的法。想當然爾,無堅不摧──無知,就是力量。
*你看看,這個 120GB 的高級硬碟裝了 110GB 的資料,卻一點重量都沒有增加!
*我最不能接受人家說我是偽物嚴正聲明下列這些並不是正宗 r 機和他兄弟本尊,但是他們要說他們很帥也可以。by rtype29
*注意你對本座上書的的態度!by n180
*機體的不足可以用技術補足,技術不足卻不是機體性能可以彌補的!這是我的信念!by zplusc1
*朝辭白帝彩雲間,欠你賭錢明日還。
*孤帆遠影必殺技,唯見腸漿天際流。
*連玩都只玩一半?by akd0021
*怨言是上天得至人類最大的供物,也是人類禱告中最真誠的部分。by runa
*東吳立案 合法利息 免留船 稻草人可借by bluejhone
*曹沖偉大的地方不是在於秤象,而是在於他做了那艘船by gunpoint
*待人處事…或者說倫理…不是根基於明文規則之上的。by christ
*大陸是台灣不可分割的一部份!by crosszero
*要吐我的,麻煩到一號窗口領號碼牌,二號窗口掛號,三號窗口申請,謝謝!by hiking
*人類從歷史上學到的唯一教訓,就是人類無法從歷史上學到教訓!by Onizuka24
*動畫迷最自豪的就是有無盡的無用知識。by ACE5218
*床前不見明月光,獨愴然而涕。by intree
*藤井樹?我稱他為「量產型言情小說產生器」。by eaglelee
*古今中外的名言,都是一行文。by Fanatic
*龍蝦若有了人性,他就不是蝦,是蝦仁。by rezo
*女人心海底針,好人都不知道…好人心海底雞,超商都買的到。by xblade
*不要認為累積善事就能兌換女朋友一枚。by ibukimaya
*我住板橋,真的是橋生啊!by Genesic
*【開卷有益】打開了考卷,才知道書本對我有益。by peterc
*不成熟的人才會把成熟或是幼稚掛在嘴上。by NovaRain
*讀出師表不流淚者,其人必不忠;看電車男不流淚者,其人必不宅。
*一人做事薏仁湯,小叮做事小叮噹;無心插柳柳橙汁,鳩佔鵲巢檸檬茶。by yoco
*我每天早上都被自己帥醒。by settingsun
*可愛就是正義
*當你覺得自己知道了些什麼時,正是你什麼都還不知道的表現。by NovaRain
*騾馬不是一天造成的。by eDonkey
*總結人生,精彩不亮麗,起落是無常。by gainx
*金風未動蟬先覺,暗訟分手死不知。by OLDFATHER
*是命跑不掉,是命要不到。by alex70266
*腦袋不自由的教授,怎麼能教出腦袋自由的學生?by hc
*良禽則木而棲,賢伶擇凱子而侍。by rolf
*有時候,男人只能用拳頭交心,用傷痛讚賞彼此。by rsd
*我們都認為孩童的天真無邪是純潔的象徵,但事實是無知就是一種罪惡,不分男女老幼都一樣。──NovaRain
*要比悲慘的事就像炒飯一樣,大家都能拿些雞毛蒜皮小事出來把飯煮熟、加油加鹽然後來個大鍋快炒,有時還可以打個蛋下去加料。但真正悲慘的人是不會做炒飯的,因為他們通常沒時間用嘴巴和文字來調味,更別說準備好白飯了。by NovaRain
*主觀視為涉入事件本體而對此所產生的體驗認知。客觀則為非涉入事件本體但對其所產生的觀察認知。by bugbook
*語言和文字是意象與感情的有損 (Lossy) 格式。by NovaRain
*雖說人間有愛,可是太低分的一樣會當掉。by Astray
*越自以為客觀,越自以為理性,你就越不可能證明感情的正當性。by TreasureH
*樹大必有枯枝,人多必有白痴。by Lincm
*天要亡我,我必逆天。by skuld007
*世界上不管什麼東西的機率都是 1/2。by ctcxforever
*小心做鬼也被笑哦,那麼多事情沒有經歷過,到時候連人家鬼在聊啥你都聽不懂。by mooncat0205
*當你舉起劍保護你愛的人的時候,你卻失去了抱起愛人的手。by ctcxforever
*這世界上多的能用你十分之一的時間賺取你薪水的十倍金錢的人,能吃飽撐著才是強者的證明,嫌人家吃飽撐著恐怕只突顯你的貧弱和渺小。by pufferfish
*樹多必有枯枝,人多必有白痴;樹不要皮必死無疑,人不要臉天下無敵。by a90811
*暴力不能解決事情,但是可以解決你。
*世上沒有強與弱,有的只有勝與負。by saitohajime
*最親近自己的人,永遠不會在妳需要她的時候前來;只有敵人,才會準時殺到。by Windranger
*所謂的科技業,就是一群男人在玩他們一輩子都買不起的玩具。by ninetails
*無法驗證的錯誤就代表沒有錯誤,檢查不出的疾病就代表沒有疾病;一個人不管多麼變態,只要他沒有做出變態的事情,他就不是變態。by TreasureH
*上帝看到世界上沒有光,所以創造了太陽;上帝看到世界上沒有白癡收容所,所以創造了教會。
*最令人傷心的事,並不是全世界的人都比你厲害,而是自己竟然不是最爛的。by NovaRain
*看別人如何成功有時很無聊而且不切實際,但看別人怎樣失敗倒是挺有意思的。各人成功的經驗不一定能複製,但如何像前人一樣失敗倒是意外地容易。by NovaRain
*好漢不騎回頭馬。愛他不成,祝他去死。by alex70266
*憂鬱只是欺騙自己而已, 對現狀或是對別人都沒有任何正向意義。by Tiberius
*大多數的醫療糾紛,沒有醫療疏失;大多數的醫療疏失,沒有醫療糾紛。by TreasureH
*時勢造英雄,屎事造英雄。by eggli
*把自己提升到看不到嘴炮白痴的世界才是正解。by poga

!from Animations, Comics, and Games
!!Air
*人如果沒有回憶,是活不下去的;但是光只靠回憶,也是無法活下去 的。by 遠野滿
*恐龍曾經長時間地興盛過…可是已經滅絕了,現在已經都不存在了。是已經邁向終結的生物喔。總會令人感到胸口一陣痛楚般的難過。by 神尾觀玲
!!Clannad
*探求事物真理之人決不得傲慢,雖然無法以科學來解釋,但絕不能漠視奇蹟的存在,一定要用目光去注視這個世界的美麗。by 一之瀨琴美
!!Final Fantasy Ⅶ
*當時是犧牲了「一些」人的生命,但是這對那些犧牲了的人來說是他們的全部啊!by Cait Sith
*你應該記住我的名字,Cloud!by Cloud
!!Kanon
*回憶跟時間是沒有關係的,而是對當事人來說,那一瞬間到底多重要by 美坂栞
*正因為不會發生,所以才叫作奇蹟。by 美坂栞
!!Metal Gear Solid Ⅱ - Sons of liberty
*生命並不只是傳遞你的基因。我們可以留下比 DNA 更多的東西。透過語言、音樂、藝術及電影…我們所看到的、所聽到的、所感覺到的…所有的憤怒、喜樂以及憂傷…這些都是我將傳遞下去的事物。這也是我活著的原因。我們必需世代交替,並讓我們的子孫能夠讀到我們巨細靡遺歷史的光明面。我們有著數位時代的科技幫助我們。也許有一天人類會走向終點,新的物種也許會統治著這個星球。地球也許不會永遠存在,但我們仍然有盡力留下生命蹤跡的責任。建造未來,保存過去,它們都有著同樣的道理… by Solid Snake
!!Sourth Park
*去你的擔擔麵!炸你的雞柳條!媽勒個挫冰!
*歡迎來到馬庫拉,這裡所有的馬庫拉都是馬庫拉,就讓我馬庫拉來跟你解釋什麼叫做馬庫拉。
*咖啡就像人生一樣又苦又澀…喝咖啡才能了解漂浪的人生。
*我才不要讓偽善的天線寶寶侵蝕我嬌弱的心靈。
!!The Big-O
*Big-O! It's show time! by Roger Smith
*對人來說,記憶是重要的東西;因為有記憶,人才能確認自我的存在。by Roger Smith
!!Keroro 軍曹
*專用可以給人平常三倍的力量!by Keroro
*夏美 my love, kiss me tender and hold me tight forever !!! by Geroro
!!天元突破
*你以為我是誰啊!!!
*聽好了,西蒙:別忘記,相信你自已;不是相信我的你,也不是相信你的我,相信你、相信自已吧!by 卡米那
*永別了…好兄弟… by 卡米那
*我是西蒙!大紅蓮團的團長!鑽洞西蒙!如果你成為銅牆鐵壁擋在我面前的話,隨時都會在你身上開個窟窿把你貫穿!那就是我的鑽頭!!by 西蒙
*這是我最後的義務。by 羅修
*你的遺志,我來實現!by 西蒙
*不要嘆息,女兒啊!曾經一度因絕望和倦怠而沉沒的靈魂、走到了這一步,雖然是虛構的身體,但如果是為了創造螺旋生命的明天的話,正如吾願!by 羅杰諾姆
*我的鑽頭是衝破天際的鑽頭啊!by
*滿天星辰都是敵人!by
*GIIIIIIIIGA DRIIIIIIIIIL BREAAAAAAAAAAAAAACK!!!!!
!!次元艦隊
*如果你的必勝信念能夠躲得過這顆子彈的話…我就相信精神是無限的吧!by 草加拓海
*就算是合法的,我也不想殺人。by 菊池雅行
!!反逆的魯魯修
*虛偽的眼淚會傷害別人,虛偽的笑容會傷害自己。by C.C.
*對於人是「追尋幸福的存」在此一事實,一絲的願望、隱約的期盼,乃是由絕望而生。by C.C.
*越是珍視的東西,越要敬而遠之。by C.C.
!!交響詩篇 Eureka-7
*不要哀求,學會爭取;若是如此,終有所獲。by 阿德洛克‧薩斯頓
!!涼宮春日的憂鬱
*我是畢業於東中的涼宮春日,對一般人類沒有興趣;如果在這裡面有外星人、未來人、異世界人、超能力者存在的話,就來找我,以上。by 涼宮春日
*我認為「萌」也是一個比較重要的要素哦。by 涼宮春日
!!跳躍吧!時空少女
*Time waits for no one.
!!新世紀 Evangilion
*不能逃、不能逃、不能逃、不能逃、不能逃、不能逃、不能逃… by 碇真嗣
*所謂的長大成人就是不斷的聚了散、散了又聚。by 葛城美里
*打沒有勝算的仗不是有種,是笨蛋。by 相田劍介
*全日本的能源就交給你了。by 葛城美里
*男女之間並非邏輯關係。by 赤木律子
*你在拼命逃避第一次接觸呢。你害怕與別人接觸嗎?如果不認識別人的話,就不會被別人背叛,也不會互相傷害,但是,也就不能擺脫寂寞。人類是不能永遠消除寂寞的,人始終是一個人。但人可以忘掉過去,所以才能夠活下去。人類常在心中感到痛苦。因為心靈怕痛苦,所以便覺得生存很困難。你就像玻璃一樣纖細,特別是你的心。by 渚薰
*歌曲真好,歌曲給我們快樂。它是 Lilin 創造文化的精髓。by 渚薰
*所有的一切,無論好與壞,都是這個現實的世界留給我們每個人的羈絆。by 淩波零
*進化的終點就是死亡。by 赤木律子
*進化的最終目的是自我毀滅。by 碇源堂
*人類的敵人,最終還是人類。by 碇源堂
*只要活著,哪裡都是天堂。by 碇唯
*死亡的命運也是新生的歡樂。by Seele
*死是不能生出東西來的。by 碇源堂
*夢是現實的延續;現實是夢的結束。by 淩波零
*越瞭解痛苦的人,就越能以溫柔待人,這和懦弱是不同的。by 加持良治
!!鋼之煉金術士
*人如果不作出犧牲就什麼都得不到,為了得到某些東西就必須付出同得的代價。by 阿爾馮斯‧艾爾立克
!!機動戰士 Gundam
*各位國民!我們的祖國是大國呢?還是小國?是小國。我國經濟力還不到連邦的三十分之一。但是,我們的祖國是強國呢?還是弱國?是強國!by 基連‧薩比
*你太不成熟了!by 布萊特‧諾亞
*現在的我,無法打倒鋼彈!拉拉啊!引導我吧!by 夏亞‧阿茲納布
!!機動戰士 Gundam ── 0080 War in the Pocket
*沒有人是因為這是沒辦法的所以就該死。by Side 6 警官
*我要戰鬥終究還是為了自己,因為害怕自己成為孤獨的人,才會去戰鬥的;但是那是我活下去的方式。逃也是屬於個人的方式,誰都無法決定誰是對的、誰是錯的,因為有戰爭就會有人死去,但不戰爭也一樣會死去。正確的事在哪裡都不存在的,只能做自己能做的事而已。by 克麗斯汀娜‧瑪肯吉
!!機動戰士 第 08 MS 小隊
*不斷射擊到砲管過熱為止!by 天田士郎
*我只簡單說幾句:絕對不可以死!我也會更努力的不讓自己戰死在沙場!戰鬥中,就算採取再多的英雄式行動,但如果因此陣亡,就什麼也不是了!我身為隊長,非常的希望小隊能夠全員生還,大家能夠一起歸隊 共同分享勝利的喜悅!by 天田士郎
!!機動戰士 Gundam ── 0083 Stardus Memory
*你也是軍官吧!如果不是一介士兵的話,就要以整個大局來看事物!by 阿那貝爾‧卡多
*…但是,戰鬥決定於一瞬之間,有所迷惑的一方是會輸的。by 紹斯‧巴寧格
*欲成大義之人是不可以拘泥於小節的。by 艾裘‧迪拉茲
*為了再次高揭吉翁的理想,也為了成就星塵作戰,所羅門啊!我又回來了啊!by 阿那貝爾‧卡多
*但是只被怨恨來支持著戰鬥的人,是打不倒我的!因為我是站在一個義字之上的!by 阿那貝爾‧卡多
!!機動戰士 Z Gundam
*這就是青春啊…by 夏亞‧阿茲納布
*機動戰士 Gundam ── 0093 逆襲的夏亞
*地球並沒有巨大到足以吞容所有人類的自私心態!by 夏亞‧阿茲納布
*(指人類的自私) 人類的智慧足以超越它!by 阿姆羅‧列
*(指人類足以克服自私) 那麼,你現在授與那些愚民睿智給我看啊!by 夏亞‧阿茲納布
!!機動武鬥傳 G Gundam
*當我的手中發出萬丈光芒,就是為了打倒你而怒吼!粉碎吧!必殺!閃耀光指!!!by 多蒙‧火洲
*我的手正火紅燃燒著,為了抓住勝利而怒吼!要去了!以流派──東方不敗之名,爆熱‧神威掌‧石破~天驚拳!by 多蒙‧火洲
*流派──東方不敗!王者之風,全新系列,天破俠亂,看啊!血染東方一片紅!by 多蒙‧火洲 & 東方不敗
!!新機動戰記 Gundam W
*五飛,告訴我!我們還要殺死多少人?我還要多少次,再殺像那孩子般的人?零式什麼也沒告訴我,告訴我,五飛!by 希洛‧唯
!!機動戰士 Gundam SEED
*什麼才是必須與之而戰的?by 拉克絲‧克萊茵
*被殺了所以去殺,因為殺了所以被殺,那樣,世界真的會和平嗎?by 卡佳莉‧阿斯哈
!!機動戰士 Gundam SEED Destiny
*名字是存在的證明,如果它是假的,那麼這個人也不會存在。by 基魯巴特‧杜蘭朵
*如果那個時候自己有力量的話…只要自己有力量的話…為自己的無力而哭泣過的人,大概誰都會這麼想…但是,當自己擁有了那個力量時,自己將會變成讓別人哭泣的人,這一點千萬不要忘記。by 阿斯蘭‧薩拉
*請在拭去眼前的淚水後贍望前路,請在發出悲慟的呼喊後聽一下對方的說話。by 米亞
!!機動戰艦ナデシコ
*所謂的正義,是最大公因數的利益;所謂的歷史,是人類任意編成的老帳本。by 星野琉璃
*海水浴場的三大名產,就是這個粉粉的咖哩、難吃的拉麵和熔化的刨冰!by 瓜佃星也
*口口聲聲說是很重要的回憶,自己卻會擅自改編記憶。by 瓜佃星也
*為了守護什麼而戰是理所當然,但是,對方會死啊;只因為有戰鬥的理由,這就是英雄嗎?by 天河明人
*因為有現在,所以有未來,過去的未來的開始。by 星野琉璃
*LET'S GEKIGER IN !!!!!!!by 激鋼人3
!!機動戰艦ナデシコ-The prince of darkness
*有些事即使瞭解了也沒辦法想的開。by 保美
!!驚爆危機
*產生感情會影響判斷。by 相良宗介
*我不是偏執狂,我是專家!by 相良宗介
*不跟恐佈份子談判,這是國際常識。by 相良宗介
*再爛的作品,只要全部角色在最後一集死光光,就會成為名作。by 相良宗介
*Fumofu!by 蹦太
!!神劍闖江湖
*人都死了,還有什麼幸福可言!by 緋村劍心
*我不需要防禦!防禦、守護,對我都沒有意義!因為,我唯一想守護的東西,已經被你奪走了!by 雪代緣
!!海賊王
*是男人就要原諒女人的謊言。by 香吉士
!!將太的壽司
*的確,那條卷壽司的確是六百條之中的唯一一條;但是,對吃那條壽司的人而言,那條海苔卷便是一切。by 鳳壽司
!!火鳳燎原
*疑人不用,用人不疑。by 曹操
*不明小義,將來如何明大義!by 關羽
*商場上,萬千殷商獲利不如奸商,慨嘆公道何在?戰場上,萬千士卒性命不如高官,慨嘆人命何價?by 陳某
!!軒轅劍貳
*也許妖魔指的不是種族,而是心吧!by 何然
!!軒轅劍外傳──楓之舞
*「名」不會比「義」來的重要,記得把「義」帶著就好。by 墨子
*記得神醫扁鵲說過:「感情不要壓抑,適當紓解有益健康。」…扁鵲真是聰明,我也覺得我很健康。by 輔子徹
!!軒轅劍參──雲和山的彼端
*人類永遠無法逃脫這無盡之痛苦和恐懼;既然逃不了,那最好的辦法就是成為恐懼本身,就能永不恐懼。by 康納里士
*要帶來恐懼,就需消滅知識和歪曲知識;要消滅知識容易,但要歪曲知識,就需先了解知識。by 康納里士
*強烈的復仇之火,用了多少淚水才漸漸澆熄,不料今天仇人卻自己送上門來。by 卡瑪
*把你所有的東西,賣給需要它的人,不是做生意;把你所沒有的賣給不需要它的人,才算是生意。by 貝魯特商店老闆
*與其拯救會毀滅的肉體,還不如拯救人的心。by 李靖
!!軒轅劍參外傳──天之痕
*人間有情,更勝天道。by古月聖
*世外悠悠隔人間,不忍悽悽亂世煙;慨懷瀟瀟任風逝,雲靄冉冉繞仙山。by 古月聖
!!軒轅劍肆──黑龍舞兮雲飛揚
*不到最後一刻,又有誰願意放棄自己的夢呢?有夢想並沒有錯,但是強迫別人活在你的夢裡,那就是錯了。by 輔子徹
!!軒轅劍外傳──蒼之濤
*古來「王道」就是構陷對手的最好名目,每當有力量的一方,想打擊對方,卻苦於找不到好藉口理由,這時只要隨便指責對方違被了誰也弄不清的「王道」,自己再怎麼理虧,也立刻成了「王道」的捍衛者by 晉文公
*拓展版圖和侵略,兩者完全是同一回事,每一次版圖擴張的背後,都有多少的血和淚?by 慕容詩
!!銀魂
*JUST WE 就是 JUST WE ,既不偉大也不卑微!by 蝮蛇萬藏
*對不起,我想問個路,請問到地獄怎麼走?by 伊莉莎白
*不去何護該保護的東西而苟延殘喘,那跟死了沒有區別。by 志村新八
*每天早上和早餐一起作好死的覺悟才是男子漢。by 桂小太郎
*不是為了斬斷敵人,而是為了斬斷弱小的自己;不是為了保護自己,而是為了保護自己的靈魂。by 吉田松陽
!!銀河英雄傳說
*國家、組織、團體──怎麼稱呼都好,要團結人類的集團,有一樣絕對必要的事物…是「敵人」。by 希爾德‧馮‧瑪琳道夫
*用筆可以控告幾百年前的獨裁者,甚至幾千年前的暴君。劍不能讓歷史倒流,但筆卻可以。by 楊威利
*如果約定了就能獲勝,那麼,我也希望常常約定……by 楊威利
*最壞的專制政治在崩潰之後或許會產生最好的民主政治,但是,最壞的民主政治在垮台之後卻絕不會產生出最好的專制政治,這是一件奇妙的事…by 楊威利
*為了信念的理由而殺人,其實比為金錢而殺人更下等。因為金錢至少具有萬人共通的價值,但是信念的價值則僅限定於本人才有。by 楊威利
*預測未來、體驗現在、回想過去,若把這三者串聯起來,往往會有不尋常的驚竦伴隨而至。充滿喜悅的驚竦,充滿恐怖的驚竦,充滿憤怒的驚竦,其中最值得畏戒警惕的無異是最後一種。有許多的人將之改稱為「後悔」……by E‧J‧Mackenzie
*傳說結束了,歷史才正要開始。
!!最終兵器彼女
*世界上沒有不殺人的兵器。by 千瀨
*有優秀的頭腦就可以停止戰爭嗎?by 美月
*壽命算是一種承諾嗎?壽命是神對生物的一種承諾嗎?那在這顆星球上,無法履行承諾,甚至連承諾都不知道,就喪失生命的「不幸」生物,不就到處都是了嗎?by 修次
*沒有承諾不代表可悲,更不是不幸,人沒有那麼悲情。沒什麼好可憐的。生物就是生物,在地球上的地位一律平等;就算生命的出生到結束只佔地球壽命的億萬分之一,他還是在地球的歷史當中佔有一席之地。當然佔有一席之地。嬰兒之所以會哭,就是要向世人證明他的存在。by 千瀨
!!小叮噹X (同人作品)
*萬事萬物都有它一個道理,就算你有道具,也不能去改變。這,你以後慢慢就會懂的。by 小叮噹
*…我分得很清楚,吃完銅鑼燒抽完菸該幹啥還是幹啥,所以我根本不必戒什麼。by 小叮噹
!!糟糕小叮噹 (同人作品)
*大雄,男人一定會遇上不得不拔槍的時候。但也有無法扣下板機的傢伙存在。你要成為能扣下板機的男人。by 小叮噹
!!瀨戶的花嫁
*雖然寫作「仁俠」,但是唸作「人魚」!by 瀨戶燦
!!魔法少女まどか.マギカ
*Don't forget. Always, somewhere, someone is fighting for you - As long as you remember her, you are not alone.

!from Movies and Dramas
!!プロポーズ大作戰(求婚大作戰)
*人類在歷史上做的最出色的一件事情就是找藉口。by 教堂妖精
*如果連後悔的原因也不知道,那就談不上後悔兩個字了。by 教堂妖精
*看不見的告白,就像觀光地石碑上寫的俳句一樣。by 教堂妖精
*難以言表的感激等於沒有感激。by 教堂妖精
*說出你的願望吧!否則就不會實現;去尋找吧!否則就不會發現;去敲門吧!否則就不會為你而開。by 教堂妖精
*明天再做的人是笨蛋。by 吉田太志
!!霍元甲
*活著,從來都不是一個人的事情。by 霍元甲
!!Just Like Heaven(宛如天堂)
*酒是上帝賜給這個艱難世界的潤滑劑,它讓男人勇敢,女人淫蕩。
!!STAR WARS
*恐懼帶來憤怒,憤怒帶來仇恨,仇恨帶來災難。by 尤達
*May the force be with you.
!!龍櫻
*知道怎麼才能讓一個人變強大嗎?首先要明白自己有多麼弱小。by 櫻木建二

!from The Real World...
!!中國
*話說天下之勢,合久必分、分久必合。by 羅貫中
*太山不讓土壤,故能成其大;河海不擇細流,故能就其深;王者不卻眾庶,故能明其德。by 李斯
*鳳凰上擊九千里,絕雲霓,負蒼天,足亂浮雲,翱翔乎杳冥之上。夫藩籬之鷃,豈能與之料天地之高哉?鯤魚朝發崑崙之墟,曝鰭於碣石,暮宿於孟諸。夫尺澤之鯢,豈能與之量海江之大哉?by 孟軻
*夫以銅為鏡,可以正衣冠;以古為鏡,可以知興替;以人為鏡,可以明得失。朕常保此三鏡,以防己過。by 李世民
*南八,男兒死耳,不可為不義屈!by 張巡
*以前脫掉的衣服,我要一件一件的穿回來。by 舒淇
*做人處事,臉皮得像輪胎一樣耐刮、耐磨,用謙遜的態度來待人處事,才能趨吉避凶,保百年身。by 倪敏然
*無知常常是注視在指點的手指,而不是手指所指示的方向。by 西藏諺語
*生命是一樁太好的東西,好到你無論選擇什麼方式渡過,都像是一種浪費。by 張曉風
*人一天只有二十一個小時,另外三小時是要思考的。by 傅斯年
*你不能計較早晨或黃昏,一天二十四小時都是你的工作時間。by 李振道
*長的是苦難,短的是人生。by 張愛玲
!!日本
*不受制於 天‧地‧人 !by 清津為信
*敵人在本能寺!by 明智光秀
*吉野山峰雪審慎,君訣別身飄零,朝夕思念腸九轉,相期惟有在夢裏。幸福時光已逝去,往日歡樂不再來,春蠶絲盡燭成灰,此恨綿綿無絕期。by 靜御前
*捨生去戰則生,畏死去戰則死。by 上杉謙信
*井底之蛙,不知大海,卻知天地之高。by 近藤勇
*古來一句,無生無死;萬里雲盡,長江水清。by 日野俊基
*戰事乃守護寶貴之物而戰也;即為寶貴之物而死,亦不可稱敗是也。by 楠木正成
*凡是偉人,必會以某種形式流傳於後世,然後大大影響世人。by 勝海舟
*彈幕是程式設計師的樂園。by ZUN(太田順也)
*死して不朽(ふきゅう)の見込みあらばいつでも死ぬべし;生きて大業(たいぎょう)の見込みあらばいつでも生くべし。(若死能名垂不朽,那隨時都可死去;若生可成就大業,那隨時都該活著。)by 吉田松陰
!!歐洲
*死一個人是個小說,死十個人是個事件,死一百個人是個震撼,死一千個人是個悲劇,死一百萬個人是個數字。by 史達林
*一,機器人不能傷害人類,或是眼見人類受到傷害而不予行動;二,機器人應該遵從人類的指令,除非指令與第一條定律相衝突;三,只要不違反第一和第二定律,機器人必須保護自身的存在。by Isaac Asimov
*道德常常能彌補智慧的缺陷,智慧卻永遠無法填補道德的空白。by Dante Alighieri
*Si vis pacem, para bellum.(要想求得和平,必先越過戰爭。)by 拉丁諺語
*最偉大的想法是簡單的。from 蒼蠅王
*人活著不是為了呼吸,而是為了行動。by 盧梭
*很奇怪,等待你的人總遠不如你所等待的人那麼顯眼。by 尚‧紀侯杜
*Men ought either to be well treated or crushed, injury ought to be of such a kind that one does not fear revenge. by 馬基維利
*L'homme n'est qu'un roseau, le plus faible de la nature,mais c'est un roseau pensant. (Man is a reed, the weakest of nature, but he is a thinking reed.) by Pascal
*當你縮排超過三層以上,你就搞砸了。 by Linus Torvalds
*The choice of a point of view is the initial act of culture. by Ortega y Gasset
*The three great virtues of a programmer: laziness, impatience, and hubris. by Larry Wall
*You did not bear the shame. You Resisted sacrificing your life from freedom, justice and honor. by German Resistance Memorial
*Any fool can write code that a computer can understand.  Good programmers write code that humans can understand. by Martin Fowler
*The road to hell is paved with good intentions. by Friedrich August von Hayek
*Honi soit qui mal y pense (Shame on him who thinks evil of it. 心懷邪念者蒙羞。) by Edward III
*Darkness cannot drive out darkness; only light can do that. Hate cannot drive out hate; only love can do that. by Martin Luther King, Jr.

!from some where...
*追到手之前,男生甚麼都可以,追到手就隨便了。如果跟我在一起之如果跟我在一起之前都不懂得節制,那在一起後又有甚麼希望可言?
*程式可以中文化,知識不行。
*人生不用太享受,只要吃個餅就會飽了。 by 附中蛋餅伯
*不離不棄,被當北七。
*開會是為了要改變歷史。
*科學,是在你猜對了之後所作的事。
*Linux is only free if your time has no value.
*Forgiveness is between them and God. It's my job to arrange the meeting.
*你無法把香蕉皮罵進垃圾桶的。
*與其成為停屍間最健康的屍體,不如成為停屍間最開心的屍體,吃吧!
*There are only two hard problems in Computer Science: cache invalidation, naming things, and off-by-one errors.
{{{
out/target/product/<product name>/system/lib/libasus-ril.so
}}}
Main page: http://www.emacswiki.org/emacs/RecreateScratchBuffer
!Introduction
The scratch buffer is useful for “notes you don’t want to save, and for Lisp evaluation”.

!Solution
Just disable killing scratch buffer.
{{{
(defun unkillable-scratch-buffer ()
	(if (equal (buffer-name (current-buffer)) "*scratch*")
	    (progn
	      (delete-region (point-min) (point-max))
	      nil)
	  t))

(add-hook 'kill-buffer-query-functions 'unkillable-scratch-buffer)
}}}
at {{{/frameworks/base/libs/utils/RefBase.cpp}}}

The {{{sp}}} means "Strong Pointer"

Use {{{trackMe}}} to debug.
!Tools
!!Package Manager: RVM
[[Install RVM]]
!Introduction
Sass is an extension of CSS3, adding nested rules, variables, mixins, selector inheritance, and more. It’s translated to well-formatted, standard CSS using the command line tool or a web-framework plugin.

http://sass-lang.com

兩種:
*Scss: 寫起來像 CSS
*Sass: 寫起來像 Ruby
支援巢狀
支援 import
支援數學(wryyy)

無痛轉移
{{{
sass-convert -F css -T scss your.css new.scss
}}}
甚至還有 folder 版本,一次轉換同個 folder 下的 css,甚至還能監視 change 作即時 comiple

debug_info: FireSass(因為 FireBug 不援援 Sass,只支援 CSS;但老實說效果有限)
!Regular Expression
*[[Using pattern matching with regular expressions in Scala]]

!Multiplexing
*[[Scala Actors: A Short Tutorial]]
!Introduction
With the advent of multi-core processors concurrent programming is becoming indispensable. Scala's primary concurrency construct is actors. Actors are basically concurrent processes that communicate by exchanging messages. Actors can also be seen as a form of active objects where invoking a method corresponds to sending a message.

The Scala Actors library provides both asynchronous and synchronous message sends (the latter are implemented by exchanging several asynchronous messages). Moreover, actors may communicate using futures where requests are handled asynchronously, but return a representation (the future) that allows to await the reply.

This tutorial is mainly designed as a walk-through of several complete example programs that can be readily compiled and run using Scala 2.4 or newer.


!First Example
Our first example consists of two actors that exchange a bunch of messages and then terminate. The first actor sends "ping" messages to the second actor, which in turn sends "pong" messages back (for each received "ping" message one "pong" message).

We start off by defining the messages that are sent and received by our actors. In this case, we can use singleton objects (in more advanced programs, messages are usually parameterized). Since we want to use pattern matching, each message is a case object:
{{{
case object Ping
case object Pong
case object Stop
}}}
The ping actor starts the message exchange by sending a Ping message to the pong actor. The Pong message is the response from the pong actor. When the ping actor has sent a certain number of Ping messages, it sends a Stop message to the pong actor.

All classes, objects and traits of the Scala actors library reside in the scala.actors package. From this package we import the Actor class that we are going to extend to define our custom actors. Furthermore, we import all members of the Actor object since it contains many useful actor operations:
{{{
import scala.actors.Actor
import scala.actors.Actor._
}}}
Actors are normal objects that are created by instantiating subclasses of the Actor class. We define the behavior of ping actors by subclassing Actor and implementing its abstract act method:
{{{
class Ping(count: Int, pong: Actor) extends Actor {
  def act() {
    var pingsLeft = count - 1
    pong ! Ping
    while (true) {
      receive {
        case Pong =>
          if (pingsLeft % 1000 == 0)
            Console.println("Ping: pong")
          if (pingsLeft > 0) {
            pong ! Ping
            pingsLeft -= 1
          } else {
            Console.println("Ping: stop")
            pong ! Stop
            exit()
          }
      }
    }
  }
}
}}}
The number of Ping messages to be sent and the pong actor are passed as arguments to the constructor. The call to the receive method inside the infinite loop suspends the actor until a Pong message is sent to the actor. In that case the message is removed from the actor's mailbox and the corresponding action on the right side of the arrow is executed.

In the case where pingsLeft is greater than zero we send a Ping message to pong using the send operator !, and decrement the pingsLeft counter. If the pingsLeft counter has reached zero, we send a Stop message to pong, and terminate the execution of the current actor by calling {{{exit()}}}.

The class for our pong actor is defined similarly:
{{{
class Pong extends Actor {
  def act() {
    var pongCount = 0
    while (true) {
      receive {
        case Ping =>
          if (pongCount % 1000 == 0)
            Console.println("Pong: ping "+pongCount)
          sender ! Pong
          pongCount = pongCount + 1
        case Stop =>
          Console.println("Pong: stop")
          exit()
      }
    }
  }
}
}}}
There is one interesting point to notice, however. When receiving a Ping message, a Pong message is sent to the sender actor, which is not defined anywhere in our class! In fact, it is a method of the Actor class. Using sender, one can refer to the actor that sent the message that the current actor last received. This avoids having to explicitly pass the sender as arguments to messages.

After having defined our actor classes, we are now ready to create a Scala application that uses them:
{{{
object pingpong extends Application {
  val pong = new Pong
  val ping = new Ping(100000, pong)
  ping.start
  pong.start
}
}}}
Analogous to Java threads, actors have to be started by calling their start method.


!Let's run it!

The complete example is included in the Scala distribution under doc/scala-devel/scala/examples/actors/pingpong.scala. Here is how you compile and run it:
{{{
$ scalac pingpong.scala
$ scala -cp . examples.actors.pingpong
Pong: ping 0
Ping: pong
Pong: ping 1000
Ping: pong
Pong: ping 2000
...
Ping: stop
Pong: stop
}}}


!Make it Thread-less!
Actors are executed on a thread pool. Initially, there are 4 worker threads. The thread pool grows if all worker threads are blocked but there are still remaining tasks to be processed. Ideally, the size of the thread pool corresponds to the number of processor cores of the machine.

When actors call thread-blocking operations, such as receive (or even wait), the worker thread that is executing the current actor (self) is blocked. This means basically that the actor is represented as a blocked thread. Depending on the number of actors you want to use, you might want to avoid this, since most JVMs cannot handle more than a few thousand threads on standard hardware.

Thread-blocking operations can be avoided by using react to wait for new messages (the event-based pendant of receive). However, there is a (usually small) price to pay: react never returns. In practice, this means that at the end of a reaction to a message, one has to call some function that contains the rest of the actor's computation. Note that using react inside a while loop does not work! However, since loops are common there is special library support for it in form of a loop function. It can be used like this:
{{{
loop {
  react {
    case A => ...
    case B => ...
  }
}
}}}
Note that react calls can be nested. This allows to receive several messages in sequence, like this:
{{{
react {
  case A => ...
  case B => react { // if we get a B we also want a C
    case C => ...
  }
}
}}}

To make our ping and pong actors thread-less, it suffices to simply replace while (true) with loop, and receive with react. For example, here is the modified act method of our pong actor:
{{{
def act() {
  var pongCount = 0
  loop {
    react {
      case Ping =>
        if (pongCount % 1000 == 0)
          Console.println("Pong: ping "+pongCount)
        sender ! Pong
        pongCount = pongCount + 1
      case Stop =>
        Console.println("Pong: stop")
        exit()
    }
  }
}
}}}


!Second Example
In this example, we are going to write an abstraction of producers which provide a standard iterator interface to retrieve a sequence of produced values.

Specific producers are defined by implementing an abstract produceValues method. Individual values are generated using the produce method. Both methods are inherited from class Producer. For example, a producer that generates the values contained in a tree in pre-order can be defined like this:
{{{
class PreOrder(n: Tree) extends Producer[int] {
  def produceValues = traverse(n)
  def traverse(n: Tree) {
    if (n != null) {
      produce(n.elem)
      traverse(n.left)
      traverse(n.right)
    }
  }
}
}}}

Producers are implemented in terms of two actors, a producer actor, and a coordinator actor. Here is how we can implement the producer actor:
{{{
abstract class Producer[T] {
  protected def produceValues: unit

  protected def produce(x: T) {
    coordinator ! Some(x)
    receive { case Next => }
  }

  private val producer: Actor = actor {
    receive {
      case Next =>
        produceValues
        coordinator ! None
    }
  }
  ...
}
}}}
Note how the producer actor is defined! This time we did not bother to create an extra subclass of Actor and implement its act method. Instead, we simply define the actor's behavior inline using the actor function. Arguably, this is much more concise! Moreover, actors defined using actor are started automatically<nowiki>--</nowiki>no need to invoke their start method!

So, how does the producer work? When receiving a Next message, it runs the (abstract) produceValues method, which, in turn, calls the produce method. This results in sending a sequence of values, wrapped in Some messages, to the coordinator. The sequence is terminated by a None message. Some and None are the two cases of Scala's standard Option class.

The coordinator synchronizes requests from clients and values coming from the producer. We can implement it like this:
{{{
private val coordinator: Actor = actor {
  loop {
    react {
      case Next =>
        producer ! Next
        reply {
          receive { case x: Option[_] => x }
        }
      case Stop => exit('stop)
    }
  }
}
}}}
Note that inside the handler for the Next message, we use reply to return a received Option value to some requesting actor. We are going to explain this in the next section, so stay tuned...


!The Iterator Interface

We want to make producers usable as normal iterators. For this, we implement an iterator method that returns<nowiki>--surprise!--</nowiki>an iterator. Its hasNext and next methods send messages to the coordinator actor to accomplish their task. Take a look:
{{{
def iterator = new Iterator[T] {
  private var current: Any = Undefined
  private def lookAhead = {
    if (current == Undefined) current = coordinator !? Next
    current
  }

  def hasNext: boolean = lookAhead match {
    case Some(x) => true
    case None => { coordinator ! Stop; false }
  }

  def next: T = lookAhead match {
    case Some(x) => current = Undefined; x.asInstanceOf[T]
  }
}
}}}

We use a private lookAhead method to implement the iterator logic. As long as the next value has not yet been looked-up, the current variable has value Undefined which is simply a place-holder object:
{{{
private val Undefined = new Object
}}}
The interesting bit is in the lookAhead method. When the current value is Undefined it means we have to get hold of the next value. For this, we use the synchronous message send operator !?. It sends the Next message to the coordinator, but instead of returning like a normal (asynchronous) message send, it waits for a reply from the coordinator. The reply is the return value of !?. A message that was sent using !? is replied to using reply. Note that simply sending a message to sender does not work! That's because !? waits to receive a message from a private reply channel instead of the mailbox. This is necessary to distinguish "true" replies from "fake" ones resulting from old messages that happen to be in the mailbox.

The producers example is also included in the Scala distribution under doc/scala-devel/scala/examples/actors/producers.scala.
!Introduction
Scrapy is a fast high-level screen scraping and web crawling framework, used to crawl websites and extract structured data from their pages.
http://scrapy.org/
<<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>
COLDTURNIP's programing notebook
Dev. CDIP
/***
!General
***/
/*{{{*/
body {
 background: #EDEDED;
}

 #contentWrapper{
 background: #fff;
 border:1px solid #DDD;
 margin: 0 1em;
 padding:0;

height:1%;
}
/*}}}*/


/***
!Links
***/
/*{{{*/
a,
a.tiddlyLink,
a.button,
a.externalLink,
#sidebarOptions .sliderPanel a{
 color: #1D65BC;
 text-decoration: none;
 background: transparent;
 border: 0;
}

a:hover,
a.tiddlyLink:hover,
a.button:hover,
a.externalLink:hover,
#sidebarOptions .sliderPanel a:hover
{
 border: 0;
 color: #1D65BC;
 text-decoration: underline;
background:transparent;
}
/*}}}*/

/***
!Header
***/
/*{{{*/
.gradient {margin-top:1em; background:#3371A3;}

.titleLine{padding: 30px 40px 15px 30px;}

.titleLine a:hover{color:#fff; border-bottom:1px dotted #eee; text-decoration:none;}

.titleLine a{color:#fff; border-bottom:1px dotted #ccc;}

.siteTitle {
 font-size: 2.2em;
 font-weight: bold;
 color:#fff;
}

.siteSubtitle {
 font-size: 1.0em;
 display: block;
 margin: .3em auto 1em;
color:#fff;
}
/*}}}*/

/***
!TopMenu
***/
/*{{{*/
#topMenu br {display:none; }
#topMenu { background: #3371A3; font-size:1em; }
#topMenu { padding:5px 32px; }
#topMenu .button, #topMenu .tiddlyLink, #topMenu .externalLink {
 margin-left:0.1em; margin-right:0.1em;
 padding:0.5em;
 color:white; font-weight:bold;
}
#topMenu a.button:hover, #topMenu a.tiddlyLink:hover { background:#fff; color:#333; text-decoration:none;}

 
/*}}}*/

/***
!Display
***/
/***
!!!Display General
***/
/*{{{*/


#displayArea { margin: 0em 15.7em 0em 0em; }

#displayFooter {
 clear: both;
}
/*}}}*/
/***
!!!Tiddler
***/
/*{{{*/
.tiddler {margin-bottom:1em; padding-bottom:1em;}

.tiddler {padding-left:1.5em;}

.title {color:#333; font-size:1.8em; border-bottom:1px solid #333; padding-bottom:0.3px; text-shadow: #999 1px 1px;}

.subtitle { font-size:90%; color:#bbb; padding-left:0.25em; margin-top:0.1em; }

.shadow .title {
 color: #aaa;
}

h1 {
  color: #333; background: transparent; padding-bottom:2px; border-bottom: 1px dotted #ccc;
}

h2,h3,h4,h5 { color: #333; background: transparent; padding-bottom:2px; border-bottom: none; }

* html .viewer pre {
 margin-left: 0em; 
}



.viewer hr {
 border: 0;
 border-top: solid 1px #333;
 margin: 0 8em;
 color: #333;
}

.viewer a.button {color:#000; border:1px solid #1D65BC; font-weight:bold;}

.viewer a.button:hover{color:#fff; background:#3371a3; text-decoration:none;}

.tagClear {clear:none;}
/*}}}*/
/***
!!!Editor
***/
/*{{{*/

* html .editor textarea, * html .editor input {
 width: 98%;
}
/*}}}*/







/***
!Sidebar
***/
/*{{{*/
#sidebar{
position:relative;
float:right;
margin-bottom:1em;
display:inline;
width: 16em;
}


.toolbar .button {color:#bbb; border:none;}
.toolbar .button:hover, .toolbar .highlight, .toolbar .marked, .toolbar a.button:active {background:transparent; color:#111; border:none; text-decoration:underline;}


.tiddler {border-bottom:3px solid #EEF1F3; padding-bottom:2em; padding-top:0em;}
.title {border-bottom:none; margin-right:8em;}

.h1, .h2, .h3, .h4, .h5 { color: #333; background: transparent; padding-bottom:2px; border-bottom: none; }

#sidebar {background: #EBEEF1 ; right:0;}



#displayFooter {
 clear: both;
}

#tiddlerDisplay{padding-top:1em;}



#sidebar .tabSelected, #sidebar .tabSected:hover {
 color: #000;
 background: #dbdee3;
 border-top: solid 1px #B2B6BE;
 border-left: solid 1px #B2B6BE;
 border-right: solid 1px #B2B6BE;
 border-bottom:solid 1px #dbdee3 !important;
padding-bottom:1px;
text-decoration:none;
}

#sidebarOptions, #sidebarTabs {border-left: 1px solid #B2B6BE;}
#sidebarTabs {border-bottom: 1px solid #B2B6BE;}



#sidebar .tabUnselected, #sidebar .tabUnselected:hover {
color: #F0F3F5;
background: #B2B6BE ;
border: solid 1px #B2B6BE ;
padding-bottom:1px;
}

#sidebarTabs .tabContents {border:none; background:#DBDEE3; }

#sidebarTabs .tabContents {border-top:1px solid #B2B6BE;}

#sidebarTabs .tabContents .tabContents {border-left:1px solid #b2b6be;}









.viewer pre, .viewer code {
border: 1px solid #B2B6BE;
background: #EBEEF1;} 

#sidebarOptions .sliderPanel {
 background: #EBEEF1; border:none;
}

#sidebarOptions input {
 border: 1px solid #1d65bc;
}

#sidebarOptions input:hover, #sidebarOptions input:active, #sidebarOptions input:focus {
 border: 1px inset #3371a3;
}

.tagging, .tagged {
 border: 1px solid #dbdee3;
 background-color: #ebeef1;
}

.selected .tagging, .selected .tagged {
 background-color: #dbdee3;
 border: 1px solid #B2B6BE;
}

 .tagging .listTitle, .tagged .listTitle {
 color: #bbb;
}

.selected .tagging .listTitle, .selected .tagged .listTitle {
 color: #014; 
}

.tagging .button:hover, .tagged .button:hover {
 border: none; background:transparent; text-decoration:underline; color:#014;
}

.tagged .highlight, .tagged .marked, .tagged a.button:active {text-decoration:underline; background:transparent; color:#014;}

.tagging .button, .tagged .button {
 color:#bbb;
}

.selected .tagging .button, .selected .tagged .button {
 color:#014;
}

.viewer blockquote {
 border-left:7px solid #ebeef1;
}

.viewer table {
 border: 1px solid #3371a3;
}

.viewer th, thead td {
 background: #3371a3;
 border: 1px solid #3371a3;
 color: #fff;
}

.viewer td, .viewer tr {
 border: 1px solid #3371a3;
}

.editor input, .editor textarea {
 border: 1px solid #1d65bc; background:#ebeef1;
}

.editor {padding-top:0.3em;}

.editor textarea:focus, .editor input:focus {
 border: 1px inset #3371a3; background:#fff;
}










.popup {
 background: #3371a3;
 border: 1px solid #333;
}

.popup hr {
 color: #333;
 background: #333;
 border-bottom: 1px;
}

.popup li.disabled {
 color: #333;
}

.popup li a, .popup li a:visited {
 color: #eee;
 border: none;
}

.popup li a:hover {
 background: #3371a3;
 color: #fff;
 border: none;
 text-decoration:underline;
}

.viewer .button:active, .viewer .marked, .viewer .highlight {
color: #fff !important;
background: #3371a3;
border: 0;
}

.button:active {background:#1d65bc; border:0;}

#sidebar .button:active, #sidebar .marked, #sidebar .highlight {color:#014; background:transparent;text-decoration:none}

#messageArea {
 border: 2px dashed #3371a3;
 background: #dbdee3;
 color: #fff;
 font-size:90%;
}

#messageArea .button {
 color: #1d65bc;
 background: #ebeef1;
 text-decoration:none;
 font-weight:bold;
 border:none; 
}

#messageArea a.button {color:#1d65bc;}

#messageArea .button:hover {text-decoration:underline;}

.viewer .tabSelected, .viewer .tabSelected:hover{
 color: #014;
 background: #eee;
 border-left: 1px solid #B2B6BE;
 border-top: 1px solid #B2B6BE;
 border-right: 1px solid #B2B6BE;
}

.viewer .tabUnselected, .viewer .tabUnselected:hover {
 color: #fff;
 background: #B2B6BE;
}

. viewer .tabContents {
 color: #014;
 background: #ebeef1;
 border: 1px solid #B2B6BE;
}

.searchBar {float:right; font-size:0.9em;}
.searchBar .button {display:block; border:none; color:#ccc;}
.searchBar .button:hover{border:none; color:#eee;}

.searchBar input{
 border: 1px inset #1d65bc; background:#dbdee3;
}

.searchBar input:focus {
 border: 1px inset #3371a3; background:#fff;
}

.blog h2, .blog h3, .blog h4{
  margin:0;
  padding:0;
border-bottom:none;
}
.blog {margin-left:1.5em;}  


.blog .excerpt {
  margin:0;
margin-top:0.3em;
  padding: 0;
  margin-left:1em;
  padding-left:1em;
  font-size:90%;
  border-left:1px solid #ddd;
}

#tiddlerWhatsNew h1, #tiddlerWhatsNew h2 {border-bottom:none;}
div[tags~="RecentUpdates"], div[tags~="lewcidExtension"] {margin-bottom: 2em;}


#topMenu .fontResizer {float:right;}

#topMenu .fontResizer .button{border:1px solid #3371A3;}
#topMenu .fontResizer .button:hover {border:1px solid #fff; color:#3371A3;}
#sidebarTabs .txtMainTab .tiddlyLinkExisting {
 font-weight: normal;
 font-style: normal;
}

#sidebarTabs .txtMoreTab .tiddlyLinkExisting {
 font-weight: bold;
 font-style: normal;
}
/*}}}*/

/***
!Editor
***/
/*{{{*/
.editor {
  font-family: monospace;
}
/*}}}*/
{{{
''        ==   '0'           //false
0         ==   ''            //true
0         ==   '0'           //true
false     ==   'false'       //false
false     ==   '0'           //true
false     ==   undefined     //false
false     ==   null          //false
null      ==   undefined     //true
" \t\r\n" ==   0             //true
}}}
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{

// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'devcdip';

// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too

// disable autosave in d3
if (window.location.protocol != "file:")
	config.options.chkGTDLazyAutoSave = false;

// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
	SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
	SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
	OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
	DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
	MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}

// create some shadow tiddler content
merge(config.shadowTiddlers,{

'TspotOptions':[
 "tiddlyspot password:",
 "<<option pasUploadPassword>>",
 ""
].join("\n"),

'TspotControls':[
 "| tiddlyspot password:|<<option pasUploadPassword>>|",
 "| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
 "| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),

'WelcomeToTiddlyspot':[
 "This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
 "<<tiddler TspotControls>>",
 "See also GettingStarted.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),

'TspotSidebar':[
 "<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n")

});
//}}}
!Introduction
Twisted is an event-driven networking engine written in Python.
http://twistedmatrix.com/trac/
*[[開發 Daemon 所需要的初始化動作]]
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 30/09/2011 16:45:08 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . |
| 30/09/2011 16:52:18 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . |
| 11/10/2011 20:47:36 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . |
| 04/11/2011 15:51:13 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . |
| 06/11/2011 04:24:21 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . |
| 19/03/2012 16:33:41 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . |
| 21/11/2012 17:03:06 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . |
| 14/07/2013 21:22:09 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . |
| 05/09/2013 16:19:45 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . | ok |
| 05/09/2013 16:25:04 | COLDTURNIP | [[/|http://devcdip.tiddlyspot.com/]] | [[store.cgi|http://devcdip.tiddlyspot.com/store.cgi]] | . | [[index.html | http://devcdip.tiddlyspot.com/index.html]] | . |
/***
|''Name:''|UploadPlugin|
|''Description:''|Save to web a TiddlyWiki|
|''Version:''|4.1.3|
|''Date:''|Feb 24, 2008|
|''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
|''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
|''Requires:''|PasswordOptionPlugin|
***/
//{{{
version.extensions.UploadPlugin = {
	major: 4, minor: 1, revision: 3,
	date: new Date("Feb 24, 2008"),
	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'
};

//
// Environment
//

if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false;	// true to activate both in Plugin and UploadService
	
//
// Upload Macro
//

config.macros.upload = {
// default values
	defaultBackupDir: '',	//no backup
	defaultStoreScript: "store.php",
	defaultToFilename: "index.html",
	defaultUploadDir: ".",
	authenticateUser: true	// UploadService Authenticate User
};
	
config.macros.upload.label = {
	promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
	promptParamMacro: "Save and Upload this TiddlyWiki in %0",
	saveLabel: "save to web", 
	saveToDisk: "save to disk",
	uploadLabel: "upload"	
};

config.macros.upload.messages = {
	noStoreUrl: "No store URL in parmeters or options",
	usernameOrPasswordMissing: "Username or password missing"
};

config.macros.upload.handler = function(place,macroName,params) {
	if (readOnly)
		return;
	var label;
	if (document.location.toString().substr(0,4) == "http") 
		label = this.label.saveLabel;
	else
		label = this.label.uploadLabel;
	var prompt;
	if (params[0]) {
		prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0], 
			(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
	} else {
		prompt = this.label.promptOption;
	}
	createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
};

config.macros.upload.action = function(params)
{
		// for missing macro parameter set value from options
		if (!params) params = {};
		var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
		var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
		var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
		var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
		var username = params[4] ? params[4] : config.options.txtUploadUserName;
		var password = config.options.pasUploadPassword; // for security reason no password as macro parameter	
		// for still missing parameter set default value
		if ((!storeUrl) && (document.location.toString().substr(0,4) == "http")) 
			storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
		if (storeUrl.substr(0,4) != "http")
			storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
		if (!toFilename)
			toFilename = bidix.basename(window.location.toString());
		if (!toFilename)
			toFilename = config.macros.upload.defaultToFilename;
		if (!uploadDir)
			uploadDir = config.macros.upload.defaultUploadDir;
		if (!backupDir)
			backupDir = config.macros.upload.defaultBackupDir;
		// report error if still missing
		if (!storeUrl) {
			alert(config.macros.upload.messages.noStoreUrl);
			clearMessage();
			return false;
		}
		if (config.macros.upload.authenticateUser && (!username || !password)) {
			alert(config.macros.upload.messages.usernameOrPasswordMissing);
			clearMessage();
			return false;
		}
		bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password); 
		return false; 
};

config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir) 
{
	if (!storeUrl)
		return null;
		var dest = bidix.dirname(storeUrl);
		if (uploadDir && uploadDir != '.')
			dest = dest + '/' + uploadDir;
		dest = dest + '/' + toFilename;
	return dest;
};

//
// uploadOptions Macro
//

config.macros.uploadOptions = {
	handler: function(place,macroName,params) {
		var wizard = new Wizard();
		wizard.createWizard(place,this.wizardTitle);
		wizard.addStep(this.step1Title,this.step1Html);
		var markList = wizard.getElement("markList");
		var listWrapper = document.createElement("div");
		markList.parentNode.insertBefore(listWrapper,markList);
		wizard.setValue("listWrapper",listWrapper);
		this.refreshOptions(listWrapper,false);
		var uploadCaption;
		if (document.location.toString().substr(0,4) == "http") 
			uploadCaption = config.macros.upload.label.saveLabel;
		else
			uploadCaption = config.macros.upload.label.uploadLabel;
		
		wizard.setButtons([
				{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption, 
					onClick: config.macros.upload.action},
				{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
				
			]);
	},
	options: [
		"txtUploadUserName",
		"pasUploadPassword",
		"txtUploadStoreUrl",
		"txtUploadDir",
		"txtUploadFilename",
		"txtUploadBackupDir",
		"chkUploadLog",
		"txtUploadLogMaxLine"		
	],
	refreshOptions: function(listWrapper) {
		var opts = [];
		for(i=0; i<this.options.length; i++) {
			var opt = {};
			opts.push();
			opt.option = "";
			n = this.options[i];
			opt.name = n;
			opt.lowlight = !config.optionsDesc[n];
			opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
			opts.push(opt);
		}
		var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
		for(n=0; n<opts.length; n++) {
			var type = opts[n].name.substr(0,3);
			var h = config.macros.option.types[type];
			if (h && h.create) {
				h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
			}
		}
		
	},
	onCancel: function(e)
	{
		backstage.switchTab(null);
		return false;
	},
	
	wizardTitle: "Upload with options",
	step1Title: "These options are saved in cookies in your browser",
	step1Html: "<input type='hidden' name='markList'></input><br>",
	cancelButton: "Cancel",
	cancelButtonPrompt: "Cancel prompt",
	listViewTemplate: {
		columns: [
			{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
			{name: 'Option', field: 'option', title: "Option", type: 'String'},
			{name: 'Name', field: 'name', title: "Name", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'} 
			]}
};

//
// upload functions
//

if (!bidix.upload) bidix.upload = {};

if (!bidix.upload.messages) bidix.upload.messages = {
	//from saving
	invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
	backupSaved: "Backup saved",
	backupFailed: "Failed to upload backup file",
	rssSaved: "RSS feed uploaded",
	rssFailed: "Failed to upload RSS feed file",
	emptySaved: "Empty template uploaded",
	emptyFailed: "Failed to upload empty template file",
	mainSaved: "Main TiddlyWiki file uploaded",
	mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
	//specific upload
	loadOriginalHttpPostError: "Can't get original file",
	aboutToSaveOnHttpPost: 'About to upload on %0 ...',
	storePhpNotFound: "The store script '%0' was not found."
};

bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
{
	var callback = function(status,uploadParams,original,url,xhr) {
		if (!status) {
			displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
			return;
		}
		if (bidix.debugMode) 
			alert(original.substr(0,500)+"\n...");
		// Locate the storeArea div's 
		var posDiv = locateStoreArea(original);
		if((posDiv[0] == -1) || (posDiv[1] == -1)) {
			alert(config.messages.invalidFileError.format([localPath]));
			return;
		}
		bidix.upload.uploadRss(uploadParams,original,posDiv);
	};
	
	if(onlyIfDirty && !store.isDirty())
		return;
	clearMessage();
	// save on localdisk ?
	if (document.location.toString().substr(0,4) == "file") {
		var path = document.location.toString();
		var localPath = getLocalPath(path);
		saveChanges();
	}
	// get original
	var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
	var originalPath = document.location.toString();
	// If url is a directory : add index.html
	if (originalPath.charAt(originalPath.length-1) == "/")
		originalPath = originalPath + "index.html";
	var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
	var log = new bidix.UploadLog();
	log.startUpload(storeUrl, dest, uploadDir,  backupDir);
	displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
	if (bidix.debugMode) 
		alert("about to execute Http - GET on "+originalPath);
	var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
	if (typeof r == "string")
		displayMessage(r);
	return r;
};

bidix.upload.uploadRss = function(uploadParams,original,posDiv) 
{
	var callback = function(status,params,responseText,url,xhr) {
		if(status) {
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
			displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
			bidix.upload.uploadMain(params[0],params[1],params[2]);
		} else {
			displayMessage(bidix.upload.messages.rssFailed);			
		}
	};
	// do uploadRss
	if(config.options.chkGenerateAnRssFeed) {
		var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
		var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
		var rssString = generateRss();
		// no UnicodeToUTF8 conversion needed when location is "file" !!!
		if (document.location.toString().substr(0,4) != "file")
			rssString = convertUnicodeToUTF8(rssString);	
		bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
	} else {
		bidix.upload.uploadMain(uploadParams,original,posDiv);
	}
};

bidix.upload.uploadMain = function(uploadParams,original,posDiv) 
{
	var callback = function(status,params,responseText,url,xhr) {
		var log = new bidix.UploadLog();
		if(status) {
			// if backupDir specified
			if ((params[3]) && (responseText.indexOf("backupfile:") > -1))  {
				var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
				displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
			}
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
			displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
			store.setDirty(false);
			log.endUpload("ok");
		} else {
			alert(bidix.upload.messages.mainFailed);
			displayMessage(bidix.upload.messages.mainFailed);
			log.endUpload("failed");			
		}
	};
	// do uploadMain
	var revised = bidix.upload.updateOriginal(original,posDiv);
	bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
};

bidix.upload.httpUpload = function(uploadParams,data,callback,params)
{
	var localCallback = function(status,params,responseText,url,xhr) {
		url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
		if (xhr.status == 404)
			alert(bidix.upload.messages.storePhpNotFound.format([url]));
		if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
			alert(responseText);
			if (responseText.indexOf("Debug mode") >= 0 )
				responseText = responseText.substring(responseText.indexOf("\n\n")+2);
		} else if (responseText.charAt(0) != '0') 
			alert(responseText);
		if (responseText.charAt(0) != '0')
			status = null;
		callback(status,params,responseText,url,xhr);
	};
	// do httpUpload
	var boundary = "---------------------------"+"AaB03x";	
	var uploadFormName = "UploadPlugin";
	// compose headers data
	var sheader = "";
	sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
	sheader += uploadFormName +"\"\r\n\r\n";
	sheader += "backupDir="+uploadParams[3] +
				";user=" + uploadParams[4] +
				";password=" + uploadParams[5] +
				";uploaddir=" + uploadParams[2];
	if (bidix.debugMode)
		sheader += ";debug=1";
	sheader += ";;\r\n"; 
	sheader += "\r\n" + "--" + boundary + "\r\n";
	sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
	sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
	sheader += "Content-Length: " + data.length + "\r\n\r\n";
	// compose trailer data
	var strailer = new String();
	strailer = "\r\n--" + boundary + "--\r\n";
	data = sheader + data + strailer;
	if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
	var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
	if (typeof r == "string")
		displayMessage(r);
	return r;
};

// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
{
	if (!posDiv)
		posDiv = locateStoreArea(original);
	if((posDiv[0] == -1) || (posDiv[1] == -1)) {
		alert(config.messages.invalidFileError.format([localPath]));
		return;
	}
	var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
				store.allTiddlersAsHtml() + "\n" +
				original.substr(posDiv[1]);
	var newSiteTitle = getPageTitle().htmlEncode();
	revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
	revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
	revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
	revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
	revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
	return revised;
};

//
// UploadLog
// 
// config.options.chkUploadLog :
//		false : no logging
//		true : logging
// config.options.txtUploadLogMaxLine :
//		-1 : no limit
//      0 :  no Log lines but UploadLog is still in place
//		n :  the last n lines are only kept
//		NaN : no limit (-1)

bidix.UploadLog = function() {
	if (!config.options.chkUploadLog) 
		return; // this.tiddler = null
	this.tiddler = store.getTiddler("UploadLog");
	if (!this.tiddler) {
		this.tiddler = new Tiddler();
		this.tiddler.title = "UploadLog";
		this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
		this.tiddler.created = new Date();
		this.tiddler.modifier = config.options.txtUserName;
		this.tiddler.modified = new Date();
		store.addTiddler(this.tiddler);
	}
	return this;
};

bidix.UploadLog.prototype.addText = function(text) {
	if (!this.tiddler)
		return;
	// retrieve maxLine when we need it
	var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
	if (isNaN(maxLine))
		maxLine = -1;
	// add text
	if (maxLine != 0) 
		this.tiddler.text = this.tiddler.text + text;
	// Trunck to maxLine
	if (maxLine >= 0) {
		var textArray = this.tiddler.text.split('\n');
		if (textArray.length > maxLine + 1)
			textArray.splice(1,textArray.length-1-maxLine);
			this.tiddler.text = textArray.join('\n');		
	}
	// update tiddler fields
	this.tiddler.modifier = config.options.txtUserName;
	this.tiddler.modified = new Date();
	store.addTiddler(this.tiddler);
	// refresh and notifiy for immediate update
	story.refreshTiddler(this.tiddler.title);
	store.notify(this.tiddler.title, true);
};

bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir,  backupDir) {
	if (!this.tiddler)
		return;
	var now = new Date();
	var text = "\n| ";
	var filename = bidix.basename(document.location.toString());
	if (!filename) filename = '/';
	text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
	text += config.options.txtUserName + " | ";
	text += "[["+filename+"|"+location + "]] |";
	text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
	text += uploadDir + " | ";
	text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
	text += backupDir + " |";
	this.addText(text);
};

bidix.UploadLog.prototype.endUpload = function(status) {
	if (!this.tiddler)
		return;
	this.addText(" "+status+" |");
};

//
// Utilities
// 

bidix.checkPlugin = function(plugin, major, minor, revision) {
	var ext = version.extensions[plugin];
	if (!
		(ext  && 
			((ext.major > major) || 
			((ext.major == major) && (ext.minor > minor))  ||
			((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
			// write error in PluginManager
			if (pluginInfo)
				pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
			eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
	}
};

bidix.dirname = function(filePath) {
	if (!filePath) 
		return;
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(0, lastpos);
	} else {
		return filePath.substring(0, filePath.lastIndexOf("\\"));
	}
};

bidix.basename = function(filePath) {
	if (!filePath) 
		return;
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("#")) != -1) 
		filePath = filePath.substring(0, lastpos);
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(lastpos + 1);
	} else
		return filePath.substring(filePath.lastIndexOf("\\")+1);
};

bidix.initOption = function(name,value) {
	if (!config.options[name])
		config.options[name] = value;
};

//
// Initializations
//

// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);

// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");

//optionsDesc
merge(config.optionsDesc,{
	txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
	txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
	txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
	txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
	txtUploadUserName: "Upload Username",
	pasUploadPassword: "Upload Password",
	chkUploadLog: "do Logging in UploadLog (default: true)",
	txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
});

// Options Initializations
bidix.initOption('txtUploadStoreUrl','');
bidix.initOption('txtUploadFilename','');
bidix.initOption('txtUploadDir','');
bidix.initOption('txtUploadBackupDir','');
bidix.initOption('txtUploadUserName','');
bidix.initOption('pasUploadPassword','');
bidix.initOption('chkUploadLog',true);
bidix.initOption('txtUploadLogMaxLine','10');


// Backstage
merge(config.tasks,{
	uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
});
config.backstageTasks.push("uploadOptions");


//}}}

First, let’s import Scala’s regex package:
{{{
import scala.util.matching.Regex
}}}
Now we declare a regular expression to match against. We can do this one of two ways:
{{{
val LogEntry = new Regex("""Completed in (\d+)ms \(View: (\d+), DB: (\d+)\) \| (\d+) OK \[http://app.domain.com(.*)\?.*""")
}}}
We use triple quotes here to signify that I am creating a raw string. A raw string means that I do not need to escape characters like the \ character. If I didn't do this, I'd be forced to use strings like "\\d+". Believe it or not, that extra slash throws me off. Just goes to show that I have written way too many parsers.

Alternatively, we can declare a new Regex by doing this:
{{{
val LogEntry = """Completed in (\d+)ms \(View: (\d+), DB: (\d+)\) \| (\d+) OK \[http://app.domain.com(.*)\?.*""".r
}}}
Strings have a method called "r", which will convert it to a Regex object. I'm not sold on this syntax at the moment, since it doesn't play well with eyeball scans, but I'm putting it here for those folks that absolutely need to save characters.

There's nothing really special here yet. The next step is REALLY cool:
{{{
val line = "Completed in 100ms (View: 25, DB: 75) | 200 OK [http://app.domain.com?params=here]"

scala> val LogEntry(totalTime, viewTime, dbTime, responseCode, uri) = line
totalTime: String = 100
viewTime: String = 25
dbTime: String = 75
responseCode: String = 200
uri: String =
}}}
The local variables totalTime, viewTime, dbTime, responseCode and uri are now bound to the values we want to extract from the original line! The regular expression value defines an unapplySeq method. I’m not quite good enough at Scala to tell you in any definite terms what that means, except that you can use the code in a pattern match:
{{{
line match {
  case LogEntry(totalTime, viewTime, dbTime, responseCode, uri) => {
    /* Process the data */
    // do something with totalTime.toInt
    // do something with viewTime.toInt
    // etc ...
  }
  case _ => // Do nothing
}
}}}
Because you can use a pattern match, and patterns will be be matched in the order of definition, this means that you can create several regular expressions representing lines you want to extract, then process them easily in using pattern matching.

Pretty powerful stuff. What would really make my day would be if someone knew how I could extract the values totalTime, viewTime, and dbTime as integers and not have to do a conversion – I’m already matching with \d+. Ideas?
!HTML5
[[DZslides]] - a one-page-template to build your presentation in HTML5 and CSS3.

!CSS
[[Sass]] - an extension of CSS3
This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.

@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://devcdip.tiddlyspot.com/controlpanel]] (your control panel username is //devcdip//).
<<tiddler TspotControls>>
See also GettingStarted.

@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the "save to web" button in the column on the right.

@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click "upload" and your ~TiddlyWiki will be saved back to tiddlyspot.com.

@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].

@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions.
!Image Building
At the source host...
{{{
$ cp <mydroid>/vendor/asus/<product name>/buildspec.mk  <mydroid>/ && make
}}}

!Image Copy
The images will be setted in {{{<mydroid>/out/target/product/<product name>/}}}
Copy the user image ({{{userdata.img}}}) and file system image ({{{system_ext3*.img}}})

!Fastboot the Target Phone
Hold both the volumn keys, and power on. Then you can use the volumn keys as the arrow keys, power key to enter.

!Burn!!!
Turn back to your PC, plug in the USB line, enter the command mode and execute as the following commands:
{{{
$ fastboot flash eng_data userdata.img
$ fastboot flash emmc_ext3_part1 system_ext3_part1.img
$ fastboot flash emmc_ext3_part2 system_ext3_part2.img
}}}
Outdated Build system documentation 
"http://source.android.com/porting/build_system.html" 

In general, the key thing to note is that android build system is 
non-recursive. For more on recursive vs non-recursive, please see 

GNU Make Recursion 
"http://www.gnu.org/s/hello/manual/make/Recursion.html" 

Why recursion is harmful 
"http://www.google.co.in/url? 
sa=t&source=web&cd=1&ved=0CBkQFjAA&url=http%3A%2F 
%2Faegis.sourceforge.net 
%2Fauug97.pdf&ei=nWmITZonhLywA9KqjYIM&usg=AFQjCNHNpBwPrZj4wjVZcyFfqmagq0M2JQ&sig2=d0fecnqbexy71nytu4PguQ" 

= FAQ = 
All the commands mentioned here are from top of the tree and assume 
you've already setup your environment with 

 $ source build/envsetup.sh 
 $ choosecombo 

== What java version is my build using? == 

In Gingerbread, your JAVA_HOME is set to '''/usr/lib/jvm/java-6-sun''' 
by build/envsetup.sh. You may see errors if you do not have JAVA 1.6 
installed. 

 $ echo $JAVA_HOME # should return empty 
 $ source build/envsetup.sh # will set your JAVA_HOME if it's empty, 
will honor the existing value otherwise 
 $ which java 
 $ java -version 
 $ javac -version 

=== Related Build Error: method does not override a method from its 
superclass. @Override === 

This "error" is due to a difference in the meaning of @Override 
between Java 1.5 and Java 1.6: Java 1.6 added the ability to use 
@Override to indicate that a method implements an interface method 
[which this code does]. 

You should be able to compile this code without error if you use a 
Java 1.6 compiler (the 'java -version' command only shows the JRE 
version.  Use 'javac -version' to get the compiler version and adjust 
your path accordingly). 

== What are the various build variants and their usage == 

Android build system supports the following build variants 

*user 
*userdebug 
*eng 
*tests 

For more on their usage and meaning, please see the Android Build 
Variants wiki 
"http://source.android.com/porting/ 
build_system.html#androidBuildVariants" 

You can build these variants as follows 

 $ cd WORKSPACE 
 $ source build/envsetup.sh 
 $ choosecombo 1 1 <product-name> user 
 $ choosecombo 1 1 <product-name> userdebug 
 $ choosecombo 1 1 <product-name> eng 

Alternatively, you can run 

 $ make PRODUCT-<product-name>-user 
 $ make PRODUCT-<product-name>-eng 
 $ make PRODUCT-<product-name>-tests 

Note that '''choosecombo''' doesn't support tests variant. More 
details on 
tests variant TBD. 

== Where is the build log? == 
You can save one for yourself with 

 $ make 2>&1 | tee log 

== How do I clean the build? == 

You can use '''dataclean''' to clean the staging area for your data 
partition 

 $ make dataclean # will rm -rf $(PRODUCT_OUT)/data/*, data-qemu/*, 
userdata-qemu.img 

You can use '''installclean''' while switching between build variants 

 $ choosecombo 1 1 <product-name> user 
 $ make installclean # deletes all of the files that change between 
different 
build types 
 $ choosecombo 1 1 <product-name> eng 

Clean and clobber, both will remove the entire build dir 

 $ make clean   # Remove all builds for current and past targets, does 
rm -rf 
$(OUT_DIR) 
 $ make clobber # Remove all builds for current and past targets 

== What is a module? == 

In android build system, an Android.mk file defines how you build. An 
android module is the entity you are building and is specified by 
variable LOCAL_MODULE in the Android.mk 

A single Android.mk can build multiple modules. 

== How do I rebuild my module? == 

If you have a 'LOCAL_MODULE := foobar' in your Android.mk, you should 
be able to do 

 $ make foobar 

== How do I build multiple modules in a dir? == 
== What are m, mm, mmm? == 

These are build utilities provided by build/envsetup.sh. Here's a 
description of all the available utilities 

 - croot:   Changes directory to the top of the tree. 
 - m:       Makes from the top of the tree. 
 - mm:      Builds all of the modules in the current directory. 
 - mmm:     Builds all of the modules in the supplied directories. 
 - cgrep:   Greps on all local C/C++ files. 
 - jgrep:   Greps on all local Java files. 
 - mgrep:   Greps on all makefiles 
 - resgrep: Greps on all local res/*.xml files. 
 - godir:   Go to the directory containing a file 
 - printconfig: tells you what configuration you are currently 
building 

Note that 'm' and 'mm' need a toplevel Android.mk in the directory you 
use them on. 

Example usage 

 $ cd dalvik/tests 
 $ mm 
 $ mmm ../tools 
 $ godir Atomic.h 
 $ m 
 $ croot 

== How do I turn off prelinking for my module? == 

Add 

 LOCAL_PRELINK_MODULE := false 

For the module in your Android.mk LOCAL_PRELINK_MODULE is set to false 
by default for executables (built using BUILD_EXECUTABLE) 

== How do I see what commands make is running? == 

You can use the '''showcommands''' modifier target. 
What is does (build/core/config.mk) 
 # The 'showcommands' goal says to show the full command 
 # lines being executed, instead of a short message about 
 # the kind of operation being done. 
 SHOW_COMMANDS:= $(filter showcommands,$(MAKECMDGOALS)) 

Usage 
 $ make showcommands 
 $ cd $some_dir_with_an_Android.mk 
 $ mm showcommands 

== How do I find out what are the available modules? == 

 $ cd $some_dir_with_an_Android.mk 
 $ mm modules 

You can also run 'make' to see the list of all the modules available 
in your tree 
 $ croot 
 $ make modules 

== How do I clean a single module/package? == 

 $ croot 
 $ make clean-$(LOCAL_MODULE) 

== How do I rebuild system image for an existing build? == 

 $ make snod 

=== What is snod? === 

'snod' is a pseduo-target provided by build/core/Makefile. You can use 
it to rebuild your system image without following it's dependencies 
and rebuilding everything else, apart from what you provide to make. 
Example use cases 

  $ make framework snod # rebuilds framework module, and system image 

== How do I build multiple variants and targets? == 

Note: this script is broken in gingerbread. 

 $ source build/tools/check_builds.sh 
 $ golden_builds <product1>-eng <product2>-user <product3>-eng 

Additionally you can run 

 $ check_builds <product1>-eng <product2>-user <product2>-eng 

What this will do for you, according to check_build.sh comments: 

 # Go get dinner, and when you get back, there will be a file 
 # test-builds/sizes.html that has a pretty chart of which files are 
 # in which tree, and how big they are. 

== How do I find what build properties are available for my build and 
how they were derived? == 
Post a full build, build properties can be examined in 

  out/target/product/$(TARGET_PRODUCT)/build.prop 

This file is created/updated by build/core/Makefile (invoked by build/ 
core/main.mk). The file is a concatentation of build/tools/ 
buildinfo.sh output + your system.prop + $ADDITIONAL_BUILD_PROPERTIES 

== App development == 

 $ cd your_app_folder 
 $ mmm 
 $ adb sync 

 If you don't use the same machine for compilation and loading it is 
possible to forward the port used by adb (5037) to the PC connected to 
the device. 
 If it's a linux machine, it is a lot easier, but it is possible to 
forward ports from windows. 
 Fastboot still has to be run on the connected machine, but since it 
only needs a few image files it is easier to coordinate. 

== How do I build my binary/library/applicaton? == 

In general, refer to the build cookbook "http://source.android.com/ 
porting/build_cookbook.html" You can also look at existing Android.mk 
files in your source tree. If you are tagging your module with 
"optional". 

In summary, 'user' tags cannot be used, they are used only for legacy 
modules (Grandfathered). 

'optional' tags makes sure that the module gets installed into user 
and eng builds as long as you add that module name to the list of 
packages (PRODUCT_PACKAGES). 

PRODUCT_PACKAGES for proprietary modules is defined in the device- 
vendor.mk 
file, e.g. vendor/<vendor-name>/prop/common/config/device-vendor.mk 

Opensource modules are defined in device/<vendor-name>/common/ 
common.mk 

The 'eng' tag implies that the module will be picked up only by 'eng' 
variant of the 
build. 

The tests tag implies that the module will be picked up by tests 
variant of the 
build. The tests variant is not available from choosecombo. 

Do not use development (or any other tags not sanctioned by the 
android build 
system) 

== My binary/library isn't available on target, whats wrong? == 

Check if you've updated the appropriate .mk configuration file to 
include 
a PRODUCT_PACKAGES entry for the module. 

Check the build log to see if your module got built. You can also use 
'mm' 
with 'showcommands' to see if the module is being built & installed. 

== I don't want to build everything, takes too long. What do I do? == 

You can build "tiny android," an Android build with a limited 
userspace that 
is useful for kernel development and verification. The tiny android 
build will 
not boot into the full UI. It will stay at one of the loading screens 
(ANDROID_ - not the boot animation). ADB will be active, allowing you 
to run 
unit tests, etc. The build time for tiny android is significantly less 
than a 
full Android build. Tiny Android builds complete in less than 2 
minutes, 
whereas a full Android build takes over 20 minutes. 

 $ BUILD_TINY_ANDROID=true make -j4 

=== How do I use a prebuilt kernel? === 

The kernel objects, vmlinux and zImage will be at <platform>/out/ 
target/product/<TARGET>/obj/KERNEL_OBJ and its subdirectories, where 
<TARGET> is the target device you selected in choosecombo above.  You 
can override the TARGET_PREBUILT_KERNEL flag with your own kernel 
image to build android with your kernel, as follows: 

 $ make -j4 TARGET_PREBUILT_KERNEL="<your_kernel_tree>/arch/arm/boot/ 
zImage" 

=== error: do_inode_allocate_extents: Failed to allocate blocks === 
One way to workaround this is to increase the system image size. 
Please see 
BOARD_*_PARTITION_SIZE variables in device/<vendor>/$(TARGET_PRODUCT)/ 
BoardConfig.mk in your workspace. 

== Misc == 

=== If you want to see all warnings in a pretty format, do === 
 $ build/tool/warn.py my_build_log > warn.html 

See the html page for a nice classification for all the warnings on 
your product. 

=== What is the 'simulator' in lunch for? === 

"the simulator is somewhat maintained, but it's a very specialized 
and 
very fragile tool which is only used by a handful of people at 
Google. 
It is likely to require the very precise environment that those 
people" 
use, which is specific to Google and isn't publicly available." 

See this thread for more detail 
"http://groups.google.com/group/android-building/browse_thread/thread/ 
55521a7849bbac1a/e4e020a8213cf7c7?lnk=gst&q=generic 
+product#e4e020a8213cf7c7" 

=== How do I rebuild the sdk? === 

 $ make PRODUCT-sdk-sdk 

== What is the difference between board, target, product and device? 
== 

Android build system supports hierarchical layering of product, 
device, board, 
and arch in a one to many relationship as described at 
"http://source.android.com/porting/ 
build_system.html#androidBuildSystemLayers" 

=== TARGET === 
In Android Build System, 'target' or 'TARGET' refers to your build 
target. There are a bunch of variables associated with a target. 

From a Build perspective, these are 

TARGET_PRODUCT: identifies the product that you are building 
TARGET_BUILD_TYPE: identifies the build type from one of 'release, 
debug' 
TARGET_BUILD_VARIANT: identifies the build variant from one of 'user, 
userdebug, eng, tests' 

From a PRODUCT perspective, these are 

TARGET_PRODUCT: identifies the product, for example, full_crespo, 
passion_us, passion_eu 
TARGET_DEVICE: identifies the device, for example, full_crespo, 
passion 
TARGET_BOARD_PLATFORM: can be used for a family of boards, for 
example, qsd8k, msm7k 
TARGET_BOOTLOADER_BOARD_NAME: used by OEMs for their boards, and by 
chipset_variants. For example, mahimahi of htc, full_crespo 
TARGET_ARCH: arm/x86 
TARGET_ARCH_VARIANT: armv5/armv7 

=== BOARD === 

In Android Build System, BOARD refers to the schematics of a product 
"http://source.android.com/porting/ 
build_system.html#androidBuildSystemLayers" 

=== DEVICE === 

For OEMs, DEVICE refers to the physical layer of plastic on the device 
"http://source.android.com/porting/ 
build_system.html#androidBuildSystemLayers" 

Each of these devices may result 
into multiple products. Examples 
* crespo  # Samsung 
* passion # HTC 

=== PRODUCT === 
The product layer represents a complete specification of a shipping 
product 
"http://source.android.com/porting/ 
build_system.html#androidBuildSystemLayers" 

== How do I add a new target? == 
Adding a new target means adding a new product. You can name your 
product as chipset_variant. Note that if one product may suffice for 
all your chipset variants. 

== How do I add a new product? == 
Follow the instructions for configuring a new product "http:// 
source.android.com/porting/build_new_device.html" for general info. 

Android products use inheritance, you can generate a nice product 
graph using 

 $ sudo apt-get install graphviz 
 $ make product-graph # pdf goes in out/product.pdf 

== PRODUCT CONFIGURATION == 
In general, android build system builds products, and allows you to 
configure what goes into a product. It doesn't explicitly support 
configuration at a build level, in allowing you to choose what to 
build. A typical android build is supposed to build all possible code 
that is available 
"http://android.git.kernel.org/?p=platform/build.git;a=blob;f=core/ 
main.mk;h=3877bb2b784da528fc20d66dc2701bdb0e3703b5;hb=HEAD" 
see build/core/main.mk line 638-639. 

You can choose what goes into a product, by adding to the 
PRODUCT_PACKAGES list which is used to specify what additional 
packages go into a product, as follows. 

=== How do I generate a product graph === 
 $ sudo apt-get install graphviz 
 $ make product-graph # pdf goes in out/product.pdf 

=== What is device-vendor.mk, when do I modify it? === 

device-vendor.mk allows you to configure proprietary modules to be 
installed 
on the target images. 

Starting with Gingerbread the Android build system enforces an 
explicit 
LOCAL_MODULES_TAGS for all modules which aren't in the GRANDFATHERED 
MODULES 
list in "http://android.git.kernel.org/?p=platform/ 
build.git;a=blob;f=core/ 
user_tags.mk;h=3eade8aa840e5c2fe0c31babf7b437d3fdf37feb;hb=HEAD" and 
recommends using "optional" tag for modules which are expected to be 
in all builds of a product. 

When LOCAL_MODULE_TAGS of a module is defined with an "optional" tag, 
the module will not be available in the generated final image/s (which 
will be flashed on Target). 

To get the module available in final image/s, module has to be part of 
PRODUCT_PACKAGES list. 

=== What is device/<vendor>/common/common.mk, when do I modify it? === 

The opensource counter part of device-vendor.mk [prev question] is 
device/<vendor>/common/common.mk and should be used for adding 
opensource modules to PRODUCT_PACKAGES. 

=== How do I configure (enable/disable) a module? === 
Configuration has two aspects with respect to Android Build System 
* What gets installed 
* What gets built 

What gets installed can be configured at a product level using the 
device-vendor.mk and common.mk configuration files, described above 
[prev questions]. 

Controlling what get's built, is a more complicated story. Presently, 
for a typical build android build system builds all modules it can 
find using findleaves.py [See modules_to_install and modules_to_check 
in build/core/main.mk]. The two ways to enable/disable a module then 
are 

* Add/Remove Android.mk 
* Wrap the Android.mk in TARGET_PRODUCT if you don't want to build 
your 
* modules for products like generic, emulator etc. 

If you want your module to not be built for variants not supported by 
your LOCAL_MODULE_TAGS, you can define LOCAL_DONT_CHECK_MODULE, though 
it is not recommended by android build system as of now. Example, 

 $(CLEAR_VARS) 
 LOCAL_DONT_CHECK_MODULE := true 
 LOCAL_MODULE := foo 
 LOCAL_MODULE_TAGS := eng 

What this will do for you is 
* For all non-eng builds, your module will only be built if it's a 
dependency 
* of another module 
* Else, it will be ignored 

== Emulator == 
=== What is the emulator? === 
From the AOSP WIKI documentation: "The Android SDK includes a mobile 
device emulator -- a virtual mobile device that runs on your computer. 
The emulator lets you develop and test Android applications without 
using a physical device." 

"http://developer.android.com/guide/developing/devices/emulator.html 
Emulator Overview" 

=== How is it used? === 
The emulator is provided by 

 external/qemu 
 sdk/emulator 
 prebuilt/linux-x86/emulator 

The one in external/qemu produces an executable called "emulator" 
which can be used from the commandline. It get's built and installed 
in out/host/linux-x86/bin/emulator and can be used with the images 
generated by building the 'generic' products provided in the AOSP 
tree. The AOSP tree provides "non-hardware-specific targets" which can 
be used "to build entire user-level system and work with emulator". 

There are two such target products available 

 target/product/generic 
 target/product/generic_x86 

They use the following boards from target/board, respectively 

 target/board/generic 
 target/board/generic_x86 

(There's also an 'emulator' board available under target/board for 
which 
there's no emulator.mk under target/product, device/ or vendor/ which 
is where 
envsetup.sh looks for product makefiles, and so it doesn't show up in 
choosecombo) 

target/board/*/README.txt explains the existence and usage of all 
three, 
generic, generic_x86, emulator. 

More documentation about the sdk emulator and it's usage at 
"http://developer.android.com/guide/developing/tools/emulator.html 
developer guide for emulator" 

Emulator usage example 
"http://groups.google.com/group/android-platform/browse_thread/thread/ 
b115c4cadbfdb333/488ca1b48bc546d8?lnk=gst&q=generic 
+product#488ca1b48bc546d8" 

== How do I rebuild the emulator? == 

"http://groups.google.com/group/android-building/browse_thread/thread/ 
f8f0c3bacd6efae/05ec2449d4e5dc6f?lnk=gst&q=emulator#05ec2449d4e5dc6f" 
[[TiddlyWiki|http://www.tiddlywiki.com]] © Osmosoft
http://docs.python.org/library/xml.etree.elementtree.html
{{{
from xml.etree.ElementTree import ElementTree
tree = ElementTree()
tree.parse('/blah_blah/strings.xml')
treeRoot = tree.getroot()
for node in treeRoot:
  print node.attrib['name'], '===>', node.text
}}}
!Buffer management
[[Re-create scratch buffer]]

!ediff
[[Ediff User's Manual|http://www.delorie.com/gnu/docs/emacs/ediff.html#SEC_Top]]

!elisp
[[Xah Lee's elisp tutorial|http://xahlee.org/emacs/elisp.html]]

!Misc
[[JJD 的部落格: Emacs 快速參考表 for Programmers|http://joeljding.blogspot.com/2009/07/emacs-quick-reference-card-for.html]]
[[StackOverflow: The single most useful Emacs feature|http://stackoverflow.com/questions/60367/the-single-most-useful-emacs-feature]]
{{{
# Global variables
WORKSRC=$HOME/worksrc


# Help
function help() {
cat <<EOF
Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
- croot:   Changes directory to the top of the tree.
- m:       Makes from the top of the tree.
- mm:      Builds all of the modules in the current directory.
- mmm:     Builds all of the modules in the supplied directories.
- cgrep:   Greps on all local C/C++ files.
- jgrep:   Greps on all local Java files.
- resgrep: Greps on all local res/*.xml files.
- godir:   Go to the directory containing a file.

Look at the source to view more functions. The complete list is:
EOF
    T=$(gettop)
    local A
    A=""
    for i in `cat $T/build/envsetup.sh | sed -n "/^function /s/function \([a-z_]*\).*/\1/p" | sort`; do
      A="$A $i"
    done
    echo $A
}

# Get the value of a build variable as an absolute path.
function get_abs_build_var()
{
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi
    CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
      make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-abs-$1
}

# Get the exact value of a build variable.
function get_build_var()
{
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi
    CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
      make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-$1
}

# check to see if the supplied product is one we can build
function check_product()
{
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi
    CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
        TARGET_PRODUCT=$1 TARGET_BUILD_VARIANT= \
        TARGET_SIMULATOR= TARGET_BUILD_TYPE= \
        get_build_var TARGET_DEVICE > /dev/null
    # hide successful answers, but allow the errors to show
}

VARIANT_CHOICES=(user userdebug eng)

# check to see if the supplied variant is valid
function check_variant()
{
    for v in ${VARIANT_CHOICES[@]}
    do
        if [ "$v" = "$1" ]
        then
            return 0
        fi
    done
    return 1
}

function setpaths()
{
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP."
        return
    fi

    ##################################################################
    #                                                                #
    #              Read me before you modify this code               #
    #                                                                #
    #   This function sets ANDROID_BUILD_PATHS to what it is adding  #
    #   to PATH, and the next time it is run, it removes that from   #
    #   PATH.  This is required so lunch can be run more than once   #
    #   and still have working paths.                                #
    #                                                                #
    ##################################################################

    # out with the old
    if [ -n $ANDROID_BUILD_PATHS ] ; then
        export PATH=${PATH/$ANDROID_BUILD_PATHS/}
    fi

    # and in with the new
    CODE_REVIEWS=
    prebuiltdir=$(getprebuilt)
    export ANDROID_EABI_TOOLCHAIN=$prebuiltdir/toolchain/arm-eabi-4.4.0/bin
    export ANDROID_TOOLCHAIN=$ANDROID_EABI_TOOLCHAIN
    export ANDROID_QTOOLS=$T/development/emulator/qtools
    export ANDROID_BUILD_PATHS=:$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_QTOOLS:$ANDROID_TOOLCHAIN:$ANDROID_EABI_TOOLCHAIN$CODE_REVIEWS
    export PATH=$PATH$ANDROID_BUILD_PATHS

    unset ANDROID_PRODUCT_OUT
    export ANDROID_PRODUCT_OUT=$(get_abs_build_var PRODUCT_OUT)
    export OUT=$ANDROID_PRODUCT_OUT

    # needed for building linux on MacOS
    # TODO: fix the path
    #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include

    # needed for OProfile to post-process collected samples
    export OPROFILE_EVENTS_DIR=$prebuiltdir/oprofile
}

function printconfig()
{
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi
    get_build_var report_config
}

function set_stuff_for_environment()
{
    settitle
    setpaths
    set_sequence_number

    # Don't try to do preoptimization until it works better on OSX.
    export DISABLE_DEXPREOPT=true

    export ANDROID_BUILD_TOP=$(gettop)
}

function set_sequence_number()
{
    export BUILD_ENV_SEQUENCE_NUMBER=9
}

function settitle()
{
    if [ "$STAY_OFF_MY_LAWN" = "" ]; then
        local product=$(get_build_var TARGET_PRODUCT)
        local variant=$(get_build_var TARGET_BUILD_VARIANT)
        export PROMPT_COMMAND="echo -ne \"\033]0;[${product}-${variant}] ${USER}@${HOSTNAME}: ${PWD}\007\""
    fi
}

case `uname -s` in
    Linux)
        function choosesim()
        {
            echo "Build for the simulator or the device?"
            echo "     1. Device"
            echo "     2. Simulator"
            echo

            export TARGET_SIMULATOR=
            local ANSWER
            while [ -z $TARGET_SIMULATOR ]
            do
                echo -n "Which would you like? [1] "
                if [ -z "$1" ] ; then
                    read ANSWER
                else
                    echo $1
                    ANSWER=$1
                fi
                case $ANSWER in
                "")
                    export TARGET_SIMULATOR=false
                    ;;
                1)
                    export TARGET_SIMULATOR=false
                    ;;
                Device)
                    export TARGET_SIMULATOR=false
                    ;;
                2)
                    export TARGET_SIMULATOR=true
                    ;;
                Simulator)
                    export TARGET_SIMULATOR=true
                    ;;
                *)
                    echo
                    echo "I didn't understand your response.  Please try again."
                    echo
                    ;;
                esac
                if [ -n "$1" ] ; then
                    break
                fi
            done

            set_stuff_for_environment
        }
        ;;
    *)
        function choosesim()
        {
            echo "Only device builds are supported for" `uname -s`
            echo "     Forcing TARGET_SIMULATOR=false"
            echo
            if [ -z "$1" ]
            then
                echo -n "Press enter: "
                read
            fi

            export TARGET_SIMULATOR=false
            set_stuff_for_environment
        }
        ;;
esac

function choosetype()
{
    echo "Build type choices are:"
    echo "     1. release"
    echo "     2. debug"
    echo

    local DEFAULT_NUM DEFAULT_VALUE
    if [ $TARGET_SIMULATOR = "false" ] ; then
        DEFAULT_NUM=1
        DEFAULT_VALUE=release
    else
        DEFAULT_NUM=2
        DEFAULT_VALUE=debug
    fi

    export TARGET_BUILD_TYPE=
    local ANSWER
    while [ -z $TARGET_BUILD_TYPE ]
    do
        echo -n "Which would you like? ["$DEFAULT_NUM"] "
        if [ -z "$1" ] ; then
            read ANSWER
        else
            echo $1
            ANSWER=$1
        fi
        case $ANSWER in
        "")
            export TARGET_BUILD_TYPE=$DEFAULT_VALUE
            ;;
        1)
            export TARGET_BUILD_TYPE=release
            ;;
        release)
            export TARGET_BUILD_TYPE=release
            ;;
        2)
            export TARGET_BUILD_TYPE=debug
            ;;
        debug)
            export TARGET_BUILD_TYPE=debug
            ;;
        *)
            echo
            echo "I didn't understand your response.  Please try again."
            echo
            ;;
        esac
        if [ -n "$1" ] ; then
            break
        fi
    done

    set_stuff_for_environment
}

#
# This function isn't really right:  It chooses a TARGET_PRODUCT
# based on the list of boards.  Usually, that gets you something
# that kinda works with a generic product, but really, you should
# pick a product by name.
#
function chooseproduct()
{
    if [ "x$TARGET_PRODUCT" != x ] ; then
        default_value=$TARGET_PRODUCT
    else
        if [ "$TARGET_SIMULATOR" = true ] ; then
            default_value=sim
        else
            default_value=generic
        fi
    fi

    export TARGET_PRODUCT=
    local ANSWER
    while [ -z "$TARGET_PRODUCT" ]
    do
        echo -n "Which product would you like? [$default_value] "
        if [ -z "$1" ] ; then
            read ANSWER
        else
            echo $1
            ANSWER=$1
        fi

        if [ -z "$ANSWER" ] ; then
            export TARGET_PRODUCT=$default_value
        else
            if check_product $ANSWER
            then
                export TARGET_PRODUCT=$ANSWER
            else
                echo "** Not a valid product: $ANSWER"
            fi
        fi
        if [ -n "$1" ] ; then
            break
        fi
    done

    set_stuff_for_environment
}

function choosevariant()
{
    echo "Variant choices are:"
    local index=1
    local v
    for v in ${VARIANT_CHOICES[@]}
    do
        # The product name is the name of the directory containing
        # the makefile we found, above.
        echo "     $index. $v"
        index=$(($index+1))
    done

    local default_value=eng
    local ANSWER

    export TARGET_BUILD_VARIANT=
    while [ -z "$TARGET_BUILD_VARIANT" ]
    do
        echo -n "Which would you like? [$default_value] "
        if [ -z "$1" ] ; then
            read ANSWER
        else
            echo $1
            ANSWER=$1
        fi

        if [ -z "$ANSWER" ] ; then
            export TARGET_BUILD_VARIANT=$default_value
        elif (echo -n $ANSWER | grep -q -e "^[0-9][0-9]*$") ; then
            if [ "$ANSWER" -le "${#VARIANT_CHOICES[@]}" ] ; then
                export TARGET_BUILD_VARIANT=${VARIANT_CHOICES[$(($ANSWER-$_arrayoffset))]}
            fi
        else
            if check_variant $ANSWER
            then
                export TARGET_BUILD_VARIANT=$ANSWER
            else
                echo "** Not a valid variant: $ANSWER"
            fi
        fi
        if [ -n "$1" ] ; then
            break
        fi
    done
}

function tapas()
{
    choosecombo
}

function choosecombo()
{
    choosesim $1

    echo
    echo
    choosetype $2

    echo
    echo
    chooseproduct $3

    echo
    echo
    choosevariant $4

    echo
    set_stuff_for_environment
    printconfig
}

# Clear this variable.  It will be built up again when the vendorsetup.sh
# files are included at the end of this file.
unset LUNCH_MENU_CHOICES
function add_lunch_combo()
{
    local new_combo=$1
    local c
    for c in ${LUNCH_MENU_CHOICES[@]} ; do
        if [ "$new_combo" = "$c" ] ; then
            return
        fi
    done
    LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
}

# add the default one here
add_lunch_combo generic-eng

# if we're on linux, add the simulator.  There is a special case
# in lunch to deal with the simulator
if [ "$(uname)" = "Linux" ] ; then
    add_lunch_combo simulator
fi

function print_lunch_menu()
{
    local uname=$(uname)
    echo
    echo "You're building on" $uname
    echo
    echo ${LUNCH_MENU_CHOICES[@]}
    echo "Lunch menu... pick a combo:"

    local i=1
    local choice
    for choice in ${LUNCH_MENU_CHOICES[@]}
    do
        echo "     $i. $choice"
        i=$(($i+1))
    done

    echo
}

function lunch()
{
    local answer

    if [ "$1" ] ; then
        answer=$1
    else
        print_lunch_menu
        echo -n "Which would you like? [generic-eng] "
        read answer
    fi

    local selection=

    if [ -z "$answer" ]
    then
        selection=generic-eng
    elif [ "$answer" = "simulator" ]
    then
        selection=simulator
    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
    then
        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
        then
            selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}
        fi
    elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
    then
        selection=$answer
    fi

    if [ -z "$selection" ]
    then
        echo
        echo "Invalid lunch combo: $answer"
        return 1
    fi

    # special case the simulator
    if [ "$selection" = "simulator" ]
    then
        export TARGET_PRODUCT=sim
        export TARGET_BUILD_VARIANT=eng
        export TARGET_SIMULATOR=true
        export TARGET_BUILD_TYPE=debug
    else
        local product=$(echo -n $selection | sed -e "s/-.*$//")
        check_product $product
        if [ $? -ne 0 ]
        then
            echo
            echo "** Don't have a product spec for: '$product'"
            echo "** Do you have the right repo manifest?"
            product=
        fi

        local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
        check_variant $variant
        if [ $? -ne 0 ]
        then
            echo
            echo "** Invalid variant: '$variant'"
            echo "** Must be one of ${VARIANT_CHOICES[@]}"
            variant=
        fi

        if [ -z "$product" -o -z "$variant" ]
        then
            echo
            return 1
        fi

        export TARGET_PRODUCT=$product
        export TARGET_BUILD_VARIANT=$variant
        export TARGET_SIMULATOR=false
        export TARGET_BUILD_TYPE=release
    fi # !simulator

    echo

    set_stuff_for_environment
    printconfig
}

function gettop
{
    local TOPFILE=build/core/envsetup.mk
    if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
        echo $TOP
    else
        if [ -f $TOPFILE ] ; then
            # The following circumlocution (repeated below as well) ensures
            # that we record the true directory name and not one that is
            # faked up with symlink names.
            PWD= /bin/pwd
        else
            # We redirect cd to /dev/null in case it's aliased to
            # a command that prints something as a side-effect
            # (like pushd)
            local HERE=$PWD
            T=
            while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
                cd .. > /dev/null
                T=`PWD= /bin/pwd`
            done
            cd $HERE > /dev/null
            if [ -f "$T/$TOPFILE" ]; then
                echo $T
            fi
        fi
    fi
}

function m()
{
    T=$(gettop)
    if [ "$T" ]; then
        make -C $T $@
    else
        echo "Couldn't locate the top of the tree.  Try setting TOP."
    fi
}

function findmakefile()
{
    TOPFILE=build/core/envsetup.mk
    # We redirect cd to /dev/null in case it's aliased to
    # a command that prints something as a side-effect
    # (like pushd)
    local HERE=$PWD
    T=
    while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
        T=$PWD
        if [ -f "$T/Android.mk" ]; then
            echo $T/Android.mk
            cd $HERE > /dev/null
            return
        fi
        cd .. > /dev/null
    done
    cd $HERE > /dev/null
}

function mm()
{
    # If we're sitting in the root of the build tree, just do a
    # normal make.
    if [ -f build/core/envsetup.mk -a -f Makefile ]; then
        make $@
    else
        # Find the closest Android.mk file.
        T=$(gettop)
        local M=$(findmakefile)
        # Remove the path to top as the makefilepath needs to be relative
        local M=`echo $M|sed 's:'$T'/::'`
        if [ ! "$T" ]; then
            echo "Couldn't locate the top of the tree.  Try setting TOP."
        elif [ ! "$M" ]; then
            echo "Couldn't locate a makefile from the current directory."
        else
            ONE_SHOT_MAKEFILE=$M make -C $T files $@
        fi
    fi
}

function mmm()
{
    T=$(gettop)
    if [ "$T" ]; then
        local MAKEFILE=
        local ARGS=
        local DIR TO_CHOP
        local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
        local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
        for DIR in $DIRS ; do
            DIR=`echo $DIR | sed -e 's:/$::'`
            if [ -f $DIR/Android.mk ]; then
                TO_CHOP=`echo $T | wc -c | tr -d ' '`
                TO_CHOP=`expr $TO_CHOP + 1`
                MFILE=`echo $PWD | cut -c${TO_CHOP}-`
                if [ "$MFILE" = "" ] ; then
                    MFILE=$DIR/Android.mk
                else
                    MFILE=$MFILE/$DIR/Android.mk
                fi
                MAKEFILE="$MAKEFILE $MFILE"
            else
                if [ "$DIR" = snod ]; then
                    ARGS="$ARGS snod"
                elif [ "$DIR" = showcommands ]; then
                    ARGS="$ARGS showcommands"
                else
                    echo "No Android.mk in $DIR."
                    return 1
                fi
            fi
        done
        ONE_SHOT_MAKEFILE="$MAKEFILE" make -C $T $DASH_ARGS files $ARGS
    else
        echo "Couldn't locate the top of the tree.  Try setting TOP."
    fi
}

function croot()
{
    T=$(gettop)
    if [ "$T" ]; then
        cd $(gettop)
    else
        echo "Couldn't locate the top of the tree.  Try setting TOP."
    fi
}

function cproj()
{
    TOPFILE=build/core/envsetup.mk
    # We redirect cd to /dev/null in case it's aliased to
    # a command that prints something as a side-effect
    # (like pushd)
    local HERE=$PWD
    T=
    while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
        T=$PWD
        if [ -f "$T/Android.mk" ]; then
            cd $T
            return
        fi
        cd .. > /dev/null
    done
    cd $HERE > /dev/null
    echo "can't find Android.mk"
}

function pid()
{
   local EXE="$1"
   if [ "$EXE" ] ; then
       local PID=`adb shell ps | fgrep $1 | sed -e 's/[^ ]* *\([0-9]*\).*/\1/'`
       echo "$PID"
   else
       echo "usage: pid name"
   fi
}

# systemstack - dump the current stack trace of all threads in the system process
# to the usual ANR traces file
function systemstack()
{
    adb shell echo '""' '>>' /data/anr/traces.txt && adb shell chmod 776 /data/anr/traces.txt && adb shell kill -3 $(pid system_server)
}

function gdbclient()
{
   local OUT_ROOT=$(get_abs_build_var PRODUCT_OUT)
   local OUT_SYMBOLS=$(get_abs_build_var TARGET_OUT_UNSTRIPPED)
   local OUT_SO_SYMBOLS=$(get_abs_build_var TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED)
   local OUT_EXE_SYMBOLS=$(get_abs_build_var TARGET_OUT_EXECUTABLES_UNSTRIPPED)
   local PREBUILTS=$(get_abs_build_var ANDROID_PREBUILTS)
   if [ "$OUT_ROOT" -a "$PREBUILTS" ]; then
       local EXE="$1"
       if [ "$EXE" ] ; then
           EXE=$1
       else
           EXE="app_process"
       fi

       local PORT="$2"
       if [ "$PORT" ] ; then
           PORT=$2
       else
           PORT=":5039"
       fi

       local PID
       local PROG="$3"
       if [ "$PROG" ] ; then
           PID=`pid $3`
           adb forward "tcp$PORT" "tcp$PORT"
           adb shell gdbserver $PORT --attach $PID &
           sleep 2
       else
               echo ""
               echo "If you haven't done so already, do this first on the device:"
               echo "    gdbserver $PORT /system/bin/$EXE"
                   echo " or"
               echo "    gdbserver $PORT --attach $PID"
               echo ""
       fi

       echo >|"$OUT_ROOT/gdbclient.cmds" "set solib-absolute-prefix $OUT_SYMBOLS"
       echo >>"$OUT_ROOT/gdbclient.cmds" "set solib-search-path $OUT_SO_SYMBOLS"
       echo >>"$OUT_ROOT/gdbclient.cmds" "target remote $PORT"
       echo >>"$OUT_ROOT/gdbclient.cmds" ""

       arm-eabi-gdb -x "$OUT_ROOT/gdbclient.cmds" "$OUT_EXE_SYMBOLS/$EXE"
  else
       echo "Unable to determine build system output dir."
   fi

}

case `uname -s` in
    Darwin)
        function sgrep()
        {
            find -E . -type f -iregex '.*\.(c|h|cpp|S|java|xml|sh|mk)' -print0 | xargs -0 grep --color -n "$@"
        }

        ;;
    *)
        function sgrep()
        {
            find . -type f -iregex '.*\.\(c\|h\|cpp\|S\|java\|xml\|sh\|mk\)' -print0 | xargs -0 grep --color -n "$@"
        }
        ;;
esac

function jgrep()
{
    find . -type f -name "*\.java" -print0 | xargs -0 grep --color -C 1 -n "$@"
}

function cgrep()
{
    find . -type f -name "*\.c*" -print0 | xargs -0 grep --color -C 1 -n "$@"
}

function hgrep()
{
    find . -type f -name "*\.h*" -print0 | xargs -0 grep --color -C 1 -n "$@"
}

function resgrep()
{
    for dir in `find . -name res -type d`; do find $dir -type f -name '*\.xml' -print0 | xargs -0 grep --color -C 1 -n "$@"; done;
}

case `uname -s` in
    Darwin)
        function mgrep()
        {
            find -E . -type f -iregex '.*/(Makefile|Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -print0 | xargs -0 grep --color -n "$@"
        }

        function treegrep()
        {
            find -E . -type f -iregex '.*\.(c|h|cpp|S|java|xml)' -print0 | xargs -0 grep --color -n -i "$@"
        }

        ;;
    *)
        function mgrep()
        {
            find . -regextype posix-egrep -iregex '(.*\/Makefile|.*\/Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -type f -print0 | xargs -0 grep --color -n "$@"
        }

        function treegrep()
        {
            find . -regextype posix-egrep -iregex '.*\.(c|h|cpp|S|java|xml)' -type f -print0 | xargs -0 grep --color -n -i "$@"
        }

        ;;
esac

function getprebuilt
{
    get_abs_build_var ANDROID_PREBUILTS
}

function tracedmdump()
{
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP."
        return
    fi
    local prebuiltdir=$(getprebuilt)
    local KERNEL=$T/prebuilt/android-arm/kernel/vmlinux-qemu

    local TRACE=$1
    if [ ! "$TRACE" ] ; then
        echo "usage:  tracedmdump  tracename"
        return
    fi

    if [ ! -r "$KERNEL" ] ; then
        echo "Error: cannot find kernel: '$KERNEL'"
        return
    fi

    local BASETRACE=$(basename $TRACE)
    if [ "$BASETRACE" = "$TRACE" ] ; then
        TRACE=$ANDROID_PRODUCT_OUT/traces/$TRACE
    fi

    echo "post-processing traces..."
    rm -f $TRACE/qtrace.dexlist
    post_trace $TRACE
    if [ $? -ne 0 ]; then
        echo "***"
        echo "*** Error: malformed trace.  Did you remember to exit the emulator?"
        echo "***"
        return
    fi
    echo "generating dexlist output..."
    /bin/ls $ANDROID_PRODUCT_OUT/system/framework/*.jar $ANDROID_PRODUCT_OUT/system/app/*.apk $ANDROID_PRODUCT_OUT/data/app/*.apk 2>/dev/null | xargs dexlist > $TRACE/qtrace.dexlist
    echo "generating dmtrace data..."
    q2dm -r $ANDROID_PRODUCT_OUT/symbols $TRACE $KERNEL $TRACE/dmtrace || return
    echo "generating html file..."
    dmtracedump -h $TRACE/dmtrace >| $TRACE/dmtrace.html || return
    echo "done, see $TRACE/dmtrace.html for details"
    echo "or run:"
    echo "    traceview $TRACE/dmtrace"
}

# communicate with a running device or emulator, set up necessary state,
# and run the hat command.
function runhat()
{
    # process standard adb options
    local adbTarget=""
    if [ $1 = "-d" -o $1 = "-e" ]; then
        adbTarget=$1
        shift 1
    elif [ $1 = "-s" ]; then
        adbTarget="$1 $2"
        shift 2
    fi
    local adbOptions=${adbTarget}
    echo adbOptions = ${adbOptions}

    # runhat options
    local targetPid=$1
    local outputFile=$2

    if [ "$targetPid" = "" ]; then
        echo "Usage: runhat [ -d | -e | -s serial ] target-pid [output-file]"
        return
    fi

    # confirm hat is available
    if [ -z $(which hat) ]; then
        echo "hat is not available in this configuration."
        return
    fi

    adb ${adbOptions} shell >/dev/null mkdir /data/misc
    adb ${adbOptions} shell chmod 777 /data/misc

    # send a SIGUSR1 to cause the hprof dump
    echo "Poking $targetPid and waiting for data..."
    adb ${adbOptions} shell kill -10 $targetPid
    echo "Press enter when logcat shows \"hprof: heap dump completed\""
    echo -n "> "
    read

    local availFiles=( $(adb ${adbOptions} shell ls /data/misc | grep '^heap-dump' | sed -e 's/.*heap-dump-/heap-dump-/' | sort -r | tr '[:space:][:cntrl:]' ' ') )
    local devFile=/data/misc/${availFiles[0]}
    local localFile=/tmp/$$-hprof

    echo "Retrieving file $devFile..."
    adb ${adbOptions} pull $devFile $localFile

    adb ${adbOptions} shell rm $devFile

    echo "Running hat on $localFile"
    echo "View the output by pointing your browser at http://localhost:7000/"
    echo ""
    hat $localFile
}

function getbugreports()
{
    local reports=(`adb shell ls /sdcard/bugreports | tr -d '\r'`)

    if [ ! "$reports" ]; then
        echo "Could not locate any bugreports."
        return
    fi

    local report
    for report in ${reports[@]}
    do
        echo "/sdcard/bugreports/${report}"
        adb pull /sdcard/bugreports/${report} ${report}
        gunzip ${report}
    done
}

function startviewserver()
{
    local port=4939
    if [ $# -gt 0 ]; then
            port=$1
    fi
    adb shell service call window 1 i32 $port
}

function stopviewserver()
{
    adb shell service call window 2
}

function isviewserverstarted()
{
    adb shell service call window 3
}

function smoketest()
{
    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
        echo "Couldn't locate output files.  Try running 'lunch' first." >&2
        return
    fi
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi

    (cd "$T" && mmm tests/SmokeTest) &&
      adb uninstall com.android.smoketest > /dev/null &&
      adb uninstall com.android.smoketest.tests > /dev/null &&
      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTestApp.apk &&
      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTest.apk &&
      adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner
}

# simple shortcut to the runtest command
function runtest()
{
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi
    ("$T"/development/testrunner/runtest.py $@)
}

function godir () {
    T=$(gettop)
    if [[ -z "$1" ]]; then
        echo "Usage: godir <regex>"
        return
    fi
    if [[ ! -f $T/filelist ]]; then
		echo "$T"
        echo -n "Creating index..."
        (cd $T; find . -wholename ./out -prune -o -type f > filelist)
        echo " Done"
        echo ""
    fi
    local lines
    lines=($(grep "$1" $T/filelist | sed -e 's/\/[^/]*$//' | sort | uniq)) 
    if [[ ${#lines[@]} = 0 ]]; then
        echo "Not found"
        return
    fi
    local pathname
    local choice
    if [[ ${#lines[@]} > 1 ]]; then
        while [[ -z "$pathname" ]]; do
            local index=1
            local line
            for line in ${lines[@]}; do
                printf "%6s %s\n" "[$index]" $line
                index=$(($index + 1)) 
            done
            echo
            echo -n "Select one: "
            unset choice
            read choice
            if [[ $choice -gt ${#lines[@]} || $choice -lt 1 ]]; then
                echo "Invalid choice"
                continue
            fi
            pathname=${lines[$(($choice-$_arrayoffset))]}
        done
    else
        # even though zsh arrays are 1-based, $foo[0] is an alias for $foo[1]
        pathname=${lines[0]}
    fi
    cd $T/$pathname
}

function goproj () {
    if [[ -z "$1" ]]; then
        echo "Usage: goproj <regex>"
        return
    fi
	echo -n "Creating index..."
	(cd $WORKSRC; find $WORKSRC -maxdepth 1 -type d  > projlist)
	echo " Done"
	echo ""
    local lines
    lines=($(grep "$1" $WORKSRC/projlist | sort | uniq))
    if [[ ${#lines[@]} = 0 ]]; then
        echo "Not found"
        return
    fi
    local projname
    local choice
    if [[ ${#lines[@]} > 1 ]]; then 
        while [[ -z "$projname" ]]; do
            local index=1
            local line 
            for line in ${lines[@]}; do
                printf "%6s %s\n" "[$index]" $line
                index=$(($index + 1)) 
            done 
            echo 
            echo -n "Select one: "
            unset choice
            read choice
            if [[ $choice -gt ${#lines[@]} || $choice -lt 1 ]]; then 
                echo "Invalid choice"
                continue
            fi   
            projname=${lines[$(($choice-$_arrayoffset))]}
        done 
    else 
        # even though zsh arrays are 1-based, $foo[0] is an alias for $foo[1]
        projname=${lines[0]}
    fi   
    cd $projname
	envsetup
}

function envsetup () {
    # determine whether arrays are zero-based (bash) or one-based (zsh)
    _xarray=(a b c)
    if [ -z "${_xarray[${#_xarray[@]}]}" ]
    then
        _arrayoffset=1
    else
        _arrayoffset=0
    fi
    unset _xarray

    # Execute the contents of any vendorsetup.sh files we can find.
    for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh 2> /dev/null`
    do
        echo "including $f"
        . $f
    done
    unset f
}

function refresh () {
	local HERE=$PWD
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi
	if [ -f $T/filelist ] ; then
		rm filelist
	fi
	echo "$T"
	echo -n "Creating index..."
	(cd $T; find . -wholename ./out -prune -o -type f > filelist)
	echo " Done"
	echo ""
	cd $HERE
}

function reload () {
    source ~/.bashrc
}
}}}
!{{{format-patch}}} only for specific commits
{{{
for c in `git log --author=Raphanus | grep ^commit | awk '{print $2}'`; do
    git format-patch "$c^\!" "$c";
done
}}}
Tip: notice that in zsh, {{{^}}} is a special charactor.
{{{=}}} expects @@string@@s
{{{-eq}}} expects @@integer@@s

{{{"$bar"}}} is for literal matches, i.e. {{{z*}}} may expand but {{{"z*"}}} will literally match the wildcard char.

The difference between {{{[]}}} and {{{[[]]}}} is that in the latter word splitting and path name expansion are not done, but are in the former.

Plus {{{[[]]}}} allows the additional operators :
{{{&&}}} (AND), {{{||}}} (OR), {{{>}}} (String1 lexically greater than String2), {{{<}}} (String1 lexically less than String2)

The {{{==}}} comparison operator behaves differently within a double-brackets test than within single brackets.
{{{
[[ $a == z* ]]   # True if $a starts with an "z" (pattern matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
[ $a == z* ]     # File globbing and word splitting take place.
[ "$a" == "z*" ] # True if $a is equal to z* (literal matching).
}}}

Check out [[http://tldp.org/LDP/abs/html/comparison-ops.html]] for more info
!Basic Knowledge
*[[test flags|shell script test flags]]
*[[[[ and [|logic statement]]
*[[switch-case statement]]
*[[logic statement]]

!My Tools
*[[envsetup.sh]]
!Test Flags
| Flag | True if ... |h
| {{{[ string1 = string2 ]}}} |string1 and string2 are equal|
| {{{[ string1 != string2 ]}}} |string1 and string2 are not equal|
| {{{[ string1 \< string2 ]}}} |string1 is lexically less than string2 (e.g. 'a' is less than 'b')|
| {{{[ string1 \> string2 ]}}} |string1 is lexically greater than string2 (e.g. 'b' is greater than 'a')|
| {{{[ -z string ]}}} |string is zero (e.g. a empty string)|
| {{{[ -n string ]}}} |string is nonzero (e.g. a VAR string)|
| {{{[ -e file ]}}} |file exists|
| {{{[ -f file ]}}} |file is a file|
| {{{[ -d file ]}}} |file is a directory|
| {{{[ -c file ]}}} |file is a character device|
| {{{[ -b file ]}}} |file is a block device|
| {{{[ -p file ]}}} |file is a named pipe|
| {{{[ -s file ]}}} |file is not empty|
| {{{[ -k file ]}}} |file's sticky bit is set|
| {{{[ -S file ]}}} |file is a socket|
| {{{[ -L file ]}}} |file is a symbolic link|
| {{{[ -r file ]}}} |file is readable by user|
| {{{[ -w file ]}}} |file is writeable by user|
| {{{[ -x file ]}}} |file is executeable by user|
| {{{[ -O file ]}}} |file is owner by user|
| {{{[ -G file ]}}} |file is group owned by a greoup|
| {{{[ -u file ]}}} |file has its set user ID bit set|
| {{{[ -g file ]}}} |file has its group user ID bit set|
| {{{[ file1 -nt file2 ]}}} |file1 is newer than file2|
| {{{[ file1 -ot file2 ]}}} |file1 is older than file2|
| {{{[ file -ef file2 ]}}} |file1 is another name for file2|
| {{{[ n1 -eq n2 ]}}} |true if integer n1 = integer n2|
| {{{[ n1 -ne n2 ]}}} |true if integer n1 <> n2|
| {{{[ n1 -gt n2 ]}}} |true if n1 > n2|
| {{{[ n1 -ge n2 ]}}} |true if n1 >= n2|
| {{{[ n1 -lt n2 ]}}} |true if n1 < n2|
| {{{[ n1 -le n2 ]}}} |true if n1 <= n2|

!References
http://www.mgt.ncu.edu.tw/~dino/script/
Here's an example
{{{
size=0					# Default Char Point Size (!)
page=660				# Default Page Point Size
while [ "$1" != "" ]			# When there are arguments...
do					# Process the next one
  case $1				# Look at $1
  in
    -l)	lines=47;			# If it's a "-l", set lines
	page=470;			# Set the Landscape Page Point
	options="$options -L -l";	# Set the Landscape Options
	shift;;				# Shift one argument along
    -p)	lines=66;			# If it's a "-p", set lines
	options="$options -l";		# Set the Portrait Options
	shift;;				# Shift one argument along
    -s)	size=$2;			# If it's a "-s", set size
	shift 2;;			# Shift two arguments along
    *)	echo "Option [$1] not one of  [p, l, s]";	# Error (!)
	exit;;				# Abort Script Now
  esac
  if [ $size = 0 ]			# If size still un-set...
  then
    size=`echo "$page / $lines" | bc`	# Set from pages over lines
  else					# or
    lines=`echo "$page / $size" | bc`	# Set lines
  fi
done
options="$options$lines -s$size"	# Build complete option list
lp -P$PRINTER $options $filename	# Output print file to printer
}}}
!Introduction
高彈性、高效能伺服器框架。
http://projects.unbit.it/uwsgi/
//{{{
config.options.chkRegExpSearch        = false;         // default false
config.options.chkCaseSensitiveSearch = false;         // default false
config.options.chkAnimate             = true;          // default true
config.options.txtUserName            = "COLDTURNIP";  // default "YourName"
config.options.chkSaveBackups         = false;         // default true
config.options.chkAutoSave            = false;         // default false
config.options.chkGenerateAnRssFeed   = false;         // default false
config.options.chkSaveEmptyTemplate   = false;         // default false
config.options.chkOpenInNewWindow     = true;          // default true
config.options.chkToggleLinks         = false;         // default false
config.options.chkHttpReadOnly        = true;          // default true
readOnly                              = false;         // default true when viewed over HTTP, false when used locally -- for TiddlyWiki v2.2+ only
showBackstage                         = true;          // default false when viewed over HTTP, true when used locally -- for TiddlyWiki v2.2+ only
config.options.chkForceMinorUpdate    = false;         // default false
config.options.chkConfirmDelete       = true;          // default true
config.options.chkInsertTabs          = false;         // default false
config.options.txtBackupFolder        = "";            // default ""
config.options.txtMainTab             = "tabTimeline"; // default "tabTimeline"
config.options.txtMoreTab             = "moreTabAll";  // default "moreTabAll"
config.options.txtMaxEditRows         = "30";          // default "30"

config.views.wikified.dateFormat = "YYYY-0MM-0DD 0hh:0mm"; // "created" and "modified" timestamps in the tiddler display
config.macros.timeline.dateFormat = "YYYY-0MM-0DD (ddd)";  // dates in the timeline
//}}}
!查看當前 stack
!!功能
在程序中加入程式碼,使其可以在 logcat 中看到目前呼叫關係
!!方法
{{{
new Exception(“print trace”).printStackTrace();
}}}
!MethodTracing
!!功能
用於 profiling,分析每個函數占用的 CPU 時間、呼叫次數、函數呼叫關係等
!!方法
#{{multiline{在程式碼中加入追蹤開關
{{{
import android.os.Debug;
……
android.os.Debug.startMethodTracing(“/data/tmp/test”); // 先建立 /data/tmp 目錄
…… // 被追蹤的程式碼
 android.os.Debug.stopMethodTracing();
}}}
}}}
#編譯,運行後,裝置端生成 {{{/data/tmp/test.trace}}} 文件
#{{multiline{把 trace 文件複製到 PC 端
{{{
$ adb pull /data/tmp/test.trace ./
}}}
}}}
#{{multiline{使用 Android 內建工具分析 trace 文件
{{{
$ $ANDROID_SRC/out/host/linux-x86/bin/traceview test.trace
}}}
此時可看到各個函數被呼叫的次數、CPU 占用率等信息
}}}
#{{multiline{使用 Android 內建工具分析生成呼叫關係類圖
PC 端先把 graphviz 裝好
{{{
$ apt-get install graphviz
}}}
之後生成圖表
{{{
$ANDROID_SRC/out/host/linux-x86/bin/dmtracedump -g test.png test.trace
}}}
此時目錄下生成類圖 test.png
}}}
!!注意
trace 文件生成與 libdvm 模組 DEBUG 版本相衝突,所以此方法只適用於對非 DEBUG 版本模擬器的 debug,否則在分析 trace 文件時會報錯
!HProf (Heap Profile)
!!功能
用於 Java 層面的記憶體用量分析,顯示詳細的記憶體占用信息,指出可疑的 memory leak 對象
!!方法
#{{multiline{在程式碼中加入 dump 行為
{{{
import android.os.Debug;
import java.io.IOException;
……
try {
    android.os.Debug.dumpHprofData(“/data/tmp/input.hprof”); // 先建立 /data/tmp 目錄
} catch (IOException ioe) {
}
}}}
}}}
#{{multiline把 hprof 文件複製到 PC 端
{{{
$ adb pull /data/tmp/input.hprof ./
}}}
}}}
#{{multiline{使用命令 hprof-conv 把 hprof 轉成 MAT 可讀的標準的 hprof
{{{
$ $ANDROID_SRC/out/host/linux-x86/bin/hprof-conv input.hprof output.hprof
}}}
}}}
#{{multiline{使用 MAT 工具看 hprof 信息
下載 MAT 工具:http://www.eclipse.org/mat/downloads.php
用工具打開 output.hprof
}}}
#關於 MAT 與 hprof 搭配 DDMS 的使用可以看[[這邊|http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html]]
#注意:此工具只能顯示 Java 層面資訊,而不能顯示 C 層的記憶體資訊
!SamplingProfile (Android 2.0 上版本適用)
!!功能
每隔 N 毫秒對當前正在運行的函數取樣,並輸出到 log 中
!!在代碼中加入取樣設定
{{{
import dalvik.system.SamplingProfiler
……
SamplingProfile sp = SamplingProfiler.getInstance();
sp.start(n); // n為設定每秒取樣次數
sp.logSnapshot(sp.snapshot());
……
sp.shutDown();
}}}
它會開一個 thread 進行監測,在 logcat 中印出訊息
!用發系統信號的方式取當前堆棧情況和內存信息
!!原理
Dalvik 虛擬機對 SIGQUIT 和 SIGUSR1 信號進行處理(參考 dalvik/vm/SignalCatcher.c),分別完成取當前堆棧和取當前內存情況的功能
!!用法
#{{multiline{
{{{
$ remount
$ chmod 4666 /data/anr/traces.txt
$ rm /data/anr/traces.txt # 將之前的 trace dump 清空
$ ps # 找尋 PID
$ kill -3 <PID>
$ cat /data/anr/traces.txt
}}}
上述動作會掃所有的 thread list(dalvik/vm/Thread.c:dvmDumpAllThreadEx()),然後將之 dump 到 traces.txt 之中(dalvik/vm/interp/Stack.c:dumpFrames())
}}}
#{{multiline{
{{{
$ chmod 777 /data/misc -R
$ ps # 找到進程號
$ kill -10 進程號 # 發送SIGQUIT信事信號給該進程,此時生成hprof信息
$ ls /data/misc/*.hprof
}}}
此時生成hprf文件,如何使用此文件,見第二部分(HProf)
}}}
!!注意
hprof 文件都很大,用完請馬上刪除
!logcat 及原理
*android.util.Log 利用 println 的標準 Java 輸出字串,並加前綴 I/V/D
*Dalvik 利用 pipe 加 thread 方式,先利用 dup2 把 stdout 和 stderr 重定向到 pipe 中(vm/StdioConverter.c:{{{dvmstdioConverterStartup}}}),然後再啟動一個 thread 從 pipe 另一端讀出內容(dalvik/vm/StdioConverter.c:{{{stdioconverterThreadStart()}}}),使用 LOG 公共工具(system/core/liblog/logd_write.c: {{{__android_log_print()}}})輸出到 /dev/log/* 中去
!logcat 通過加不同參數看 /dev/log/ 下的不同輸入信息的方法
{{{
# logcat -b main 顯示主緩衝區中的信息
# logcat -b radio 顯示無線緩衝區中的信息
# logcat -b events 顯示事件緩衝區中的信息
}}}
!jdwp (java debug wire protocol) 及原理
*虛擬機(device 端)在啟動時加載了 Agent JDWP 從而具備了調試功能。在 debug 端(PC端)通過 JDWP 協定與 device 連接,通過發送命令來獲取的狀態和控制 Java 程序的執行。JDWP 是通過命令(command)和回覆(reply)進行通信的。
*JDK 中調試工具 jdb 就是一個調試器,DDMS 也提供調試器與設備相連。
*Dalvik 為 JDWP 提供了兩種連接協定:tcp 和 adb
**tcp 可以手動指定 port
**adb 自動設定為 port 8700,通常使用 DDMS 就是通過 adb
!monkey
monkey 是一個 Android 內建的工具。它向系統發送偽隨機的用戶事件流,實現對正在開發的應用程序進行壓力測試。
!!方法
在 decivce 端打開 setting 介面
{{{
$ adb shell
# monkey -p com.android.settings -v 500
}}}
!其它小工具
詳見 android.os.Debug 中提供的工具
!!取毫微秒級的時間,用於計算時間
{{{threadCpuTimeNanos()}}}
!!統計兩點間的記憶體分配情況
{{{startAllocCounting()}}}
{{{stopAllocCounting()}}}
{{{getGlobalAllocCount()}}}
{{{get…..}}}
!!印出當前已 load 的 class
{{{getLoadedClassCount()}}}
{{{printLoadedClasses()}}}(需要打開 NDEBUG 才能打開 system/core/ 中 Log 功能)
*{{multiline{如果要重新掛載全部 partition:
{{{
adb remount
}}}
}}}
*{{multiline{如果只要重掛特定的 partition,在 adb shell 裡面:
{{{
mount -o remount,rw <partition path>
}}}
例如,要移除 google 內建寫的 apk,我們需要 remount {{{/system}}}:
{{{
mount -o remount,rw /system
}}}
}}}
!理由

#通常在系統啟動時即開始活動,而且不會結束。
#通常是以 root 的身份啟動的。
#通常在背景執行。
#通常不受終端機控制,也不對終端機做輸出入。

!細目

順序並不一定要固定,也不一定每個動作都需要。

!!變更工作目錄

*一般說來,最好是變更到根目錄,這是因為根目錄不會/不可能被卸載。
*如果沒有變更工作目錄,或將工作目錄變更到一個子目錄下,則會產生無法將該目錄卸載的副作用。
*當這個 deamon 需要處理到檔案時,先變更工作目錄到一個明確的地方,可以避免在處理檔案時,找不到檔案或搞錯路徑。

一般做法
{{{
chdir("/");
}}}

!!設定新的 umask (檔案建立時的屬性遮罩)
{{{
umask(new_umask);
}}}
一般可能設定的新遮罩值有兩種。
*高限制、高安全性:{{{umask(077);}}}
*無限制:{{{umask(0);}}}

!!關閉所有設備

避免從父程序處繼承了已開啟的設備,影嚮其他程序對該設備的存取。因為一個 deamon 是一直在系統中活動的,如果它握有一個設備卻又不使用的話,除了增加系統負擔外,也會影嚮其他程序處理該設備的動作。

要得知系統最大可開啟的設備數,並關閉的話,可以:
<<<
(1) POSIX.1
{{{
nfds = sysconf(_SC_OPEN_MAX);
for(i = 0; i < nfds; i++)
    close(i);
}}}

{{{sysconf(_SC_OPEN_MAX)}}} 可用一個巨集 _POSIX_OPEN_MAX 替代,但是 {{{sysconf(_SC_OPEN_MAX)}}} 是執行時期取得,而 {{{_POSIX_OPEN_MAX}}} 卻是編譯時期即已決定,缺少彈性,不建議使用。例如原先系統的最大可開啟設備數為 32 ,但更新或升級系統後,此值增加到 64,如果程式是用 {{{_POSIX_OPEN_MAX}}} 的話,就需要重新編譯一次,而用 {{{sysconf()}}} 的話就不需要。
<<<
<<<
(2) BSD
{{{
nfds = getdtablesize()
for(i = 0; i < nfds; i++)
    close(i);
}}}
<<<

!!自動切換至背景執行

產生一個子程序,則這個子程序就會自動進入背景執行,而父程序則結束,如此即可讓 deamon 自已切換至背景執行。
{{{
if( fork() )
    exit(0);
}}}
依 POSIX 標準,process 的上下層關係有兩個特性:
#當 child process 結束時,系統會發出 {{{SIGCHLD}}} 給它的 parent process,使得 parent 得知 child 最後離開時的狀態;如果 parent 沒有利用 {{{waitpid()}}} 來接這個 signal,以 Linux 為例會使得 child process 處於半死不活的狀態 (zombie)
#process 的上下關係只有 parent-child。一旦 parent process 在 child 之前結束,child process 會脫離這個上下層關係,把 PPID 掛給 PID = 1 (init daemon),而 init daemon 總是能正確處理任何的 {{{SIGCHLD}}}

!!設定程序的有效使用者及使用群 ID

{{{
if(setuid(new_uid))
    exit(0);
if(setgid(new_gid))
    exit(0);
}}}

如果無法設定的話,最好是將程序結束,不要繼續下去,以免發生安全漏洞,或產生其他的困擾。

除非必要,不要設為 0 (root) 。

!!建立新的活動期間 (session) ,並脫離原控制終端機
  
將自已設為一個活動期間,脫離原來的活動期間,如此將使自已脫離原來的程序群。脫離原來的程序群,意味的是,自已將形成一個新的程序群,使自已不受舊有的工作控制訊號的影嚮。

由於 deamon 都是在背景執行的,不需要終端機,同時為了避免受到控制終端機的影嚮,最好脫離控制終端機:

{{{
setsid();
}}}

*呼叫 {{{setsid()}}} 的結果是:
*#將擁有新的活動期間以及處理程序群,同時自已將成為新處理程序群的領導。
*#將脫離原來的控制終端機,但不會再產生一個新的控制終端機。
*{{{setsid()}}} 是 POSIX 所定義的方法, BSD 及 SVR4 的方法則是 {{{setpgrp()}}},但兩者雖然名稱相同,卻用法不同。
  
!!設定工作控制訊號的處理方式,忽略部份訊號

必須設定 {{{SIGTSTP}}}, {{{SIGTTIN}}}, {{{SIGTTOU}}} 三個來自控制終端機的工作訊號的處理方式為不理會,這是因為這三個工作訊號的預設方式為暫停程序動作,這對一個 deamon 程序而言,是不必要的。

設定方式:
<<<
(1) Standard ANSI C: {{{signal()}}}
{{{
#ifdef SIGTSTP
signal( SIGTSTP, SIG_IGN );
#endif
#ifdef SIGTTIN
signal( SIGTTIN, SIG_IGN );
#endif
#ifdef SIGTTOU
signal( SIGTTOU, SIG_IGN );
#endif
}}}
<<<
<<<
(2) POSIX.1 : {{{sigaction()}}}
{{{
struct sigaction act;
act.sa_handler = SIG_IGN;
#ifdef SIGTSTP
sigaction( SIGTSTP, &act, NULL );
#endif
#ifdef SIGTTIN
sigaction( SIGTTIN, &act, NULL );
#endif
#ifdef SIGTTOU
sigaction( SIGTTOU, &act, NULL );
#endif
}}}
<<<

*在 POSIX 中,並沒有定義 {{{signal()}}},{{{signal()}}} 是 ANSI C 所定義的,在 POSIX 中建議使用 {{{sigaction()}}},不過既然 {{{signal()}}} 在 ANSI C 中有定義,同時在不理會訊號 ({{{SIG_IGN}}}) 的處置方式上,並沒有系統上的差異。
*雖然 {{{SIGTSTP}}}, {{{SIGTTIN}}}, {{{SIGTTOU}}} 三個訊號在 POSIX 中有定義,但因為這三個屬於工作控制訊號,有些系統並不需要或沒有定義,因此判斷其是否已定義,可以減少移植上的困擾。

另外,有兩個訊號可以設定用途。

#{{{SIGTERM}}}: 軟體終結訊號,一般 daemon 會捕捉這個訊號,以進行結束前的資源釋放與資料存取動作。這個訊號是指令 kill 預設送出的訊號,此訊號在 ANSI C 中即有定義,其值為 {{{15}}} 。
#{{{SIGHUP}}}: 掛斷訊號,原本此訊號來自終端機離線,但對一個已脫離終端機的 daemon 來說,這個訊號沒有意義,但一般都會捕捉這個訊號,把這個訊號當作暫停(stop)或重新啟動(restart)、載入(reload)的通知。這個訊號在 ANSI C 中有定義,其值為 {{{1}}} 。