KSH coding standard – by Stephen Phil Hill

This post was originated by Stephen Phil Hill (Stephen.p.Hill@alcatel-lucent.com) on Oct 8, 2008. As an experienced developer in SU (software upgrade), Phil has spent years on writing KSH and TCL scripts. More ever, this KSH coding standard has been a necessary manual/rules in ALU for all developers who write shell scripts. This post is allowed by Stephen Hill himself. Any question, comment or suggestion, please leave a message here or email to me (dave.tian@alcatel-lucent.com) or Phil.

NOTE: These suggestions, recommendations, and rules are not actual requirements of the project. Instead they are a combination of recommendations that help improve code efficiency and robustness, recommendations that help smooth the code inspection process, and even some style suggestions. Do not be concerned that you must follow these exactly – but be prepared for a slower code inspection if you disregard them totally.

NOTE: These standards assume ksh93 is being used. At the moment all recommendations and code used illustrating them are also compatible with ksh88. Compatibility with bash is not guaranteed but many of the rules apply equally well to bash code.

To determine the ksh version you are using from the cmd-line, simply enter Ctrl-v. This works in either EMACS or VI line-editing mode.

You can also execute:

    print ${.sh.version}

for the same result.

If your program needs to verify this at run time one other way is to check on specific functionality:

    if [[ $'x' == x ]] ; then
        echo "is using ksh93 parsing"
    fi

some very minimal Style recommendations


RULE : indent via tabs, not spaces or a mixture of tabs and spaces.

RECOMMENDATION: an exception – wrapping long lines. It can look very readable if you indent the wrap the same number of tabs as the first line, plus 4 spaces.

Eg:

   command -a -b -c -d --arg1 stuff --arg2 stuff 
       --arg3 stuff --arg4 stuff

   next command

So the first line is indented one tab. The continuation on the second line is by one tab then 4 spaces. The following line returns to one tab indentation.

This preserves a reasonable alignment for people that use different tabstop settings.


RULE : declare functions before ‘main body’ code in your programs. Don’t mix and match.

Exceptions – maybe loading libraries, typesets of variables, etc.


RECOMMENDATION : Label the main body of the program

At the point of the “main body” start put a ksh comment that includes the word “main”. It helps us old-timer C-programmers out. Eg:

  # Begin "main()" program body.

RULE : at least some minimal function prologs

RECOMMENDATION : It can be pretty brief. Just a sentence or two on what it does.

RULE : Don’t put too much. You don’t want to give explicit detail there and have to update it every time you change one line of code. Be realistic – it won’t be updated and it will be wrong in no time.


Where to put the then or do
if [[ condition ]]
then
   stuff
fi

while [[ condition ]]
do
   stuff
done

-VS-

if [[ condition ]] ; then
   stuff
fi

while [[ condition ]] ; do
   stuff
done

RECOMMENDATION: I have a personal preference for the second/shorter method, but I won’t try to make any rule on that. The separate line version doesn’t seem to add any readability or anything else I can see though…

RULE: Just don’t switch mid-stream. If you are adding 10 lines in an existing function then follow the method used in the rest of that function.

If you are adding a new function then do what you please.


Ordering functions

When creating a library of functions for use by others, order the functions in some logical way – either by functionality of alphabetically.


Coding standards and recommendations


RULE : use the ksh syntax checker

Always test your code with the build-in syntax checker and fix those warnings before you even try the code. Eg:

  ksh -n myscript.ksh

RULE : use the ksh syntax checker on bash code too

If writing bash code, try out the ksh syntax checker on it. You will have to discard some false positives but it is still better than the built-in bash syntax checking.

But also try the bash built-in syntax checker.


RULE : Use [ ] sparingly.

Use of single-square-brackets is somewhat deprecated, largely replaced with double-square-brackets for string and double-paren (( )) for math ops.

It should technically still be allowed for simple tests ( eg, if [ -f myfile ] ) but you will find that many reviewers have a religious zeal for eliminating all uses of [ ]. Use at your own risk.


RULE : Use (( )) for arithmetic expressions.

Using (( )) is almost identical to using ‘let’. Use <>=! style comparison operators. Eg:

   if (( $i > 3 )) ; then

   if (( i > 3 )) ; then

     # note those two forms - using "$i" and using "i"
     # are identical except using "i" is faster

   (( i-- ))

   (( i++ ))

   cmd
   if (( $? != 0 )) ; then

