呜呼!

Aug302007
0 评论

这个世界上,有些事情,仅有努力永远是不够的

k_eckel's mindview

0 评论

细想想,生活中的种种不如意,做选择时的惶恐不安,选择后的多种如果以及在失去某个机会或者在一次至关重要的考查中失败都 不是那么的影响巨大.生命是一连串长期而持续的积累,一次失败或者一次成功都不足以彻底改变一个人的生活.你要做的就是静静的积累,默默的努力,朝着自己 的目标前进
   生命是一种长期而持续的累积过程,绝不会因为单一的事件而毁了一个人的一生,也不会因为单一的事件而救了一个人的一生。
属于我们该得的,迟早会得到;属于我们不该得的,即使侥幸巧取也不可能长久保有。

如果我们看清这个事实,许多所谓"人生的重大抉择"就可以淡然处之,根本无需焦虑。
而所谓"人生的困境",也往往当下就变得无足挂齿。
   "生命是一种长期而持续的累积过程,不会因为一时的际遇而终止增或减。"
   生命的真相是一种长期而持续的累积过程(这是偶发的际遇无法剥夺的,而不是一时顺逆的际遇。
如果我们能看清处这个事实,生命的过程就真是"功不唐捐",没什么好贪求,也没什么好焦虑的了!
剩下来,我们所需要做的无非只是想清楚自己要从人生获得什么,然后安安稳稳,诚诚恳恳的去累积就是了。
   当我们面对两个可能的方案,而焦虑的不知何所抉择时,通常表示这两个方案或者一样好,或者一样坏,因而实际上选择哪个都一样,唯一的差别只是先后之序而已。而且,愈是让我们焦虑得厉害的,其实差别越小,愈不值得焦虑。反而真正有明显的好坏差别时,我们轻易的就知道该怎么做了。

可是我们却经常看不到长远的将来,短视的盯着两案短期内的得失:想选甲案,就舍不得乙案的好处;想选乙案,又舍不得甲案的好处。如果看得够远,人生常则八,九十,短则五,六十年,先做哪一件事又有什么关系?
   "朝三暮四"这个成语故事里,主人原本喂养猴子的橡实是"早上四颗下午三颗",后来改为"朝三暮四",猴子就不高兴而坚持改回到"朝四暮三""朝三暮四"和"朝四暮三"有什么本质区别?
   福祸如何,谁能全面知晓?
我们又有什么好得意?又有什么好忧虑?
人生的得与失,有时候怎么也说不清楚,有时候却再简单不过了:我们得到平日累积的成果,而失去我们不曾努力累积的!
所以重要的不是和别人比成就,而是努力去做自己想做的。

功不唐捐,最后该得到的不会少你一分,不该得到的也不会多你一分。

ScreenShot of Transparent Terminal

Aug232007
0 评论

Next Generation Ubuntu

0 评论

HOWTO: Terminal as the desktop background

0 评论

The objective is to have a gnome terminal running as the desktop background, right above the actual background image, that won't be displayed by the statusbar or ticker.

It should look something like this:
Full transparency
or
Semi-transparent with shadows (using Xgl)

Ok, lets get started...

1) Download devilspie

Code:
sudo apt-get install devilspie
2) Create a configuration file
Code:
mkdir ~/.devilspie
nano ~/.devilspie/DesktopConsole.ds
3) Paste the following configuration (press Ctrl^X to save and exit):
Code:
(if
(matches (window_name) "DesktopConsole")
(begin
(set_workspace 4)
(below)
(undecorate)
(skip_pager)
(skip_tasklist)
(wintype "utility")
(geometry "+50+50")
(geometry "924x668")
)
)
Notes:
- i use workspace 4 but you can use whatever you like.
- you should at least adjust the geometry lines to match your screen.
- Read the devilspie wiki, for other commands!!!

4) Create a new gnome-terminal profile named "DesktopConsole"
- in the "General" tab, untick "show menubar by default..."
- in the "Scrolling" tab, select "Scrollbar is" -> Disabled.
- in the "Effects" tab, set "Transparent background" and shade to "None" (or to whatever you prefer)

5) Add devilspie and gnome-terminal to the Startup Programs in your session:
in System->preferences->sessions, "Startup Programs" tab, add the 2 programs:
Code:
devilspie
gnome-terminal --window-with-profile=DesktopConsole
6) Logout, Login

Quotes

Aug222007
0 评论

"Programs must be written for people to read, and only incidentally for machines to execute.'
- Abelson & Sussman, SICP, preface to the first edition"

Quotes

0 评论

"The less confident you are, the more serious you have to act."

- Tara Ploughman
pad

emacs中文的显示和输入

0 评论

不使用中文的locale也是可以显示和输入中文的,因为从原理上说,对一个X应用程序,只要它能正确识别要显示文本的编码,然后找到相应的字体就 能正确显示,而对中文的输入来说,在能正确显示的前提下,只要能知道来自输入法的文本的编码也能正确输入。那这是不是说中文的locale没有存在的价值 呢?不是的,看一个例子:

在各个locale变量都是en_US.UTF-8的环境下打开emacs(我用的是emacs22),带上 -q选项使不加载~/.emacs文件,在*scratch*里输入“学习”两个字(如果有乱码的话可以先尝试打开一个带中文的utf-8文件,然后再在 *scratch*里输入,似乎是emacs22.0.50.1的bug),你会发现两个字的字体有较大差别,把光标移到“学“字上,用C-u C-x =查看字符信息,发现其charset是japanese jisx0208,font是-JIS-Fixed-...,再查看“习“字,charset是chinese-Gb2312,Font是-arphic -ar pl...,显然这里emacs把“学”字认为是一个日语charset里的字符,而把“习”字认为是一个中文charset里的字符,由于在缺省情况下 emacs为两个charset使用了不用的字体,就使两个字看起来不大一致。

虽然可以在fontset里对这个japanese charset强制指定使用和中文charset相同的字体,比如simsun,但这究竟不是一个好办法,因为在一般情况下中文的字体都是没有包含全部日 文的。不过这里为什么把这两个字认为是这两个charset,而不是utf-8?在en_US.UTF-8的环境下从输入法输出的字符应该是UTF-8才 对。这就和字体有关了,由于字体本身的特点,一种字体通常只包括了一种语言的某个字符集里的字符,至多再加上ascii字符,比如simsun字体除了 ascii字符外,只包括了gbk字符集里的字符,这样对于utf-8这样的多语言编码,就必须把它编码的各个字符归到各个字体使用的字符集才能使用这些 字体,而在utf-8使用的unicode里,有一些字符是中日韩共用的,应该把他们归到哪种字符集呢?没有一个特定的使用环境似乎不好办,这里 emacs在en_US下把“学“字归入了日文字符集,这对中文的使用者就是不合适的。所以你必须告诉emacs你的使用环境,这里中文locale就发 挥作用了,设置LANG=zh_CN.UTF-8,或者你只希望中文的显示和输入正确而保持英文环境,也可以只设置LC_CTYPE=zh_CN.UTF -8

25 useful commands in Linux/UNIX

Aug212007
0 评论

25)host

host is a simple utility for performing DNS lookups. It is normally used to convert names to IP addresses and vice versa. When no arguments or options are given, host prints a short summary of its command line arguments and options.

Example:
$ host mail.yahoo.com
mail.yahoo.com is an alias for login.yahoo.com.
login.yahoo.com is an alias for login-global.yahoo8.akadns.net.
login-global.yahoo8.akadns.net is an alias for login.yahoo.akadns.net.
login.yahoo.akadns.net has address 69.147.112.160

24)dig

dig (domain information groper) is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried. Most DNS administrators use dig to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output. Other lookup tools tend to have less functionality than dig.

$ dig mail.yahoo.com

