2019年8月23日 星期五

Solution for Google Chrome Shortcut Name Changed to LINE after LINE Extension is Installed on Ubuntu

Solution for this issue
https://askubuntu.com/questions/851048/google-chrome-app-name-changed-after-installing-line-from-chrome-web-store/851061

Locate and edit ~/.local/share/applications/_opt_google_chrome_chrome.desktop where content is like below

[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Name=LINE
Icon=google-chrome
Exec=/opt/google/chrome/chrome
StartupNotify=false
StartupWMClass=Google-chrome
OnlyShowIn=Unity;
X-BAMFGenerated=true

Change value of Name, restart Chrome and the name shown on desktop should be changed.

If you are using Gnome Display Manager (GDM) and Chrome does not appear while searching on Activities, remove OnlyShownIn=Unity; and search again.

If this does not work, locate another folder where Google Chrome .desktop lies in, such as /usr/share/applications/, where Name is LINE, change the value and restart Chrome.

Good luck.

2017年1月5日 星期四

Fibonacci with print and value cache

Following is simple way to print Fibonacci(n)

long long fibonacci(int n)
{
    if (n <= 2)
        return 1;

    return fibonacci(n - 1) + fibonacci(n - 2);
}

int main(...)
{
    int ret = 0;
    int n = 0;

    /* Enter n ... */

    for (; i <= n; i++)
        printf("%lld ", fibonacci(i));

    return 0;
}

However Fibonacci(n) is recalculated in numerous times, we can cache the result for future usage

Following is fibonacci with cache, much faster

long long fibonacci(int n, int *printed, long long *cache)
{
    long long value = 0;

    if (cache[n] != 0)
        value = cache[n];
    else
    {
        if (n <= 2)
            value = 1;
        else
            value = fibonacci(n - 1, printed, cache) +
                           fibonacci(n - 2, printed, cache);

        cache[n] = value;
    }

    if (!printed[n])
    {
        printf("%lld ", value);
        printed[n] = 1;
    }

    return value;
}

int main(...)
{
    int ret = 0;
    int n = 0;
    int *printed = NULL;
    long long *cache = NULL;
    /* Enter n ... */

    /* Allocate memory for printed and cache by n ... */

    fibonacci(n, printed, cache); 

    return 0;  
}

2016年12月4日 星期日

Using goto safely

Goto statement is two-edged sword, if we use goto under the premise of structured programming, it's safe and more readable for maintenance.

Following are examples for goto:

1. Releasing allocated memory
2. Solution for deeply nested code
3. Breaking the structured code by goto 4. Abuse of goto

1. Releasing allocated memory at the end of function

int function(...) { int ret = ERR_NONE; type *ptr = NULL; ... /* ptr points to an allocated memory block */ ret = function_a(ptr); if (ret != ERR_NONE) { report_error_log(ret); free(ptr); return ret; } ret = function_b(ptr); if (ret != ERR_NONE) { report_error_log(ret); free(ptr); return ret; } ... return ret; }
You have to write duplicate free for ptr We can use goto to release at the end of function once error occurs int function(...) { int ret = ERR_NONE; type *ptr = NULL; ... /* ptr points to to an allocated memory block */
ret = function_a(ptr); if (ret != ERR_NONE) { report_error_log(ret); goto _exit; }
/* implicit else */
ret = function_b(ptr); if (ret != ERR_NONE) { report_error_log(ret); goto _exit; }
/* implicit else */
... report_function_done_log(); _exit: free(ptr); return ret; } It's pretty much the same when there is ptr and ptr2

By the way, if 3 or above pointers are used in a function,
It's time to think about if part of statements can be extracted to sub function.

2. Solution for deeply nested code

int function(...) { int ret = ERR_NONE; type *ptr = NULL; ... /* ptr points to to an allocated memory block */ ret = function_a(ptr); if (ret == ERR_NONE) { ret = function_b(ptr); if (ret == ERR_NONE) { ... /* in some nested block */ report_function_done_log(); } else { report_error_log(ret); free(ptr); return ret; } } else { report_error_log(ret); free(ptr); return ret; } return ret; }
Deeply nested code layout is less readable for maintainability comparing to style in example 1., it's more readable if adopting goto-style of example 1.

3. Breaking the structured code by goto

Using goto to break a for loop is not safe
Following example breaks the one-in-one-out rule
Unexpected hard-to-debug behavior may occur in this style in unfortunate situation
int ret = ERR_NONE; int i = 0; for (; i < N; i++) { ret = function_x(i); if (ret) { report_error_log(ret); goto _exit; } } ... _exit: do_something(); return ret;

Following style keeps one-in-one-out structure
Using break instead of goto to leave loop At exit of loop, checking return code and goto exit if error occurs In this way the for loop can even be extracted to sub function
int ret = ERR_NONE; int i = 0; for (; i < N; i++) { ret = function_x(i); if (ret) { report_err_log(); break; } } if (ret != ERR_NONE) goto _exit; ... _exit: do_something(); return ret;

4. Abuse of goto

Abuse of goto causes redundant behavior
Following code fails to allocate memory for ptr
No need to free null ptr

int function(...) { int ret = ERR_NONE; type *ptr = NULL; ptr = (type *)malloc(sizeof(type)); if (!ptr) { ret = errno; report_error_log(ret); goto _exit; } ... _exit: free(ptr); return ret; }
So goto can be reduced ptr = (type *)malloc(sizeof(type)); if (!ptr) { ret = errno; report_error_log(ret); return ret; } In conclusion goto is two-edged sword, depends on how we use it

2015年3月30日 星期一

Creating cscope and ctags database for vim

Here is a guide how to establish cscope and ctags database for tracing Android codebase, you can apply the code to any other project in C/C++ or Java. I wrote a script for creating the database with following functions

  • Creating cscope database
  • Creating ctags database
  • Update cscope or ctags databse if they exist
  • Clean cscope and ctags database

Usage under shell after the script is included

  • run run_cscope_ctags to create database
  • run clean_cscope_ctags to clean database
  • run run_cscope_ctags while database exists to update database


Following are steps for using the script, enjoy it.

I. Install related tools
  1. sudo apt-get install cscope
  2. sudo apt-get install ctags
II. Include script for cscope and ctags into .bashrc
  1. vim ~/.bashrc
    append following script for establishing cscope and ctags databse
    #
    # Including cscope ctags script
    #
    source $HOME/path/you/place/run_cscope_ctags.sh
    
  2. vim run_cscope_ctags.sh
    paste following code in the script
    #!/bin/bash
    tags_update="n"
    tags_create="n"
    cscope_update="n"
    cscope_create="n"
    
    function make_ctags()
    {
     ctags_option="-R    \
      --exclude=.git  \
      --exclude=out   \
      --c++-kinds=+p  \
      --fields=+iaS   \
      --extra=+q ."
    
     ctags_option2="-R   \
      --exclude=.git  \
      --exclude=out   \
      --extra=+q ."
    
     if [ $1 == "update" ]; then
      ctags -o newtags $ctags_option2
      rm -f tags
      mv newtags tags
     elif [ $1 == "create" ]; then
      ctags $ctags_option2
     else
      echo Error: wrong ctags option, check the code
      exit 1
     fi  
    }
    
    function make_cscope()
    {
     find `pwd` -path ./out -prune               \
      -o -name "*.aidl"   -exec echo \"{}\" \;\
      -o -name "*.asm"    -exec echo \"{}\" \;\
      -o -name "*.s"      -exec echo \"{}\" \;\
      -o -name "*.S"      -exec echo \"{}\" \;\
      -o -name "*.h"      -exec echo \"{}\" \;\
      -o -name "*.c"      -exec echo \"{}\" \;\
      -o -name "*.cpp"    -exec echo \"{}\" \;\
      -o -name "*.cc"     -exec echo \"{}\" \;\
      -o -name "*.java"   -exec echo \"{}\" \;\
      -o -name "*.xml"    -exec echo \"{}\" \;\
      -o -name "*.dtsi"   -exec echo \"{}\" \;\
      -o -name "*.dts"    -exec echo \"{}\" \;\
      -o -name "*.rc"     -exec echo \"{}\" \;\
      -o -name "*.mk"     -exec echo \"{}\" \;\
      -o -name "*.sh"     -exec echo \"{}\" \;\
      -o -name "*.kl"     -exec echo \"{}\" \;\
      > cscope.files
    
     if [ $1 == "update" ]; then
      cscope -bkq -i cscope.files -f newcscope.out
      rm -f cscope.out cscope.out.in cscope.out.po
      mv newcscope.out cscope.out
      mv newcscope.out.in cscope.out.in
      mv newcscope.out.po cscope.out.po
     elif [ $1 == "create" ]; then
      cscope -bkq -i cscope.files -f cscope.out
     else
      echo Error: wrong cscope option, check the code
      exit 1
     fi
    
     return 0
    }
    
    #
    # Check ctags
    #
    function check_ctags()
    {
     if [ -f "tags" ]; then
      read -p "tags file exists, update it? (y/n) " tags_update
    
     if [ $tags_update = "y" ] || [ $tags_update = "Y" ]; then
      echo "tags is to update"
     elif [ $tags_update = 'n' ] || [ $tags_update = 'N' ]; then
      echo "tags not updated"
     else
      echo "wrong option, quit"
      exit 1
     fi
     else
      read -p "tags does not exist, create new tags? (y/n) " tags_create
     fi
    }
    
    #
    # Check cscope
    #
    function check_cscope()
    {
     if [ -f "cscope.out" ]; then
      read -p "cscope.out exists, update it? (y/n) " cscope_update
    
      if [ $cscope_update = "y" ] || [ $cscope_update = "Y" ]; then
       echo "cscope files is to update"
      elif [ $cscope_update = 'n' ] || [ $cscope_update = 'N' ]; then
       echo "cscope files not updated"
      else
       echo "wrong option, quit"
       exit 1
      fi
     else
      read -p "cscope.out does not exist, create new cscope.out? (y/n) " cscope_create
     fi
    }
    
    #
    # Create ctags and cscope
    #
    function create_ctags_cscope()
    {
     if [ $tags_create = "y" ] || [ $tags_create = "Y" ]; then
      echo "creating tags file"
      make_ctags "create";
      echo "tags created"
     fi
    
     if [ $cscope_create = "y" ] || [ $cscope_create = "Y" ]; then
      echo "creating cscope.out"
      make_cscope "create";
      echo "cscope.out created"
     fi
    }
    
    #
    # Update ctags and cscope
    #
    function update_ctags_cscope()
    {
     if [ $tags_update = "y" ] || [ $tags_update = "Y" ]; then
      echo "updating tags file"
      make_ctags "update";
      echo "tags updated"
     fi
    
     if [ $cscope_update = "y" ] || [ $cscope_update = "Y" ]; then
      echo "updating cscope files"
      make_cscope "update";
      echo "cscope.out updated"
     fi
    }
    
    #
    # Clean current database
    #
    function clean_ctags_cscope()
    {
     rm -f cscope.* ncscope.* tags
    }
    
    #
    # Main function
    #
    function run_cscope_ctags()
    {
     check_ctags;
     check_cscope;
     create_ctags_cscope;
     update_ctags_cscope;
    }
Another options for C++ tagging
http://stackoverflow.com/questions/1932396/c-source-tagging

2015年1月9日 星期五

Making Raspberry Pi a Torrent Box

Installing and setting transmission-daemon

http://wwssllabcd.github.io/blog/2013/04/22/how-to-setup-transmission-deamon-in-raspberry-pi/


http://choorucode.com/2014/07/05/how-to-torrent-on-raspbmc-using-transmission/

Permission settings for download folders

http://www.robertsetiadi.net/installing-transmission-in-raspberry-pi/

Upgrade Ubuntu 13.04 to 14.04 LTS

1. Follow steps in 

http://www.tuxtrix.com/2014/03/upgrade-from-ubuntu-1304-to-ubuntu-1404.html
This is gonna take hours.
There are prompts you need to select when installing new packages, don't leave.

2. If Ubuntu 14.04 LTS boots to tty1

sudo apt-get update 
sudo apt-get install aptitude
sudo aptitude reinstall lightdm
reboot and see if it works, else
sudo aptitude install gdm
reboot

2014年9月6日 星期六

Control Raspberry Pi via VNC and setup virtual server on router/AP

The setup concept is like following diagram

VNC client<-->Internet<-->router<-->Raspberry Pi
  1. Setup VNC server
    • sudo apt-get install tightvncserver
    • vncserver -geometry 1024x768 -depth 24 and set password, this password is only used for VNC login
    • You will require a password to access your desktops.

      Password: 
      Warning: password truncated to the length of 8.
      Verify:   
      Would you like to enter a view-only password (y/n)? n

      New 'X' desktop is raspberrypi:1

      Creating default startup script /home/pi/.vnc/xstartup
      Starting applications specified in /home/pi/.vnc/xstartup
      Log file is /home/pi/.vnc/raspberrypi:1.log
    • :1 is desktop number which stands for VNC port is 5901
  2. Setup virtual server on router/AP
    • Enter virtual server settings in router
    • Name: RPi
    • IP address: loca network address of RPi, 192.168.x.y for example
    • Public port: choose a valid port number, 8899 for example
    • Private port: 5901
    • Protocol: choose both TCP and UDP
  3. Connect to Raspberry Pi
    • Check your worldwide IP address on Internet, w.x.y.z
    • Open VNC client and enter address like w.x.y.z:8899
    • Connect and it should work