Note: I don’t know of any benefit for using (( )) around simple assignments, eg:

   i=7

RULE : Use double square brackets for string operations.

( couldn’t get the characters through the wiki formatter )

Eg:

   if [[ ${HOST_SIDE} != "A" ]]; then
   if [[ -e ${VALDATA} ]]; then

RULE : Do not use the old Bourne shell command substitution syntax
     x=`cmd`

Instead use the newer KSH syntax for command substitution:

     x=$(cmd)

This is much more flexible, nestable, etc.


RULE : Use the {} in variable references almost all the time.
     Wrong: $x

     Right: ${x}
     Right: ${1}
Also Right: $1

It is hard to justify this rule with technical reasons – in 99.9% of usage it won’t matter at all. It actually comes down to a “Because we said so!” kind of rule, and in SU code you need to match existing style somewhat.


RULE : typeset locals

Prevent collision between the global and function-local namespaces – typeset all your variables in functions.


RULE : global/local variable naming conventions

Make globals distinguishable from locals by name, make global variable names in ALL CAPS.

Locals should be all lower case, though mixed case can be used if you feel it is appropriate.


RULE : no littering the filesystem

no tmp files in random directories – put them somewhere specific, not $CWD

   BAD: cmd > out
   BAD: do_stuff_with out
   BAD: rm -f out

   BETTER: outfile=/var/tmp/out.$$
   BETTER: cmd > ${outfile}
   BETTER: do_stuff_with ${outfile}
   BETTER: rm -f ${outfile}

RULE : clean up tmp files

clean up after yourself, especially in error legs. trap’s are good for this.

    trap "rm -f some_tmp_file ; print -u2 'IT FAILED BADLY'" EXIT

    code
    more code

    # done, clean up and exit.  Clear trap to avoid error message.
    rm -f some_tmp_file
    trap "" EXIT
    print "ALL DONE"
    exit 0

RULE : get return codes from rsh’d commands

'rsh' doesn’t return the remote return code to you. For that reason we have the wrapper function 'remote_sh' for you to use. There is also the ksh script 'remote_shell'.

Rule of thumb: if you are using it multiple times in one script, definitely use remote_sh. If you are only calling it once you can use remote_shell.


RULE : LEARN ABOUT KSH PATTERN MATCHING!!!!!!!!!!!!

*NEVER EVER use*

   echo ${ACRNLIST} | grep [b-km-zA-Z].: > /dev/null
   if [ $? -eq 0 ]; then

instead use ksh pattern matching.

     if [[ "${ACRNLIST}" == [b-k][m-z][A-Z]: ]]; then

RULE : LEARN ABOUT KSH PATTERN SUBSTITUTION!

*Don’t do this, with an external sed process to launch*

   ACRNLIST=$(echo "${ACRNLIST}" | sed "s/,/ /g")