; <<>> DiG 9.4.1-P1 <<>> mail.yahoo.com
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9867 ;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 8, ADDITIONAL: 8 ;; QUESTION SECTION: ;mail.yahoo.com. IN A ;; ANSWER SECTION: mail.yahoo.com. 195 IN CNAME login.yahoo.com. login.yahoo.com. 65 IN CNAME login-global.yahoo8.akadns.net. login-global.yahoo8.akadns.net. 122 IN CNAME login.yahoo.akadns.net. login.yahoo.akadns.net. 51 IN A 69.147.112.160 ;; AUTHORITY SECTION: akadns.net. 84671 IN NS zc.akadns.org. akadns.net. 84671 IN NS zd.akadns.org. akadns.net. 84671 IN NS eur1.akadns.net. akadns.net. 84671 IN NS use3.akadns.net. akadns.net. 84671 IN NS usw2.akadns.net. akadns.net. 84671 IN NS asia9.akadns.net. akadns.net. 84671 IN NS za.akadns.org. akadns.net. 84671 IN NS zb.akadns.org. ;; ADDITIONAL SECTION: za.akadns.org. 23366 IN A 195.219.3.169 zb.akadns.org. 23366 IN A 206.132.100.105 zc.akadns.org. 23366 IN A 61.200.81.111 zd.akadns.org. 23366 IN A 63.209.3.132 eur1.akadns.net. 17773 IN A 213.254.204.197 use3.akadns.net. 17773 IN A 204.2.178.133 usw2.akadns.net. 17773 IN A 208.185.132.166 asia9.akadns.net. 17773 IN A 220.73.220.4 ;; Query time: 27 msec ;; SERVER: 24.92.226.9#53(24.92.226.9) ;; WHEN: Mon Aug 20 13:34:17 2007 ;; MSG SIZE rcvd: 421 23)mkdir

The mkdir utility creates the directories named as operands, in the order specified, using mode ``rwxrwxrwx'' (0777) as modified by the current umask(2).

Example:
$ mkdir test
$ ls -l | grep test
drwxr-xr-x 2 owner group 512 Aug 20 13:35 test

22)rm

The rm utility attempts to remove the non-directory type files specified on the command line. If the permissions of the file do not permit writ- ing, and the standard input device is a terminal, the user is prompted (on the standard error output) for confirmation.

Example (file):

$ rm test2
$ ls -l | grep test2

Example (dir):
what you get when you try to rm a dir is:

$ rm test
rm: test: is a directory

to get around this do:

$ rm -r test
$ ls -l | grep test


21)cp

In the first synopsis form, the cp utility copies the contents of the source_file to the target_file. In the second synopsis form, the con- tents of each named source_file is copied to the destination target_directory. The names of the files themselves are not changed. If cp detects an attempt to copy a file to itself, the copy will fail.

Example:

$ cp test test2
$ ls -l | grep test
-rw-r--r-- 1 owner group 0 Aug 20 13:40 test
-rw-r--r-- 1 owner group 0 Aug 20 13:41 test2

copy a directory do:

$ cp -r test test2
$ ls -l | grep test
drwxr-xr-x 2 owner group 512 Aug 20 13:42 test
drwxr-xr-x 2 owner group 512 Aug 20 13:42 test2


20)grep

grep searches the named input FILEs (or standard input if no files are named, or the file name - is given) for lines containing a match to the given PATTERN. By default, grep prints the matching lines.

Example:

$ ls
example test three
$ ls | grep th
three


19)ls

For each operand that names a file of a type other than directory, ls displays its name as well as any requested, associated information. For each operand that names a file of type directory, ls displays the names of files contained within that directory, as well as any requested, asso- ciated information.

Example:

$ ls
example test three
$ ls -l
total 0
-rw-r--r-- 1 owner group 0 Aug 20 13:44 example
-rw-r--r-- 1 owner group 0 Aug 20 13:44 test
-rw-r--r-- 1 owner group 0 Aug 20 13:44 three


18)startx

The startx script is a front end to xinit that provides a somewhat nicer user interface for running a single session of the X Window Sys- tem. It is often run with no arguments.

Example:
To use startx user most have .xinitrc file in there home directory. Examples of the file are:

$ cat ~/.xinitrc
exec fluxbox
(this will start fluxbox)
$ cat ~/.xinitrc
exec gnome-session
(this will start gnome)
$ cat ~/.xinitrc
exec startkde
(this will start kde)

17)nano

nano is a small, free and friendly editor which aims to replace Pico, the default editor included in the non-free Pine package. Rather than just copying Pico's look and feel, nano also implements some missing (or disabled by default) features in Pico, such as "search and replace" and "go to line and column number".

Example:

$nano test

(will open test file for edit to exit type: Ctrl+X)

16)pwd

The pwd utility writes the absolute pathname of the current working directory to the standard output.

Example:

$ pwd
/usr/home/username/test

15)cat

The cat utility reads files sequentially, writing them to the standard output. The file operands are processed in command-line order. If file is a single dash (`-') or absent, cat reads from the standard input. If file is a UNIX domain socket, cat connects to it and then reads it until EOF. This complements the UNIX domain binding capability available in inetd(8).

Example:

$ cat test
this is the contents of the file test


14)man

The man utility formats and displays the on-line manual pages. This ver- sion knows about the MANPATH and PAGER environment variables, so you can have your own set(s) of personal man pages and choose whatever program you like to display the formatted pages. If section is specified, man only looks in that section of the manual. You may also specify the order to search the sections for entries and which preprocessors to run on the source files via command line options or environment variables. If enabled by the system administrator, formatted man pages will also be compressed with the ``/usr/bin/gzip -c'' command to save space.

Example:

$ man find

Show information about the command find

13)kill

The kill utility sends a signal to the processes specified by the pid op- erands.

Example:

$ kill 694

(694 is the id of the program running)

12)locate

The locate program searches a database for all pathnames which match the specified pattern. The database is recomputed periodically (usually weekly or daily), and contains the pathnames of all files which are pub- licly accessible.

Example:

#locate Xorg.0.log
/var/log/Xorg.0.log
/var/log/Xorg.0.log.old

(you man need to run /usr/libexec/locate.updatedb to update locate listing)

11)ifconfig

The ifconfig utility is used to assign an address to a network interface and/or configure network interface parameters. The ifconfig utility must be used at boot time to define the network address of each interface present on a machine; it may also be used at a later time to redefine an interface's address or other operating parameters.

Example:
# ifconfig
em0: flags=8843 metric 0 mtu 1500
options=18b
ether 00:16:41:16:28:2a
inet 192.168.1.2 netmask 0xffffff00 broadcast 192.168.1.255
media: Ethernet autoselect (1000baseTX )
status: active
lo0: flags=8049 metric 0 mtu 16384
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000

10)ssh

ssh (SSH client) is a program for logging into a remote machine and for executing commands on a remote machine. It is intended to replace rlogin and rsh, and provide secure encrypted communications between two untrusted hosts over an insecure network. X11 connections and arbitrary TCP ports can also be forwarded over the secure channel.

Example:

#ssh localhost
Password:
Welcome to FreeBSD-World

(you wouldn't use local host you would use the computer ip or hostname you are connecting to)

9)gzip

The gzip program compresses and decompresses files using Lempel-Ziv cod- ing (LZ77). If no files are specified, gzip will compress from standard input, or decompress to standard output. When in compression mode, each file will be replaced with another file with the suffix, set by the -S suffix option, added, if possible. In decompression mode, each file will be checked for existence, as will the file with the suffix added.

Example:

$ gzip -9 test.tar
test.tar.gz

$ gzip -d test.tar.gz
$ ls | grep test.tar
test.tar


8)bzip2

bzip2 compresses files using the Burrows-Wheeler block sorting text compression algorithm, and Huffman coding. Compression is generally considerably better than that achieved by more conventional LZ77/LZ78-based compressors, and approaches the performance of the PPM family of statistical compressors.

Example:

$ bzip2 -9 test.tar
$ ls | grep test.tar
test.tar.bz2
$ bzip2 -d test.tar.bz2
$ ls | grep test.tar
test.tar


7)zip

zip is a compression and file packaging utility for Unix, VMS, MSDOS, OS/2, Windows NT, Minix, Atari and Macintosh, Amiga and Acorn RISC OS.

Example:

$ zip test.zip test
adding: test/ (stored 0%)
$ ls | grep test
test
test.zip
$ unzip test.zip
Archive: test.zip


6)tar

tar creates and manipulates streaming archive files. This implementation can extract from tar, pax, cpio, zip, jar, ar, and ISO 9660 cdrom images and can create tar, pax, cpio, ar, and shar archives.


Example:

$ tar -cf t2.tar example test three
$ ls | grep t2
t2.tar
$ tar -xf t2.tar
(files are now extracted)


5)mount

The mount utility calls the nmount(2) system call to prepare and graft a special device or the remote node (rhost:path) on to the file system tree at the point node. If either special or node are not provided, the appropriate information is taken from the fstab(5) file.

Example:

# cat /etc/fstab
# Device Mountpoint FStype Options Dump Pass#
/dev/ad4s1b none swap sw 0 0
/dev/ad4s1a / ufs rw 1 1
/dev/acd0 /cdrom cd9660 ro,noauto 0 0
# mount /cdrom
# ls /cdrom
4.1 TRANS.TBL etc
# umount /cdrom
# ls /cdrom
#

(/cdrom is already listed in the fstab if it was not I would have to do 'mount /dev/acd0 /cdrom')

4)passwd

The passwd utility changes the user's local, Kerberos, or NIS password. If the user is not the super-user, passwd first prompts for the current password and will not continue unless the correct password is entered.

Example:

$ passwd
Changing local password for username
Old Password:
New Password:
Retype New Password:
$


3)ping

The ping utility uses the ICMP protocol's mandatory ECHO_REQUEST datagram to elicit an ICMP ECHO_RESPONSE from a host or gateway. ECHO_REQUEST datagrams (``pings'') have an IP and ICMP header, followed by a ``struct timeval'' and then an arbitrary number of ``pad'' bytes used to fill out the packet.

Example:

$ ping -c 5 www.yahoo.com
PING www.yahoo-ht3.akadns.net (69.147.114.210): 56 data bytes
64 bytes from 69.147.114.210: icmp_seq=0 ttl=47 time=48.814 ms
64 bytes from 69.147.114.210: icmp_seq=1 ttl=47 time=32.916 ms
64 bytes from 69.147.114.210: icmp_seq=2 ttl=47 time=32.361 ms
64 bytes from 69.147.114.210: icmp_seq=3 ttl=47 time=33.912 ms
64 bytes from 69.147.114.210: icmp_seq=4 ttl=47 time=33.846 ms

--- www.yahoo-ht3.akadns.net ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 32.361/36.370/48.814/6.249 ms


2)tail

The tail utility displays the contents of file or, by default, its stan- dard input, to the standard output.

# tail /var/log/auth.log
Aug 19 20:38:05 laptop su: username to root on /dev/ttyv0
Aug 20 00:10:38 laptop login: login on ttyv0 as username
Aug 20 00:11:30 laptop su: username to root on /dev/ttyp0
Aug 20 00:56:32 laptop su: username to root on /dev/ttyp1
Aug 20 01:31:26 laptop su: username to root on /dev/ttyv0
Aug 20 10:25:58 laptop login: login on ttyv0 as username
Aug 20 10:26:21 laptop su: username to root on /dev/ttyp0
Aug 20 13:58:06 laptop su: username to root on /dev/ttyp1
Aug 20 14:18:23 laptop su: username to root on /dev/ttyp1
Aug 20 14:27:39 laptop su: useranme to root on /dev/ttyp1


1)top

Top displays the top processes on the system and periodically updates this information.

Example:

last pid: 5327; load averages: 0.00, 0.00, 0.00 up 0+04:05:41 14:30:28
44 processes: 1 running, 43 sleeping
CPU states: 0.2% user, 0.0% nice, 1.3% system, 0.0% interrupt, 98.5% idle
Mem: 198M Active, 608M Inact, 128M Wired, 26M Cache, 111M Buf, 31M Free
Swap: 1024M Total, 8K Used, 1024M Free

PID USERNAME THR PRI NICE SIZE RES STATE C TIME WCPU COMMAND
694 username 1 96 0 53004K 48212K select 1 4:23 0.10% Xorg
10306 username 1 96 0 7496K 4300K select 1 0:04 0.05% xterm

中文字体

Aug202007
0 评论

使用 fc-list 查看你的系统中装了哪些中文字体:

$ fc-list :lang=zh-cn"

Notes on Programming in C

Aug182007
0 评论

Notes on Programming in C
Rob Pike, AT&T Bell Laboratories
Introduction
Kernighan and Plauger's The Elements of Programming Style (Prentice Hall, 1978) was an important and rightly influential book. But sometimes I feel its concise rules were taken as a cookbook approach to good style instead of the succinct expression of a philosophy they were meant to be. If the book claims that variable names should be chosen meaningfully, doesn't it then follow that variables whose names are small essays on their use are even better? Isn't MaximumValueUntilOverflow a better name than maxval? I don't think so.

What follows is a set of short essays that collectively encourage a philosophy of clarity in programming rather than giving hard rules. I don't expect you to agree with all of them, because they are opinion and opinions change with the times. But they've been accumulating in my head, if not on paper until now, for a long time, and are based on a lot of experience, so I hope they help you understand how to plan the details of a program. (I've yet to see a good essay on how to plan the whole thing.) If you find them idiosyncratic, fine; if you disagree with them, fine; but if they make you think about why you disagree, that's better. Under no circumstances should you program the way I say to because I say to; program the way you think expresses best what you're trying to accomplish in the program. And do so consistently and ruthlessly.

Your comments are welcome.

Issues of typography
A program is a sort of publication. It's meant to be read by the programmer, another programmer (perhaps yourself a few days, weeks or years later), and lastly a machine. The machine doesn't care how pretty the program is - if the program compiles, the machine's happy - but people do, and they should. Sometimes they care too much: pretty printers mechanically produce pretty output that accentuates irrelevant detail in the program, which is as sensible as putting all the prepositions in English text in bold font. Although many people think programs should look like the Algol-68 report (and some systems even require you to edit programs in that style), a clear program is not made any clearer by such presentation, and a bad program is only made laughable.

Typographic conventions consistently held are important to clear presentation, of course - indentation is probably the best known and most useful example - but when the ink obscures the intent, typography has taken over. So even if you stick with plain old typewriter-like output, be conscious of typographic silliness. Avoid decoration; for instance, keep comments brief and banner-free. Say what you want to say in the program, neatly and consistently. Then move on.

Variable names
Ah, variable names. Length is not a virtue in a name; clarity of expression is. A global variable rarely used may deserve a long name, maxphysaddr say. An array index used on every line of a loop needn't be named any more elaborately than i. Saying index or elementnumber is more to type (or calls upon your text editor) and obscures the details of the computation. When the variable names are huge, it's harder to see what's going on. This is partly a typographic issue; consider

for(i=0 to 100)
array[i]=0

vs.

for(elementnumber=0 to 100)
array[elementnumber]=0;

The problem gets worse fast with real examples. Indices are just notation, so treat them as such.

Pointers also require sensible notation. np is just as mnemonic as nodepointer if you consistently use a naming convention from which np means `node pointer' is easily derived. More on this in the next essay.

As in all other aspects of readable programming, consistency is important in naming. If you call one variable maxphysaddr, don't call its cousin lowestaddress.

Finally, I prefer minimum-length but maximum-information names, and then let the context fill in the rest. Globals, for instance, typically have little context when they are used, so their names need to be relatively evocative. Thus I say maxphysaddr (not MaximumPhysicalAddress) for a global variable, but np not NodePointer for a pointer locally defined and used. This is largely a matter of taste, but taste is relevant to clarity.

I eschew embedded capital letters in names; to my prose-oriented eyes, they are too awkward to read comfortably. They jangle like bad typography.

The use of pointers
C is unusual in that it allows pointers to point to anything. Pointers are sharp tools, and like any such tool, used well they can be delightfully productive, but used badly they can do great damage (I sunk a wood chisel into my thumb a few days before writing this). Pointers have a bad reputation in academia, because they are considered too dangerous, dirty somehow. But I think they are powerful notation, which means they can help us express ourselves clearly.

Consider: When you have a pointer to an object, it is a name for exactly that object and no other. That sounds trivial, but look at the following two expressions:

np
node[i]

The first points to a node, the second evaluates to (say) the same node. But the second form is an expression; it is not so simple. To interpret it, we must know what node is, what i is, and that i and node are related by the (probably unspecified) rules of the surrounding program. Nothing about the expression in isolation can show that i is a valid index of node, let alone the index of the element we want. If i and j and k are all indices into the node array, it's very easy to slip up, and the compiler cannot help. It's particularly easy to make mistakes when passing things to subroutines: a pointer is a single thing; an array and an index must be believed to belong together in the receiving subroutine.

An expression that evaluates to an object is inherently more subtle and error-prone than the address of that object. Correct use of pointers can simplify code:

parent->link[i].type

vs.

lp->type.

If we want the next element's type, it's

parent->link[++i].type

or

(++lp)->type.

i advances but the rest of the expression must stay constant; with pointers, there's only one thing to advance.

Typographic considerations enter here, too. Stepping through structures using pointers can be much easier to read than with expressions: less ink is needed and less effort is expended by the compiler and computer. A related issue is that the type of the pointer affects how it can be used correctly, which allows some helpful compile-time error checking that array indices cannot share. Also, if the objects are structures, their tag fields are reminders of their type, so

np->left

is sufficiently evocative; if an array is being indexed the array will have some well-chosen name and the expression will end up longer:

node[i].left.

Again, the extra characters become more irritating as the examples become larger.

As a rule, if you find code containing many similar, complex expressions that evaluate to elements of a data structure, judicious use of pointers can clear things up. Consider what

if(goleft)
p->left=p->right->left;
else
p->right=p->left->right;

would look like using a compound expression for p. Sometimes it's worth a temporary variable (here p) or a macro to distill the calculation.

Procedure names
Procedure names should reflect what they do; function names should reflect what they return. Functions are used in expressions, often in things like if's, so they need to read appropriately.

if(checksize(x))

is unhelpful because we can't deduce whether checksize returns true on error or non-error; instead

if(validsize(x))

makes the point clear and makes a future mistake in using the routine less likely.

Comments
A delicate matter, requiring taste and judgement. I tend to err on the side of eliminating comments, for several reasons. First, if the code is clear, and uses good type names and variable names, it should explain itself. Second, comments aren't checked by the compiler, so there is no guarantee they're right, especially after the code is modified. A misleading comment can be very confusing. Third, the issue of typography: comments clutter code.

But I do comment sometimes. Almost exclusively, I use them as an introduction to what follows. Examples: explaining the use of global variables and types (the one thing I always comment in large programs); as an introduction to an unusual or critical procedure; or to mark off sections of a large computation.

There is a famously bad comment style:

i=i+1; /* Add one to i */

and there are worse ways to do it:

/**********************************
* *
* Add one to i *
* *
**********************************/

i=i+1;

Don't laugh now, wait until you see it in real life.

Avoid cute typography in comments, avoid big blocks of comments except perhaps before vital sections like the declaration of the central data structure (comments on data are usually much more helpful than on algorithms); basically, avoid comments. If your code needs a comment to be understood, it would be better to rewrite it so it's easier to understand. Which brings us to

Complexity
Most programs are too complicated - that is, more complex than they need to be to solve their problems efficiently. Why? Mostly it's because of bad design, but I will skip that issue here because it's a big one. But programs are often complicated at the microscopic level, and that is something I can address here.

Rule 1. You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is.

Rule 2. Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest.

Rule 3. Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (Even if n does get big, use Rule 2 first.) For example, binary trees are always faster than splay trees for workaday problems.

Rule 4. Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms as well as simple data structures.

The following data structures are a complete list for almost all practical programs:

array
linked list
hash table
binary tree

Of course, you must also be prepared to collect these into compound data structures. For instance, a symbol table might be implemented as a hash table containing linked lists of arrays of characters.

Rule 5. Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming. (See Brooks p. 102.)

Rule 6. There is no Rule 6.

Programming with data
Algorithms, or details of algorithms, can often be encoded compactly, efficiently and expressively as data rather than, say, as lots of if statements. The reason is that the complexity of the job at hand, if it is due to a combination of independent details, can be encoded. A classic example of this is parsing tables, which encode the grammar of a programming language in a form interpretable by a fixed, fairly simple piece of code. Finite state machines are particularly amenable to this form of attack, but almost any program that involves the `parsing' of some abstract sort of input into a sequence of some independent `actions' can be constructed profitably as a data-driven algorithm.

Perhaps the most intriguing aspect of this kind of design is that the tables can sometimes be generated by another program - a parser generator, in the classical case. As a more earthy example, if an operating system is driven by a set of tables that connect I/O requests to the appropriate device drivers, the system may be `configured' by a program that reads a description of the particular devices connected to the machine in question and prints the corresponding tables.

One of the reasons data-driven programs are not common, at least among beginners, is the tyranny of Pascal. Pascal, like its creator, believes firmly in the separation of code and data. It therefore (at least in its original form) has no ability to create initialized data. This flies in the face of the theories of Turing and von Neumann, which define the basic principles of the stored-program computer. Code and data are the same, or at least they can be. How else can you explain how a compiler works? (Functional languages have a similar problem with I/O.)

Function pointers
Another result of the tyranny of Pascal is that beginners don't use function pointers. (You can't have function-valued variables in Pascal.) Using function pointers to encode complexity has some interesting properties.

Some of the complexity is passed to the routine pointed to. The routine must obey some standard protocol - it's one of a set of routines invoked identically - but beyond that, what it does is its business alone. The complexity is distributed.

There is this idea of a protocol, in that all functions used similarly must behave similarly. This makes for easy documentation, testing, growth and even making the program run distributed over a network - the protocol can be encoded as remote procedure calls.

I argue that clear use of function pointers is the heart of object-oriented programming. Given a set of operations you want to perform on data, and a set of data types you want to respond to those operations, the easiest way to put the program together is with a group of function pointers for each type. This, in a nutshell, defines class and method. The O-O languages give you more of course - prettier syntax, derived types and so on - but conceptually they provide little extra.

Combining data-driven programs with function pointers leads to an astonishingly expressive way of working, a way that, in my experience, has often led to pleasant surprises. Even without a special O-O language, you can get 90% of the benefit for no extra work and be more in control of the result. I cannot recommend an implementation style more highly. All the programs I have organized this way have survived comfortably after much development - far better than with less disciplined approaches. Maybe that's it: the discipline it forces pays off handsomely in the long run.

Include files
Simple rule: include files should never include include files. If instead they state (in comments or implicitly) what files they need to have included first, the problem of deciding which files to include is pushed to the user (programmer) but in a way that's easy to handle and that, by construction, avoids multiple inclusions. Multiple inclusions are a bane of systems programming. It's not rare to have files included five or more times to compile a single C source file. The Unix /usr/include/sys stuff is terrible this way.

There's a little dance involving #ifdef's that can prevent a file being read twice, but it's usually done wrong in practice - the #ifdef's are in the file itself, not the file that includes it. The result is often thousands of needless lines of code passing through the lexical analyzer, which is (in good compilers) the most expensive phase.

Just follow the simple rule.

Rob Pike / rob@research.att.com / Sep. 1987

RuthAron Pairs

Aug172007
0 评论




00001: /*
00002: * Program: ruth-aaron.cc
00003: * ----------------------
00004: * Presents a short program which identifies
00005: * and prints out the first 20 Ruth-Aaron pairs.
00006: */
00007:
00008: #include<iostream>
00009: #include<cmath>
00010: #include<vector>
00011: using namespace std;
00012:
00013:
00014: bool isPrime(int n)
00015: {
00016: if (n == 1) return false;
00017: if (n == 2) return true;
00018:
00019: for (int k = 2; k <= sqrt(double(n)) + 1; k++) {
00020: if (n % k == 0)
00021: return false;
00022: }
00023:
00024: return true;
00025: }
00026:
00027: int factorSum(int num)
00028: {
00029: int sum = 0;
00030: if(isPrime(num))
00031: sum = num;
00032: else {while(num != 1){
00033: for(int i =2; i <= num;i++) {
00034: if(isPrime(i) && (num % i == 0)) {
00035: sum += i;
00036: num /= i;
00037: break;
00038: }
00039: }
00040: }
00041: }
00042: return sum;
00043: }
00044:
00045: int main()
00046: {
00047: int kNumRuthAaronPairsNeeded = 60;
00048: // defines a constant variable so we know what 20 really is
00049:
00050: cout << "This program prints out the first "
00051: << kNumRuthAaronPairsNeeded
00052: << " Ruth-Aaron pairs...." << endl;
00053: cout << "And here they are:" << endl;
00054: cout << "------------------" << endl;
00055:
00056: cout << endl;
00057: int j = 1;
00058: while(kNumRuthAaronPairsNeeded != 0) {
00059:
00060: if(factorSum(j) == factorSum(j + 1)) {
00061: cout << " " << 61 - kNumRuthAaronPairsNeeded <<"). "
00062: << j << " and " << j + 1 << endl;
00063: kNumRuthAaronPairsNeeded--;
00064: }
00065: j = j + 1;
00066: }
00067: cout << endl;
00068:
00069: cout << "All done!" << endl;
00070: return 0;
00071: }






英文版的Emacs使用中文

Aug152007
0 评论

很简单,只要在./emacs加上: (set-language-environment Chinese-GB)
哈蛤,开心死拉。

Emacs字体设置

0 评论

由于 emacs 是个支持多语言的程序,它支持很多种字符集,而一种字体一般只覆 盖一个或几个字符集,因此只用一种字体是无法显示 emacs 支持的所有文字的。 因此在emacs中需要设置 fontset,也就是多种字体的集合,或者叫做字体集。

如果我们不指定 fontset, 那么 emacs 会使用默认的 fontset-default 来显示 字体。如果你觉得这种字体不好看,就需要自己定义 fontset。定义 fontset 有 两种方式,一种是在 ~/.emacs 中使用 create-fontset-from-fontset-spec 函 数,令一种是在 ~/.Xdefaults 中定义资源。我们分别介绍这两种方法。

使用 create-fontset-from-fontset-spec

每个 fontset 都有一个很长的正规名称,例如:

 -*-courier-medium-r-normal--14-*-*-*-*-*-fontset-courier

为了方便起见也可以使用短名称,就是最后两段:fontset-courier

那么这个名称是怎么生成的呢?首先我们用 xlsfonts 命令找到自己满意的字体, 比如:

 -adobe-courier-medium-r-normal--14-100-100-100-m-90-iso8859-1

然后把最后两段去掉,也就是把 iso8859-1 去掉,换上自己起的字体集名称, 比如 fontset-courier,最后把我们不关心的部分用 `*' 号取代就可以了, 注意,用 xlsfonts 列出来的字体名称中,有些字段为 0,这些是可缩放的矢量 字体,这些 0 不能保留,必须用数字或 `*' 号取代,例如,

 -adobe-courier-medium-r-normal--0-0-0-0-p-0-iso8859-1

要改为:

 -adobe-courier-medium-r-normal--14-*-*-*-p-*-fontset-courier

还有一点需要注意,尽量不要选用可缩放的矢量字体,因为 emacs 不支持 xft, 因此无法打开抗锯齿,这些字体会显得很毛糙,不好看。

选定了字体就可以用 create-fontset-from-fontset-spec 函数定义 fontset 了,这个函数很简单,它的参数是个字符串:

(create-fontset-from-fontset-spec
(concat
"-*-courier-medium-r-normal-*-14-*-*-*-*-*-fontset-courier,"
"chinese-gb2312:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gb2312*-*,"
"mule-unicode-0100-24ff:-*-simsun-medium-r-*-*-14-*-*-*-c-*-iso10646*-*,"
"korean-ksc5601:-*-*-medium-r-*-*-14-*-*-*-*-*-ksc5601*-*,"
"chinese-cns11643-5:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,"
"chinese-cns11643-6:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,"
"chinese-cns11643-7:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,"
"sjis:-*-medium-r-normal--14-*-jisx0208*-*"))

这个字符串的第一段是 fontset 的名称,实际上也指定了英文(ascii字符集)字 体,后面的各段格式都是“字符集:字体”,分别为不同的字符集指定字体,例如 上面的定义中,ascii采用courier字体,chinese-gb2312采用simsun字体,以此 类推。

定义好了 fontset 以后,我们就可以让 emacs 使用这个fontset了:

 (set-default-font "fontset-courier")

另外,为了让 emacs 创建新的 frame 时 (C-x 5 系列命令) 采用我们指定的 fontset,还要进行下面的设置:

(setq default-frame-alist
(append
'((font . "fontset-courier")) default-frame-alist))

在 ~/.Xdefaults 中定义 fontset

第二种定义 fontset 的方法是在 ~/.Xdefualts 中定义资源字符串:

Emacs.Fontset-0:-*-courier-medium-r-normal-*-14-*-*-*-*-*-fontset-courier,\
chinese-gb2312:-*-simsun-medium-r-*-*-14-*-*-*-c-*-*-*,\
mule-unicode-0100-24ff:-*-simsun-medium-r-*-*-14-*-*-*-c-*-iso10646*-*,\
korean-ksc5601:-*-*-medium-r-*-*-14-*-*-*-*-*-ksc5601*-*,\
chinese-cns11643-5:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,\
chinese-cns11643-6:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,\
chinese-cns11643-7:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,\
sjis:-*-medium-r-normal--14-*-jisx0208*-*

然后让 emacs 使用这个 fontset:

 Emacs.font: fontset-courier

更改了 ~/.Xdefaults 的内容以后要执行:

 xrdb .Xdefaults

命令,这样更改才能起作用。

上述两种方法都可以实现同样的效果。但是有一点细微的差别,采用第一种方法 时,fontset 的定义是写在 ~/.emacs 中的,而 emacs 启动过程中,是先建立了 第一个窗口,然后才读取 ~/.emacs 的,建立第一个窗口时,因为还没有读到我 们定义的 fontset, 因此它会采用 fontset-default 创建第一个窗口,当读到我 们定义的 fontset 时,再进行调整,如果我们定义的 fontset 与默认的 fontset-default 字体差别比较大,就会看到emacs进行了一个调整窗口大小的动 作,这个动作延缓了 emacs 的启动过程。而采用第二种方法则不会出现这个问题, 因此推荐使用第二种方法。

Fonts Emacs HOWTO

0 评论

Checking font availability
To check if some font is available in emacs do following:

1.Switch to *scratch* buffer.
Type: (prin1-to-string (x-list-fonts "font-you-whant-to-check or pattern")).
2.Place the cursor after the last closing paren and hit C-j.
List of the names of available fonts
matching given pattern will appear in the current buffer (*scratch*).
3.For listing of all available fonts use (prin1-to-string (x-list-fonts "*")).

Which font emacs uses now ( default font)?
Sometimes you want to know what is your default font (font of
default-face), i.e. font you currently use in emacs.
You can do this by performing the following steps :

1.Switch to *scratch* buffer.
2.Type: (frame-parameter nil 'font).
3.Place the cursor after the closing paren and press C-j. Name of default font will appear in current buffer (*scratch*).

My ubuntu desktop

Aug092007
0 评论

cool film!!

0 评论

Live.Free.or.Die.Hard.

ubuntu字体方案--黑体

Aug072007
1 评论

此方法在 Ubuntu 6.06、6.10、7.04 上测试通过。

如果你不喜欢华文黑体,也可以使用其他黑体来代替,修改方法不变。

使用华文黑体 (STHeiti) 替换 Ubuntu 中文字体方法

1、下载 STHeiti 字体

这里下载 stheiti.rar 字体包,解压后复制到 /usr/share/fonts/truetype 下面。

设置 STHeiti.ttf 可读权限:

sudo chmod a+r /usr/share/fonts/truetype/stheiti.ttf

2、设置 STHeiti 为首选中文字体

sudo gedit /etc/fonts/language-selector.conf

找到下面内容所在行(共有三处):
<family>Bitstream Vera .... </family>
在他们下面一行添加:
<family>STHeiti</family>
刷新字体缓存:

sudo fc-cache -f -v

3、设置英文字体和渲染方式

打开 “系统-首选项-字体” 面板:

在字体选项里选择一款英文字体,如:Lucida Grande 或者 Bitstream Vera Sans。在 “字体渲染” 选项中选择 “次象素平滑” 或者 “最佳形状” 。

注意:如果发现在 Firefox 里英文显示不正常,需要在 Firefox 的 “选项 –> 内容 –> 字体和颜色” 中选择一款英文字体,如:Lucida Grande 或者 Bitstream Vera Sans。

4、强制 STHeiti 不使用微调

sudo gedit /etc/fonts/fonts.conf

加入下面一段:

<match target="font">
<test name="family">
<string>STHeiti</string>
</test>
<edit name="hinting">
<bool>false</bool>
</edit>
</match>
OK,使用Ctrl+Alt+BackSpace重启x看效果。

ubuntu主题的删除

0 评论

自行安裝的話,應該是放在家目錄下的子目錄 .theme 底下,佈景的名稱和子目錄的名稱是一樣的,所以你只要將那個子目錄砍掉就可以了。如果你想要重新來過的話,把 .theme 這個子目錄整個砍了都可以。

至 於佈景方面, Gnome 分成三個部分: gtk 2.x theme, metacity theme, icon theme。這三個是可以任意組合的,也就是說當我們選擇『自訂(U)...』,會出現一個佈景主題詳細設定的視窗,其中界面控制是 gtk 2.x theme,視窗邊框是 metacity theme,而圖示是 icon theme。

ubuntu 升级错误!!

0 评论

ubuntu升级错误,failed to write cache!
重新安装7.04并升级,出现错误,提示failed to write cache
解决办法,看到ubuntu台湾网站上有写到。
#!/bin/bash
#
# 修正 Ubuntu 7.04 fc-cache failed to write cache 错误
#

sudo touch /usr/share/fonts
sudo touch /usr/share/fonts/X11
sudo touch /usr/share/fonts/X11/100dpi
sudo touch /usr/share/fonts/X11/75dpi
sudo touch /usr/share/fonts/X11/Type1
sudo touch /usr/share/fonts/X11/encodings
sudo touch /usr/share/fonts/X11/encodings/large
sudo touch /usr/share/fonts/X11/misc
sudo touch /usr/share/fonts/X11/util
sudo touch /usr/share/fonts/truetype
sudo touch /usr/share/fonts/truetype/arphic
sudo touch /usr/share/fonts/truetype/baekmuk
sudo touch /usr/share/fonts/truetype/freefont
sudo touch /usr/share/fonts/truetype/kochi
sudo touch /usr/share/fonts/truetype/openoffice
sudo touch /usr/share/fonts/truetype/thai
sudo touch /usr/share/fonts/truetype/ttf-arabeyes
sudo touch /usr/share/fonts/truetype/ttf-bengali-fonts
sudo touch /usr/share/fonts/truetype/ttf-bitstream-vera
sudo touch /usr/share/fonts/truetype/ttf-dejavu
sudo touch /usr/share/fonts/truetype/ttf-devanagari-fonts
sudo touch /usr/share/fonts/truetype/ttf-gentium
sudo touch /usr/share/fonts/truetype/ttf-gujarati-fonts
sudo touch /usr/share/fonts/truetype/ttf-kannada-fonts
sudo touch /usr/share/fonts/truetype/ttf-lao
sudo touch /usr/share/fonts/truetype/ttf-malayalam-fonts
sudo touch /usr/share/fonts/truetype/ttf-mgopen
sudo touch /usr/share/fonts/truetype/ttf-oriya-fonts
sudo touch /usr/share/fonts/truetype/ttf-punjabi-fonts
sudo touch /usr/share/fonts/truetype/ttf-tamil-fonts
sudo touch /usr/share/fonts/truetype/ttf-telugu-fonts
sudo touch /usr/share/fonts/type1
sudo touch /usr/share/fonts/type1/gsfonts
sudo touch /usr/share/X11/fonts
sudo touch /usr/share/X11/fonts/100dpi
sudo touch /usr/share/X11/fonts/75dpi
sudo touch /usr/share/X11/fonts/Type1
sudo touch /usr/share/X11/fonts/encodings
sudo touch /usr/share/X11/fonts/encodings/large
sudo touch /usr/share/X11/fonts/misc
sudo touch /usr/share/X11/fonts/util
sudo touch /usr/local/share/fonts
sudo touch /var/lib/defoma/fontconfig.d
sudo touch /var/lib/defoma/fontconfig.d/A
sudo touch /var/lib/defoma/fontconfig.d/B
sudo touch /var/lib/defoma/fontconfig.d/C
sudo touch /var/lib/defoma/fontconfig.d/D
sudo touch /var/lib/defoma/fontconfig.d/E
sudo touch /var/lib/defoma/fontconfig.d/F
sudo touch /var/lib/defoma/fontconfig.d/G
sudo touch /var/lib/defoma/fontconfig.d/H
sudo touch /var/lib/defoma/fontconfig.d/J
sudo touch /var/lib/defoma/fontconfig.d/K
sudo touch /var/lib/defoma/fontconfig.d/L
sudo touch /var/lib/defoma/fontconfig.d/M
sudo touch /var/lib/defoma/fontconfig.d/N
sudo touch /var/lib/defoma/fontconfig.d/O
sudo touch /var/lib/defoma/fontconfig.d/P
sudo touch /var/lib/defoma/fontconfig.d/R
sudo touch /var/lib/defoma/fontconfig.d/S
sudo touch /var/lib/defoma/fontconfig.d/T
sudo touch /var/lib/defoma/fontconfig.d/U
sudo touch /var/lib/defoma/fontconfig.d/V
sudo touch /var/lib/defoma/fontconfig.d/a
sudo touch /var/lib/defoma/fontconfig.d/j
sudo touch /var/lib/defoma/fontconfig.d/m
sudo touch /var/lib/defoma/fontconfig.d/u
以上代码写成脚本后执行。
chmod 755 a.sh

Installing Emacs 22 on Ubuntu

0 评论

1.sudo apt-get install cvs
2.cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/sources/emacs co emacs
3.OR Download the source from http://ftp.gnu.org/pub/gnu/emacs/emacs-22.1.tar.gz
4.install essential lib
1)png,ttif,jpeg...
sudo apt-get install libjpeg62-dev
sudo apt-get install libtiff4-dev
sudo apt-get install libungif4-dev
sudo apt-get install libpng12-dev


2)GTK
sudo apt-get install gnome-core-devel
sudo apt-get install libglib2.0-doc libgtk2.0-doc
sudo apt-get install devhelp
sudo apt-get install glade-gnome glade-common glade-doc
3)x-windows
sudo apt-get install xorg-dev
4)important!! in order to avoid error:annot open termcap database file for emacs
sudo
apt-get install libncurses5-dev
5.
./configure –with-gtk –enable-font-backend –with-xft –with-png –with-tiff –with-jpeg –with-freetype
6.if(cvs) make bootstrap
7.make
8.sudo make install