instead use ksh pattern substitution

     ACRNLIST=${ACRNLIST//,/ }

In this example the double-slash means the same as the ‘g’ did for sed. See the manpage.


RULE : LEARN ABOUT KSH SUBSTRING SUPPORT:

*Don’t do this, with an external cut process to launch*

   x=$(echo ${blah} | cut -c3-10)
   y=$(echo ${blah} | cut -c10-)

instead use ksh substring support

   x=${blah:2:8}
   y=${blah:9}

Remember in converting these that it goes from 1-based to 0-based, and from start-to-end to start-and-length. See the manpage.

Anecdote: I spotted a script with one of those ‘echo | cut’ statements in it. It was inside a nested loop and was being hit about 4400 times to parse some data at script startup. It consistently took 55 seconds to run just that loop on ihgp. Changing that ONE LINE appropriately made the nested loop complete in less than 1 second.


RULE : Check user input data types

If the user is typing an answer to a prompt and the script is using it in a way that bad data may cause a ksh syntax error, check that the data is valid.

Eg, verify that it is numeric:

/bin/echo -e "Enter number of apples desired:c"
read A
if [[ "${A}" != +([[:digit:]]) ]];then
    error "answer was not a number"
fi

RULE : Don’t over use ‘rm -fr’

Never use 'rm -fr' on a file, only use the 'r' on a directory.


RULE : Exit with a useful value

Scripts should always exit with a meaningful exit value.


RULE : Return with a useful return value

Functions should almost always return with a meaningful return value.


RULE : Case statements should handle default (usually)

Case statements should almost always include a default case ( with * ) to catch unexpected errors.


RULE : Safer string handling

When comparing strings, use quotes to prevent errors due to unusual strings. Eg:

  if [[ "${my_var}" == "done" ]]; then

NOTE: quoting changes it from a pattern match to a string comparison. If you have a pattern you must NOT quote it but you must escape special characters – eg, whitespace.

  if [[ "${my_var}" == *it is done ]]; then

RULE : checking if a process is alive by PID

When you have the PID of a process and you need to check if it is still running, some people are tempted to construct elaborate pipelines of ps, grep, sed, and cut. Do not! This is done exactly the same way you would in C, with signal 0:

   kill -0 ${pid}
   if (( $? != 0 )) ; then
      # process is finished
      wait ${pid}
      echo "process exited with $?"

RULE : use getopts for argument parsing

Possibly KSH93-specific syntax here?

For parsing arguments, usually use getopts. There are exceptions but most scripts that have their own parsing code end up being messy to use and messy to extend later. A simple example follows illustrating several good points:

  • Supports longname aliases for the short names ( eg, -v is the same as –verbose )
  • Supports longname options that do not have short names ( eg, –help )
  • No #feature dependency concentration on the option spec string since it is multi-line
#
# getopts options spec.
#

OPT_SPEC=":"
OPT_SPEC+="[-][99:-help] "
OPT_SPEC+="[-][98:-examples] "
OPT_SPEC+="[-][v:-verbose] "
OPT_SPEC+="[-][s:-set]: "
OPT_SPEC+="[-][h:-hostname]: "

typeset -u SET_ARG
typeset -i VERBOSE

SET_ARG=""
VERBOSE=0
HOST_ARG=""

# parse command-line
while getopts "${OPT_SPEC}" arg ; do
    case "${arg}" in
    99)
        # --help
        print "${USAGE}"
        scriptexit "${CURR_CMD}" 0
        ;;
    98)
        # --examples
        print "${USAGE}"
        print "${USAGE2}"
        scriptexit "${CURR_CMD}" 0
        ;;
    v)
        ((VERBOSE++))
        ;;
    s)
        SET_ARG=${OPTARG}
        SET="Y"
        ;;
    h)
        HOST_ARG=${OPTARG}
        ;;
    *)
        print "ERROR: Invalid Argument"
        print "${USAGE}"
        scriptexit "${CURR_CMD}" 1
        ;;
    esac
done
shift $(($OPTIND-1))
Posted in Programming | Tagged | 2 Comments

AI – a modern approach: book digest I

1. Studying the root principles of intelligence is much more important than copying the sample.

2. ‘The Logical Structure of the World’, by Rudolf Carnap, 1928, defines a clear process of computing, which is used to extract knowledge from basic experiments – it may be the first theory treating consciousness like process of computing.

3. ‘Nicomanchean Ethics’, by Aristotle – what we need to give a good consideration is means not results.

4. The difference between Cybernetics and AI: Cybernetics uses calculus, matrix algebra to analyze stable and continuously depicted system. More ever, precise analysis could be realized only when the system is pure linear. AI, to certain extent, is finding ways to get ride of the limitations from mathematic methods of Cybernetics, containing tools like linguistics, vision and planning based on logic, induction and deduction.

Posted in AI/ML | Tagged | 1 Comment

AI – a modern approach: book digest 0

From this post, I will begin the series of blogs for book digest of ‘AI – a modern approach’. I plan it as per chapter per blog (wish everything will goes well). Though I am not sure if this is gonna give others some hint, I need to write down something for this book indeed, not only just for my bad memory. Like the comment on the back cover, ‘It is this book making me like AI’. God bless.

Posted in AI/ML | Tagged | Leave a comment

passing 2D array in C – some mistakes and tips

// This is an example source file which is used to show common
// mistakes and tips when passing 2D array as a parameter to a
// function call in C/C++ programming.
// Feb 19, 2011
// dave.tian@alcatel-lucent.com

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define PRINT_ADDR( _var)                                      
        do                                                     
        {                                                      
                printf("addr of var     : 0x%xn", (_var));    
                printf("addr of var[0]  : 0x%xn", (_var)[0]); 
                printf("addr of var[1]  : 0x%xn", (_var)[1]); 
        }                                                      
        while(0);