e生成Linux下Makefile的automak全攻略

Aug052007
0 评论

Linux下Makefile的automake生成全攻略

  作为Linux下的程序开发人员,大家一定都遇到过Makefile,用make命令来编译自己写的程序确实是很方便。一般情况下,大家都是手工写一个简单Makefile,如果要想写出一个符合自由软件惯例的Makefile就不那么容易了。

  在本文中,将给大家介绍如何使用autoconf和automake两个工具来帮助我们自动地生成符合自由软件惯例的Makefile,这样就可以象常见的GNU程序一样,只要使用“./configure”,“make”,“make instal”就可以把程序安装到Linux系统中去了。这将特别适合想做开放源代码软件的程序开发人员,又或如果你只是自己写些小的Toy程序,那么这个文章对你也会有很大的帮助。

  一、Makefile介绍

  Makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接,但是不是所有的文件都需要重新编译,Makefile中纪录有文件的信息,在make时会决定在链接的时候需要重新编译哪些文件。

  Makefile的宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。

  Makefile的基本结构不是很复杂,但当一个程序开发人员开始写Makefile时,经常会怀疑自己写的是否符合惯例,而且自己写的Makefile经常和自己的开发环境相关联,当系统环境变量或路径发生了变化后,Makefile可能还要跟着修改。这样就造成了手工书写Makefile的诸多问题,automake恰好能很好地帮助我们解决这些问题。

  使用automake,程序开发人员只需要写一些简单的含有预定义宏的文件,由autoconf 根据一个宏文件生成configure,由automake根据另一个宏文件生成Makefile.in,再使用configure依据 Makefile.in来生成一个符合惯例的Makefile。下面我们将详细介绍Makefile的automake生成方法。

  二、使用的环境

  本文所提到的程序是基于Linux发行版本:Fedora Core release 1,它包含了我们要用到的autoconf,automake。

  三、从helloworld入手

  我们从大家最常使用的例子程序helloworld开始。

  下面的过程如果简单地说来就是:

  新建三个文件:

   helloworld.c
   configure.in
   Makefile.am

  然后执行:

aclocal; autoconf; automake --add-missing; ./configure; make; ./helloworld

  就可以看到Makefile被产生出来,而且可以将helloworld.c编译通过。

  很简单吧,几条命令就可以做出一个符合惯例的Makefile,感觉如何呀。

  现在开始介绍详细的过程:

  1、建目录

  在你的工作目录下建一个helloworld目录,我们用它来存放helloworld程序及相关文件,如在/home/my/build下:

$ mkdir helloword
$ cd helloworld

  2、 helloworld.c

  然后用你自己最喜欢的编辑器写一个hellowrold.c文件,如命令:vi helloworld.c。使用下面的代码作为helloworld.c的内容。

int main(int argc, char** argv)
{
printf("Hello, Linux World!\n");
return 0;
}

  完成后保存退出。

  现在在helloworld目录下就应该有一个你自己写的helloworld.c了。

  3、生成configure

  我们使用autoscan命令来帮助我们根据目录下的源代码生成一个configure.in的模板文件。

  命令:

$ autoscan
$ ls
configure.scan helloworld.c

  执行后在hellowrold目录下会生成一个文件:configure.scan,我们可以拿它作为configure.in的蓝本。

  现在将configure.scan改名为configure.in,并且编辑它,按下面的内容修改,去掉无关的语句:

============================configure.in内容开始=========================================
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_INIT(helloworld.c)
AM_INIT_AUTOMAKE(helloworld, 1.0)

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AC_OUTPUT(Makefile)
============================configure.in内容结束=========================================

  然后执行命令aclocal和autoconf,分别会产生aclocal.m4及configure两个文件:

$ aclocal
$ls
aclocal.m4 configure.in helloworld.c
$ autoconf
$ ls
aclocal.m4 autom4te.cache configure configure.in helloworld.c


  大家可以看到configure.in内容是一些宏定义,这些宏经autoconf处理后会变成检查系统特性、环境变量、软件必须的参数的shell脚本。

  autoconf 是用来生成自动配置软件源代码脚本(configure)的工具。configure脚本能独立于autoconf运行,且在运行的过程中,不需要用户的干预。

  要生成configure文件,你必须告诉autoconf如何找到你所用的宏。方式是使用aclocal程序来生成你的aclocal.m4。

  aclocal根据configure.in文件的内容,自动生成aclocal.m4文件。aclocal是一个perl 脚本程序,它的定义是:“aclocal - create aclocal.m4 by scanning configure.ac”。

  autoconf从configure.in这个列举编译软件时所需要各种参数的模板文件中创建configure。

  autoconf需要GNU m4宏处理器来处理aclocal.m4,生成configure脚本。

  m4是一个宏处理器。将输入拷贝到输出,同时将宏展开。宏可以是内嵌的,也可以是用户定义的。除了可以展开宏,m4还有一些内建的函数,用来引用文件,执行命令,整数运算,文本操作,循环等。m4既可以作为编译器的前端,也可以单独作为一个宏处理器。

4、新建Makefile.am

  新建Makefile.am文件,命令:


$ vi Makefile.am


  内容如下:


AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=helloworld
helloworld_SOURCES=helloworld.c


  automake会根据你写的Makefile.am来自动生成Makefile.in。

  Makefile.am中定义的宏和目标,会指导automake生成指定的代码。例如,宏bin_PROGRAMS将导致编译和连接的目标被生成。

  5、运行automake

  命令:


$ automake --add-missing
configure.in: installing `./install-sh'
configure.in: installing `./mkinstalldirs'
configure.in: installing `./missing'
Makefile.am: installing `./depcomp'


  automake会根据Makefile.am文件产生一些文件,包含最重要的Makefile.in。

  6、执行configure生成Makefile


$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands
$ ls -l Makefile
-rw-rw-r-- 1 yutao yutao 15035 Oct 15 10:40 Makefile
你可以看到,此时Makefile已经产生出来了。

7、使用Makefile编译代码

$ make
if gcc -DPACKAGE_NAME="" -DPACKAGE_TARNAME="" -DPACKAGE_VERSION="" -

DPACKAGE_STRING="" -DPACKAGE_BUGREPORT="" -DPACKAGE="helloworld" -DVERSION="1.0"

-I. -I. -g -O2 -MT helloworld.o -MD -MP -MF ".deps/helloworld.Tpo" \
-c -o helloworld.o `test -f 'helloworld.c' || echo './'`helloworld.c; \
then mv -f ".deps/helloworld.Tpo" ".deps/helloworld.Po"; \
else rm -f ".deps/helloworld.Tpo"; exit 1; \
fi
gcc -g -O2 -o helloworld helloworld.o


  运行helloworld

$ ./helloworld
Hello, Linux World!


  这样helloworld就编译出来了,你如果按上面的步骤来做的话,应该也会很容易地编译出正确的 helloworld文件。你还可以试着使用一些其他的make命令,如make clean,make install,make dist,看看它们会给你什么样的效果。感觉如何?自己也能写出这么专业的Makefile,老板一定会对你刮目相看。

  四、深入浅出

  针对上面提到的各个命令,我们再做些详细的介绍。

  1、 autoscan

  autoscan是用来扫描源代码目录生成configure.scan文件的。 autoscan可以用目录名做为参数,但如果你不使用参数的话,那么autoscan将认为使用的是当前目录。autoscan将扫描你所指定目录中的源文件,并创建configure.scan文件。

  2、 configure.scan

  configure.scan包含了系统配置的基本选项,里面都是一些宏定义。我们需要将它改名为configure.in

  3、 aclocal

  aclocal是一个perl 脚本程序。aclocal根据configure.in文件的内容,自动生成aclocal.m4文件。aclocal的定义是:“aclocal - create aclocal.m4 by scanning configure.ac”。

  4、 autoconf

  autoconf是用来产生configure文件的。configure是一个脚本,它能设置源程序来适应各种不同的操作系统平台,并且根据不同的系统来产生合适的Makefile,从而可以使你的源代码能在不同的操作系统平台上被编译出来。

  configure.in文件的内容是一些宏,这些宏经过autoconf 处理后会变成检查系统特性、环境变量、软件必须的参数的shell脚本。configure.in文件中的宏的顺序并没有规定,但是你必须在所有宏的最前面和最后面分别加上AC_INIT宏和AC_OUTPUT宏。

  在configure.ini中:

  #号表示注释,这个宏后面的内容将被忽略。

  AC_INIT(FILE)

  这个宏用来检查源代码所在的路径。