void subFunc1( char **string)
{
        // SegV
        // Like the gcc’s warning:
        // warning: passing arg 1 of `subFunc1′ from incompatible pointer type
        // Pointer to pointer of char is NOT parameter type of 2-D array
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
}

void subFunc2( char string[][100])
{
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
}

void subFunc3( char *string[2])
{
        // SegV
        // Like the gcc’s warning:
        // warning: passing arg 1 of `subFunc3′ from incompatible pointer type
        // ‘char *string[2]’ is a 1-D array of char pointer with length 2.
        // The address of this case is the same like subFunc1.

        char *str2[2];
        printf("Declaration: char *str2[2];n");
        PRINT_ADDR( str2)
        printf("sizeof(str2)=%d, sizeof(str2[0])=%d, sizeof(str2[1])=%dn",
                sizeof(str2), sizeof(str2[0]), sizeof(str2[1]));

        printf("Processing parameter passing-byn");
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
}

void subFunc4( char (*string)[2])
{
        // Wired Output
        // Like the gcc’s warning:
        // warning: passing arg 1 of `subFunc4′ from incompatible pointer type
        // ‘char (*string)[2]’ here means a pointer to 1-D char array with length 2.
        // ‘string[0]’ is the exact char pointer of ‘msg[0]’, however,
        // ‘string[1]’ is the next char pointer of the next 1-D char arrray with length 2.
        // Below gives the right way to get the pointer of the second string.
        // And subFunc5 shows the right way to use this parameter.

        char (* str2)[2];
        printf("Declaration: char (* str2)[2];n");
        PRINT_ADDR( str2)
        printf("sizeof(str2)=%d, sizeof(str2[0]=%d, sizeof(str2[1])=%dn",
                sizeof(str2), sizeof(str2[0]), sizeof(str2[1]));

        printf("Processing parameter passing-byn");
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
        printf("String 2: %sn", (string[0]+100));
}

void subFunc5( char (*string)[100])
{
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
}

static char msg[2][100];

int main( int argc, char **argv)
{
        if ( argc != 2)
        {
                printf("Pleaes input the function number from 1~4n");
                return 1;
        }

        unsigned int funcNumber = strtoul( argv[1], NULL, 10);

        snprintf( msg[0], (100-1), "%s", "This is the first string");
        snprintf( msg[1], (100-1), "%s", "This is the second string");
        printf("string 1: %snString 2: %sn", msg[0], msg[1]);
        printf("sizeof(char)=%d, sizeof(char *)=%dn", sizeof(char), sizeof(char *));

        switch( funcNumber)
        {
                case 1:
                        printf("Call for subFunc1n");
                        subFunc1( msg);
                        break;
                case 2:
                        printf("Call for subFunc2n");
                        subFunc2( msg);
                        break;
                case 3:
                        printf("Call for subFunc3n");
                        subFunc3( msg);
                        break;
                case 4:
                        printf("Call for subFunc4n");
                        subFunc4( msg);
                        break;
                case 5:
                        printf("call for subFunc5n");
                        subFunc5( msg);
                        break;
                default:
                        printf("Invalid function number %d; valid number is 1~4n", funcNumber);
                        return 1;
        }

        return 0;
}

The output running on a Linux machine is like below:

/home/daveti/Ctest: ./multiDarray
Pleaes input the function number from 1~4
/home/daveti/Ctest: ./multiDarray 1
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
Call for subFunc1
addr of var     : 0x8049d20
addr of var[0]  : 0x73696854
addr of var[1]  : 0x20736920
Memory fault
/home/daveti/Ctest: ./multiDarray 2
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
Call for subFunc2
addr of var     : 0x8049d20
addr of var[0]  : 0x8049d20
addr of var[1]  : 0x8049d84
String 1: This is the first string
String 2: This is the second string
/home/daveti/Ctest: ./multiDarray 3
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
Call for subFunc3
Declaration: char *str2[2];
addr of var     : 0xbf8a0f80
addr of var[0]  : 0xb7e840e4
addr of var[1]  : 0xb7f5a160
sizeof(str2)=8, sizeof(str2[0])=4, sizeof(str2[1])=4
Processing parameter passing-by
addr of var     : 0x8049d20
addr of var[0]  : 0x73696854
addr of var[1]  : 0x20736920
Memory fault
/home/daveti/Ctest: ./multiDarray 4
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
Call for subFunc4
Declaration: char (* str2)[2];
addr of var     : 0xb7f16160
addr of var[0]  : 0xb7f16160
addr of var[1]  : 0xb7f16162
sizeof(str2)=4, sizeof(str2[0]=2, sizeof(str2[1])=2
Processing parameter passing-by
addr of var     : 0x8049d20
addr of var[0]  : 0x8049d20
addr of var[1]  : 0x8049d22
String 1: This is the first string
String 2: is is the first string
String 2: This is the second string
/home/daveti/Ctest: ./multiDarray 5
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
call for subFunc5
addr of var     : 0x8049d20
addr of var[0]  : 0x8049d20
addr of var[1]  : 0x8049d84
String 1: This is the first string
String 2: This is the second string
/home/daveti/Ctest:

Posted in Programming | Tagged , | Leave a comment

LightRadio – a base station that fits in your hand

Official information from Alcatel-Lucent: (http://all.alcatel-lucent.com/wps/portal/cf/lightradio#tabAnchor1) From around 2009~2010, Alcatel-Lucent Bell Labs starts ‘GreenTouch‘ focusing on eco-sustainable networks, enabling a low carbon economy, innovation and engagement, reducing Alcatel-Lucent’s carbon footprint. In 2011, as a response to that ‘Green’, ‘LightRadio’ is invented as a real thing.

As a challenge to traditional RAN (radio access network, including base station and antennas), the main difference of LR (short of LightRadio) is  the ability to dynamic deployment – hanging on street signs or anywhere there is power and broadband connection, and taking advantages of ‘cloud’, comparing with RAN’s static configuration – not easy to move and special place to install, and its non-distributed way of computing provided by base station. Even though there is detailed data of LR published, we could figure out the reason its facing LTE – using MIMO – the key technology of antenna in LTE. That’s why we could zip LR into your hand. When we take a consideration of ‘cloud’ part, it is easy to find there would be a new distribute computing architecture of management of these LRs covering the whole network instead of per base station – This is a higher level of management which should provide more intelligence, better and faster solutions, like a network level of load balance, for example. However, there is also one question left for us – Is this ‘cloud’ provided by LTE core network (like MME) or reusing/leasing public/special IT ‘cloud’ or there may be a new ‘cloud’ constructed by Carrier itself. Whatever the answer is, ‘cloud’ is stepping into telecommunication indeed.

Posted in Uncategorized | Tagged , , , , | 1 Comment

blog.com is blocked by the Chinese Government – do the right thing – some thoughts on GFW

Once it happens, it happens fast. Even though support@blog.com has fixed the bug in spam filter, people in China mainland are unable to access any XXXX.blog.com. Yes, Blog.com is blocked by Great Firewall of China (aka for GFW), like Facebook, YouTube, Twitter and Time. Again, I still insist on NPNP (no porn no politics) in my blog instead of asking the government for ‘Do no harm’. However, I do believe in freedom of speech. When it is hard for the government to do no harm to everyone, it is the very time for everyone to do the right thing. (BTW: this post is written via a SSH tunnel server in US to bypass GFW!)

Posted in Uncategorized | Tagged , , | 4 Comments

happy chinese new year – do the right thing – some thoughts on software

(The pic above was taken on Feb 3, 2011 – Chinese New Year, Spring Festival – my Jackson and Squier) Happy Chinese New Year – the year of rabbit 过年好, my dear friends:) though it seems a little late…I have been trying to get access to my blog since Feb 2, 2011 and could not make it through until now. I thought blog.com was blocked by the Chinese Government (as you might know already there is a IP filter system called Great FireWall aka. for GFW in China mainland for website blocking because of political reason. The famous blocked websites include YouTube, Facebook and etc..) as the only way for me to access my blog was proxy, like kproxy.com. Further more, besides opening a ticket to support@blog.com, I planned to buy a VPN and use OpenVPN. Frankly, I was out of rage indeed as there was no reason to block my blog. It was, is and will be NPNP – NO PORN, NO POLITICS! The good news is blocking was caused by spam filter of blog.com itself instead of GFW and it is fixed. However, 7-day blocking of my blog do give me some hints on Software:

1. The more people like it, the deeper it would hurt – I have a deep feeling for this right now. Even though the blog service is totally free, there is a hidden contract of trust between user and service provider. It may be hard (kinds of reasons) to attract customers but very easy (only one reason) to push them away. Trust me!

2. The deeper it may hurt, the more responsibility the company needs to take – No doubt as long as you still agree with the words: Customer is God.

3. The more responsibility you need to take, the more testing you need to do – This is based on the assumption that the feature is necessary and the design is considerate. If it is true, then try to determine what kind of bugs could be reported by user and what kind should not. If the ‘should not’ ones happen on user, what is the impact, both impact to the company and customer.

4. The more testing you need to do, the more automatic it should be – Automation testing should be a very complicated function area which is always underestimated because of marketing policy. Personally, I do agree with the point ‘We have no time for testing’ as long as new product developement used to marketing is the first priority indeed. Otherwise, please think abut the relationship among testing, quality and brand on Software.

5. The more automatic it should be, the more detailed it should be – Unit Testing, Feature Testing, Beta Version, Internal Testing, Public Testing…There are tons of different testings covering different stages. There should be a good and practical combination for these testing per product or project. Take an example, in Lucent, the different stages for testing are UT(Unit Tesing), DT(Deliverable Testing), FT(Feature Testing) and NLT(Network Level Testing). Different testings are used to find different bugs.

6. The more detailed it should be, the more classic and modern approaches it needs – Yes, I mean both, the classic approaches and the modern ones. I never doubt the power of ‘old’ Tcl/Tk, Perl, Shell, SOAP, XML and etc – they are classic and useful. However, it would be prefect if we could take use of new modern approaches like new languages, Python, JavaScript, like Agile testing, TDD, BDD, like new testing tools/lib, Coverity, JUnit. I have to admit that I am NOT familiar with testing or I am only familiar with code static analysis (Coverity) and UT as a software developer. However, my developer experience does not prevent me from asking this question: do we have take full use of classic and modern approaches to guarantee the quality and save the time to deliver the product?

7. Do the right thing – Per Google’s words ‘Do no harm’. It would be great if ‘Do no harm’. I mean, yes, this should be the bottom line for us to live with. However, though declaring a never-used variable is ‘Do no harm’, I do not think this line of code could be passed by code inspection:) I once asked myself this question: why do i like programming? I spent a few weeks to find my answer – to purchase the fairness, which may not be possible to purchase. (I do not plan to explain my answer here, maybe another post:) In the word of software, everyone obeys 2 basic rules: 1. No pain no gain. 2. There is always one way to get close to being perfect. In this word, ‘Do the right thing’ should be the bottom line for everyone.