AM_INIT_AUTOMAKE(PACKAGE, VERSION)

  这个宏是必须的,它描述了我们将要生成的软件包的名字及其版本号:PACKAGE是软件包的名字,VERSION是版本号。当你使用make dist命令时,它会给你生成一个类似helloworld-1.0.tar.gz的软件发行包,其中就有对应的软件包的名字和版本号。

AC_PROG_CC

  这个宏将检查系统所用的C编译器。

AC_OUTPUT(FILE)

  这个宏是我们要输出的Makefile的名字。

  我们在使用automake时,实际上还需要用到其他的一些宏,但我们可以用aclocal 来帮我们自动产生。执行aclocal后我们会得到aclocal.m4文件。

  产生了configure.in和aclocal.m4 两个宏文件后,我们就可以使用autoconf来产生configure文件了。

  5、 Makefile.am

  Makefile.am是用来生成Makefile.in的,需要你手工书写。Makefile.am中定义了一些内容:

AUTOMAKE_OPTIONS

  这个是automake的选项。在执行automake时,它会检查目录下是否存在标准GNU软件包中应具备的各种文件,例如AUTHORS、ChangeLog、NEWS等文件。我们将其设置成foreign时,automake会改用一般软件包的标准来检查。

bin_PROGRAMS

  这个是指定我们所要产生的可执行文件的文件名。如果你要产生多个可执行文件,那么在各个名字间用空格隔开。

helloworld_SOURCES

  这个是指定产生“helloworld”时所需要的源代码。如果它用到了多个源文件,那么请使用空格符号将它们隔开。比如需要helloworld.h,helloworld.c那么请写成helloworld_SOURCES= helloworld.h helloworld.c。

  如果你在bin_PROGRAMS定义了多个可执行文件,则对应每个可执行文件都要定义相对的filename_SOURCES。

  6、 automake

  我们使用automake --add-missing来产生Makefile.in。

  选项--add-missing的定义是“add missing standard files to package”,它会让automake加入一个标准的软件包所必须的一些文件。

  我们用automake产生出来的Makefile.in文件是符合GNU Makefile惯例的,接下来我们只要执行configure这个shell 脚本就可以产生合适的 Makefile 文件了。

  7、 Makefile

  在符合GNU Makefiel惯例的Makefile中,包含了一些基本的预先定义的操作:

make

  根据Makefile编译源代码,连接,生成目标文件,可执行文件。

make clean

  清除上次的make命令所产生的object文件(后缀为“.o”的文件)及可执行文件。

make install

  将编译成功的可执行文件安装到系统目录中,一般为/usr/local/bin目录。

make dist

  产生发布软件包文件(即distribution package)。这个命令将会将可执行文件及相关文件打包成一个tar.gz压缩的文件用来作为发布软件的软件包。

  它会在当前目录下生成一个名字类似“PACKAGE-VERSION.tar.gz”的文件。PACKAGE和VERSION,是我们在configure.in中定义的AM_INIT_AUTOMAKE(PACKAGE, VERSION)。

make distcheck

  生成发布软件包并对其进行测试检查,以确定发布包的正确性。这个操作将自动把压缩包文件解开,然后执行configure命令,并且执行make,来确认编译不出现错误,最后提示你软件包已经准备好,可以发布了。

===============================================
helloworld-1.0.tar.gz is ready for distribution
===============================================
make distclean

  类似make clean,但同时也将configure生成的文件全部删除掉,包括Makefile。

  五、结束语

  通过上面的介绍,你应该可以很容易地生成一个你自己的符合GNU惯例的Makefile文件及对应的项目文件。

  如果你想写出更复杂的且符合惯例的Makefile,你可以参考一些开放代码的项目中的configure.in和Makefile.am文件,比如:嵌入式数据库sqlite,单元测试cppunit。

Emacs自动补全

0 评论

1. Emacs 自带的hippie-expand (参考的是王垠的)
hippie-expand是 Emacs 自带的功能,
把M-/ 绑定到 hippie-expand,在.emacs文件中加入
;;绑定按键
(global-set-key [(meta ?/)] 'hippie-expand)

hippie-expand 的补全方式。它是一个优先列表, hippie-expand 会优先使用表最前面的函数来补全。通常的设置是:

(setq hippie-expand-try-functions-list
'(try-expand-dabbrev
try-expand-dabbrev-visible
try-expand-dabbrev-all-buffers
try-expand-dabbrev-from-kill
try-complete-file-name-partially
try-complete-file-name
try-expand-all-abbrevs
try-expand-list
try-expand-line
try-complete-lisp-symbol-partially
try-complete-lisp-symbol))
首先使用当前的buffer补全,如果找不到,就到别的可见的窗口里寻找,
如果还找不到,那么到所有打开的buffer去找,如果还……那么到kill-ring里,
到文件名,到简称列表里,到list,…… 当前使用的匹配方式会在 echo 区域
显示.
确实是非常好用,基本上我M-/就能到达我想要的了.

2 采用etags
etags能像cscope那样,在代码里跳来跳去,比如查找函数,变量等,它还能够自动补齐代码.
1),先生成etags文件
find . /usr/include/ -name "*.c" -or -name "*.cpp" -or -name "*.hpp" -or -name "*.h" |xargs etags --members --language=c++
2).配置.emacs
(setq tags-file-name "~/TAGS")
3),使用
在emacs中,M-tab 就可以自动补齐了,不过有时候还是不是很好用.
M-. 查找一个tag,比如函数定义类型定义等。
C-u M-. 查找下一个tag的位置
M-* 回到上一次运行M-.前的光标位置。 M-TAB 自动补齐函数名。

3 采用cedet包
1)下载cedet
网址是 http://cedet.sourceforge.net/
2)编译
tar -zxf cedet-1.0pre4.tar.gz
cd cedet-1.0pre4
make
如果make不成功的话,就看看那个说明吧
3)配置
查看emacs的配置文件在哪里
whereis emacs
拷贝编译好了的cedet
cp -r cedet-1.0pre4 /usr/share/emacs/
查看是否有我们需要的那个文件
ls /usr/share/emacs/cedet-1.0pre4/common/cedet.el

配置.emacs文件,在.emacs文件中加入
;;;;;;;;;;cedet
(load-file "/usr/share/emacs/cedet-1.0pre4/common/cedet.el")

;;设置检索范围
(setq semanticdb-project-roots
(list
(expand-file-name "/")));;可以设置为项目的顶级目录

;;绑定按键,ctr+tab,以下三种,任意选择一个,我喜欢第二个
;;(global-set-key [(control tab)] 'senator-complete-symbol);
(global-set-key [(control tab)] ' senator-completion-menu-popup)
;; (global-set-key [(control tab)] 'semantic-ia-complete-symbol-menu)

4)使用
在一个未输入完成的函数上尝试下ctr+tab键

Ken Thompson And Dennis M. Ritchie

Aug022007
0 评论

 
Posted by Picasa

Good Shot

0 评论

 
Posted by Picasa

Pure Nature

Aug012007
0 评论

 
Posted by Picasa

Macintosh' Wallpaper

0 评论

 

Posted by Picasa