Posted in Programming | Tagged , , , | 6 Comments

ZIYO-The Return-Love is like yesterday

#Band(乐队)    : ZIYO(自游乐队)
#Album(专辑)    : The Return(回到我)
#Song(曲目)    : Love is like yesterday(爱像是昨天)
#Tab(扒谱)    : daveti
#Lyric(歌词)    : Web
#Time(时间)    : Jan 21, 2011
#Email(邮箱)    : dave.tian@alcatel-lucent.com
#Rhythm(节奏)    : C|Am|Dm|G


1————–0————0————-1————3——
2———-3————1————–3————-0———-
3——–0—0——-2—2———2—2——–0—0——–
4———————————0—————————–
5——3———–0——————————————–
6———————————————-3—————-

1—–8-10-8—7-8-10-8—10-12-10—8-7-8-10—–
2—–8-10-8—7-8-10-8—10-12-10—8-7-8-10—–
3——————————————————
4——————————————————
5——————————————————
6——————————————————

赶在夜幕吞噬前的一瞬间 记忆点燃一只烟
点燃一支烟
想想最后谁还会在谁身边
会是谁谁谁
还会不会
那些爱过的人 伤过的人 哭过的人 恨过的人
在哪里
一路上还有多少雨水泪水等我去回忆
有时世界仿佛只剩一半
有些骄傲随着时间溜走被冲淡
有人站在旷野独自呼喊
有些忧伤不知何时会消散
有人站在心里停滞不前
有人站在原地等着一切再出现
是我的爱情 自我欺骗
像是昨天
像是那昨天
是否
曾和某人在某个时间
牵着手幻想明天
谁也不改变
对着天空说一定要爱很远
到现在是谁忘了当初的勇敢
那些爱过的人 伤过的人 哭过的人 恨过的人
在哪里
一路上还有多少雨水泪水等我去回忆
有时世界仿佛只剩一半
有些骄傲随着时间溜走被冲淡
有人站在旷野独自呼喊
有些忧伤不知何时会消散
有人站在心里停滞不前
有人站在原地等着一切再出现
是我的爱情 自我欺骗
像是昨天
像是那昨天
乎 耶
就唱一首歌给自己听
忘记你声音
忘记你
声音
就唱一首歌给自己听
忘记你声音
忘记你
声音
就唱一首歌给自己听
忘记你声音
忘记你
就唱一首歌给自己听

有时世界仿佛只剩一半
有些骄傲随着时间溜走被冲淡
有人站在旷野独自呼喊
有些忧伤不知何时会消散
有人站在心里停滞不前
有人站在原地等着一切再出现
是我的爱情 自我欺骗
像是昨天
像是那昨天……

Posted in Music Prose | Tagged , | Leave a comment

to record my stupid mistake in programming

This post is used to record one mistake while my coding – just for my bad memory:) I have to admit that it spent me the whole day to figure out what was wrong, as it looked prefect except parse error during compiling. At least 2 things are revealed: 1, I suck on C; 2, I need to learn compiler theory…

#include <stdio.h>
#include <stdlib.h>

typedef struct _Big{
 char big;
 int bigInt;
}Big;

typedef struct _Bigger{
 char bigger;
 Big *bigP;
}Bigger;

typedef struct _Biggest{
 char biggest;
 Bigger *biggerP;
}Biggest;

#define GET_BIG( _biggestP) 
 ((_biggestP)->biggerP->bigP)

#define BIGINT_IS_ONE( _biggestP, _bigInt) 
 ( 1 == GET_BIG( _biggestP)->(_bigInt))
 // daveti: insane happens here, like 'xxx->(xxx)'

int main(void)
{
 Biggest *bP = calloc( 1, sizeof( Biggest));
 bP->biggerP = calloc( 1, sizeof( Bigger));
 bP->biggerP->bigP = calloc( 1, sizeof( Big));

 bP->biggerP->bigP->bigInt = 2;
 printf( "i = %sn"
 ,( BIGINT_IS_ONE( bP, bigInt) ? "one" : "not one")
 );

 return 0;
}
Posted in Programming | Tagged | 1 Comment

write your own function with varying arguments

This post is used to tell how to write your own function with varying arguments (如何写变参函数) – we will write our own ‘printf()’ function called ‘ddLog()’. Wish the code below would give you a hint:)

/*
* This source file is used to show an example on
* writing function with a varying number of arguments
* of varying types, like printf() and snprintf().
* Originated: Jan 12, 2011
* dave.tian@alcatel-lucent.com
*/

#include <stdio.h>
#include <string.h>
#include <stdarg.h>

/* var arg function declaration */
int ddLog( const char *, …);

int main( void)
{
int date = 20110112;
char at = ‘@’;

ddLog( “This is a demo function”
” used to show how to write”
” var arg function based on”
” ANSI stylen”
“-%s%c%dn”,
“daveti”, at, date);

return 0;
}

/* ddLog() is some kind of like printf() */
int ddLog( const char *msg, …)
{
char outPut[ 1000];
char *outP = outPut;
// Var arg structure
va_list argS;
// Determine if it is format string
char *percentP = NULL;
// Pointer for each arg
char *argP;
char argChar;
int argInt;

// Start var arg parsing
va_start(argS, msg);
while ( *msg != ”)
{
if ( *msg == ‘%’)
{
percentP = msg;
msg++;
continue;
}

if ( percentP != NULL)
{
switch ( *msg)
{
case ‘s’: //string
argP = va_arg( argS, const char *);
outP += snprintf( outP, (1000+outPut-outP), “%s”, argP);
break;
case ‘c’: //char
argChar = (char) va_arg( argS, int);
outP += snprintf( outP, (1000+outPut-outP), “%c”, argChar);
break;
case ‘d’: //int
argInt = va_arg( argS, int);
outP += snprintf( outP, (1000+outPut-outP), “%d”, argInt);
break;
default:
// Un-supported format string
// Copy the ‘%’ and un-supported char here
*outP++ = ‘%’;
*outP++ = *msg;
break;
}
percentP = NULL;
msg++;
continue;
}

*outP++ = *msg++;
}

// Copy the ” at the end
*outP = ”;

// End var arg parsing
va_end(argS);

printf(“%s”, outPut);
return strlen( outPut);
}

Posted in Programming | Tagged | Leave a comment