8.2 Simple Programming under Linux

8.2.1 Perl

perl

Powerful and widely used scripting language, very popular among gurus. Perl looks cryptic yet it is quite straight-forward if you need to achieve simple tasks. Think of perl as a swiss-army knife for simple programming. Perl's syntax parallels that of the "C" language. Excellent implementation of the perl interpreter is available for MS Windows so you code can be cross-platform. Here is how Eric Reymond (famous Linux guru) describes perl: "Perl, of course, is the 800-pound gorilla of modern scripting languages. It has largely replaced shell as the scripting language of choice for system administrators, thanks partly to its comprehensive set of UNIX library and system calls, and partly to the huge collection of Perl modules built by a very active Perl community. The language is commonly estimated to be the CGI language behind about 85% of the ``live'' content on the Net. Larry Wall, its creator, is rightly considered one of the most important leaders in the Open Source community, and often ranks third behind Linus Torvalds and Richard Stallman in the current pantheon of hacker demigods."

How do I write a simple perl script?

I may use pico (or any other text editor of my choice) to type in a simple perl script:

pico try_perl

The example script below does nothing useful, except illustrates some features of perl:

#!/usr/bin/perl -w

# a stupid example perl program

# the lines starting with # are comments except for the first line

# names of scalar variables start with $

$a=2;

$b=3;

# each instruction ends with a semicolon, like in "c"

print $a**$b,"\n";

$hello_world='Hello World';

print $hello_world,"\n";

system "ls";

The first line tells the shell how to execute my text file. The option "-w" causes perl to print some additional warnings, etc. that may be useful for debugging your script. The next 3 lines (starting with #) are comments. The following lines are almost self explanatory: I assign some values to two variables ($a and $b), put $a to power $b and print the result. The "\n" prints a new line, just like in the "c" programming language. Then I define another variable to contain the string "Hello World" and, in the next line, I print it to the screen. Finally, I execute the local operating system command "ls", which on Linux prints the listing of the current directory content. Really stupid script.

After saving the file, I make it executable:

chmod a+x try_perl

Now, I can run the script by typing:

./try_perl

Here is somewhat longer script that does something very simple yet useful to me. I take a long text file which is generated by a data acquisition system. I need to erase every other line (or so) so that the file can be crammed into MS Excel (as required):

#!/usr/bin/perl -w

# Create a text file containing a selection of lines from an original file. This is needed

# so that data for manual postprocessing are fewer.

#

# Prompt the user for the filename, and the selection of lines to preserve in the output.

print STDOUT "Enter the filename: ";

chomp($infile=<STDIN>);

open(INFILE,"<$infile"); # open the file for reading.

print STDOUT "Enter the number of initial lines to preserve: ";

chomp($iskip=<STDIN>); # the first lines may contain column headings etc

print STDOUT "Enter the skip: ";

chomp($skip=<STDIN>);

#

# The name of the output file is created automatically on the basis of the

# input file and the selection of lines. It is always of type CSV, so preserve is so.

$outfile=$infile.'-pro'.$iskip.'-'.$skip.'.csv'; #glue strings together using the dot operator.

open(OUTFILE,">$outfile"); # open file for writing.

#

# write the "initial" lines to the output file.

for($a=0;$a<$iskip;$a++) {

$line=<INFILE>;

print OUTFILE $line;

}

#

# do the rest of the file

$c=0;$w=0;$skip++;

while($line=<INFILE>){

$c++;

if(!($c%$skip)) { #use % for remainder of integer division

print OUTFILE $line;

$w++;

}

}

#

close(OUTFILE);

print STDOUT "Read Lines: ", $c+$iskip," Wrote lines: ", $w+$iskip,"\n";

8.2.2 Python

python

Modern and very elegant object oriented interpreter. Powerful and (arguably) more legible than perl. Very good (and large) free handbooks by G. van Rossum (the Python creator) are available on the net (try: http://www.python.org/doc/ for browsing or ftp://ftp.python.org for downloading).

How do I write a simple Python program?

Edit a text file that will contain your Python program. I can use the kde "kate" editor to do it (under X):

kate try_python.py &

Type in some simple python code to see if it works:

#!/usr/bin/env python

print 2+2

The first line (starting with the "pound-bang") tells the shell how to execute this text file--it must be there (always as the first line) for Linux to know that this particular text file is a Python script. The second line is a simple Python expression.

After saving the file, I make it executable:

chmod a+x try_python.py

after which I can run it by typing:

./try_python.py

Python is an excellent, and very modern programming language. Give it a try, particularly if you like object oriented programming. There are numerous libaries/extensions available on the Internet. For example, scientific python (http://starship.python.net/crew/hinsen/scientific.html) and numeric python (http://sourceforge.net/projects/numpy) are popular libraries used in engineering.

Here is a slightly longer, but still (hopefully) self-explanatory python code. A quick note: python flow control depends on the code indentation--it makes it very natural looking and forcing legibility, but takes an hour to get used to.

#!/usr/bin/env python

# All comments start with a the character "#"

# This program converts human years to dog years

# get the original age

age = input("Enter your age (in human years): ")

print # print a blank line

# check if the age is valid using a simple if statement

if age < 0:

print "A negative age is not possible."

elif age < 3 or age > 110:

print "Frankly, I don't believe you."

else:

print "That's the same as a", age/7, "year old dog."

8.2.3 tcl

tcl

(Pronounced "tickle".) Popular scripting language.

A simple tcl program?

#!/usr/bin/tclsh

puts stdout {Hello World!}


wish

(type in X-terminal ) A front-end to Tk, an X-windows extension of tcl. Often used for building front-ends of a program.

How do I write a simple GUI program (using Tk)?

Tk is a GUI extension of the easy yet powerful tcl programming language. For example, I may use pico to create a text file that will contain a simple tk program:

pico try_tk

and type in a simple example of tk code to see if it works:

#!/usr/bin/wish

button .my_button -text "Hello World" -command exit

pack .my_button

The first line (starting with the "#!" pound-bang) tells the shell what utility to use to execute my text file. The next two lines are an example of a simple tk program. First, I created a button called "my_button" and placed it at the root of my class hierarchy (the dot in front of "my_button"). To the button, I tied the text "Hello World" and a command that exits the program (when the button is pressed). Last line makes my program's window adjust its size to just big enough to contain my button.

After saving the file, I make it executable:

chmod a+x try_tk

after which I can run it by typing (in the X-terminal, because it requires X-windows to run):

./try_tk

Tk is very popular for building GUI front ends.

8.2.4 ruby

ruby

A purely object-oriented scripting language. This language is a relative newcomer, but it is rapidly gaining popularity, and may well be the flavour of the future of programming.

To write a simple program in ruby, I open my favorite text editor and start a program with the following first line:

#!/usr/bin/ruby

Here is an example of a program that I wrote to help me understand the basics of the ruby language:

#!/usr/bin/ruby

#This is a comment

a = Array.new

print "Please enter a few words (type EXIT to stop):\n"

i = 0

while enterWord = STDIN.gets

enterWord.chop!

if enterWord == "EXIT"

break

end

a[i] = enterWord

i += 1

end

#sort the array

for i in 0...a.length-1 do

for j in i+1...a.length do

if a[j] < a[i]

tmp = a[i]

a[i] = a[j]

a[j] = tmp

end

end

end

#Output the results

print "You entered " + a.length.to_s + " entries.\n\n"

for i in 0...a.length do

print "Entry " + (i+1).to_s + ": "+ a[i] + "\n"

end

I save my ruby script to file "myprogram". To execute it, I need to type on the command line:

./myprogram

8.2.5 C

gcc filename.c

GNU C compiler. Quite straight-forward if you know C. Extensive free manuals are available on the net.

How do I compile a simple C program?

Start your favourite text editor and type in your source code. For example, I may use pico:

pico hello.c

and type in the Kerningham and Richie (the creators of "c") intro example of a C program:

#include <stdio.h>

void main(void) {

printf("hello world\n");

}

I save the file and then invoke the GNU C compiler to compile the file "hello.c":

gcc hello.c

The gcc compiler produces an executable binary file "a.out", which I can run:

./a.out

8.2.6 C++

g++ filename.C

GNU C++ compiler. The capital "C" is often used for C++ sources. If you need an "integrated development environment" (IDE), kdevelop is really something you would probably like to look at.

How do I compile a simple C++ program?

Just like in c, I open a text editor and write my program. For example, using pico, I write the following program:

//This is a comment (to the end of line, C++ style)

#include <stdio.h>

#include <math.h>

#include <iostream.h>

#include <stdlib.h>

//define a function

double wheeldrop (double dGap, double dDiameter) {

double dDrop, dRadius, dNotDrop;


dRadius = dDiameter * 0.5;

dDrop = dRadius - sqrt( (dRadius*dRadius)-(0.25*dGap*dGap) );


return (dDrop);

} //end of the function


//The function main is the entry point to the program

void main(void) {

double dGap, dDiameter, dDrop, dRadius, dNotDrop; //variables


for (;;) { //infinite loop

cout << "Please enter gap between track segments and \n"

<< "diameter of train wheel in inches (-1 -1 to exit): ";

cin >> dGap >> dDiameter;


if ((dGap == -1) && (dDiameter == -1))

break;

else if (dGap < dDiameter) { //do calculations

dDrop = wheeldrop (dGap, dDiameter);

printf ("The wheel will drop %f inches.\n\n", dDrop);

}

else {

printf ("Error, your train is going to crash.\n Gap bigger then wheel!\n\n");

}

}

}

I save the source to the file "train.c", and then invoke the GNU C++ compiler to compile the file "train.c" to an executable called "traincalc":

g++ -o traincalc train.c

I can then run the executable by typing:

./traincalc


kdevelop

(type in X-terminal) Integrated development environment for K. It is really worth downloading (if it does not come with your distribution).


glade

(type in X-terminal) A graphical builder of user interfaces.

"Glade is an interface builder developed by Damon Chaplin. It allows graphical and interactive construction of Gnome/Gtk graphical user interfaces. From Glade, the generated interface can be saved in a xml file or directly exported to C code to be included in a C source tree. Glade also allows to define the name of the handlers - functions - to be attached to the various event of the interface. For example the function (name) to be called when a specific menu item is pressed." (From: http://linuxtoday.com/news_story.php3?ltsn=2000-07-16-013-04-PS-GN)

What "C" functions are available for programming under Linux?

Too many for a newbie like myself. I started by studying the header files (*.h) in the directory /usr/include and all its subdirectories. To find a header file that contains a prototype for a given function (e.g., cosh) I would do something like:

cd /usr/include

grep -H "cosh" *.h

There are also many interesting libraries that are not a part of a typical distribution, e.g., GNU libraries for scientific computing (GSL): http://sources.redhat.com/gsl/. Also check: http://www.phy.duke.edu/~hsg/sci-computing.html.

8.2.7 Assembler

as

nasm

ndisasm

(3 commands). Assembler, an alternative "native assembler" and a disassembler. Send in your newbie examples how to use those :) E.g.: ndisasm /bin/sh |more produces a long output of "assembler mnemonics" from a binary on my system (/bin/sh in this example) but I cannot understand it anyway :( To learn more about nasm, you may want to see: file:///usr/share/doc/nasm-doc-0.98/html/nasmdoc0.html

Example Intel assembly for Linux 2.2.17 or higher:

;; hello.asm: Copyright (C) 2001 by Brian Raiter, under the GNU

;; General Public License (version 2 or later). No warranty.


BITS 32


org 0x05936000


db 0x7F, "ELF"

dd 1

dd 0

dd $$

dw 2

dw 3

_start: inc eax ; 1 == exit syscall no.

mov dl, 13 ; set edx to length of message

cmp al, _start - $$

pusha ; save eax and ebx

xchg eax, ebx ; set ebx to 1 (stdout)

add eax, dword 4 ; 4 == write syscall no.

mov ecx, msg ; point ecx at message

int 0x80 ; eax = write(ebx, ecx, edx)

popa ; set eax to 1 and ebx to 0

int 0x80 ; exit(bl)

dw 0x20

dw 1

msg: db 'hello, world', 10

After saving this to a plain-text file hello.asm, I can build it to an output file "hello" and make the output executable using the command:

nasm -f bin -o hello hello.asm && chmod +x hello

and execute it using:

./hello

The example above is borrowed from http://www.muppetlabs.com/~breadbox/software/tiny/.

Why would somebody use assembler? After building from assembler, this example executable is 56 bytes on my system. The "C" language example with identical functionality (see one page above) is 13.7 kB.

Here is brief info to help me understand the above program:

";" marks comments (to the end of the line).

"msg:" -- is an example of a label (like in FORTRAN).

org (="origin")--declares where in the memory the program begins (after it is loaded to memory for execution).

db, dd, dw are nasm "pseudoinstructions" used to insert initialized data into the output file.

"$" evaluates to the assembly position at the beginning of the line containing the expression; so you can code an infinite loop using "JMP $". "$$" evaluates to the beginning of the current section.

The general-purpose 32-bit registers in the 80x86 ("Intel") processor are: EAX, EBX, ECX, EDX, ESI, EDI, EBP, and ESP. (The "E" stands for extended. It is there because the processor can instead "overlay" the registers and treat them as 16-bit registers with names: AX, BX, CX, CX, SI, DI, BP, and SP. Still underlying those, there are also eight 8-bit registers: AL, AH, BL, BH, CL, CH, DL, DH. Here, the "L" and "H" stand for "high" and "low" byte.).

Mnemonics for some common 80x86 processor instructions:

Name Syntax Comment

NOP NOP No operation (do nothing).

MOV mov destination, source Move (copy, set)data.

XCHG XCHG operand1,operand2 Exchange the values.

CMP CMP operand1,operand2 Compare the two operands.

PUSH PUSH source Push onto stack.(Place the value on stack and increment the stack pointer).

PUSHF PUSHF Push flags.

PUSHA PUSHA Push all general-purpose registers.

POP POP destination Pop from stack(take the value from stack, and decrement the stack pointer). Pop is reverse to push.

POPF POPF Pop flags.

POPA POPA Pop all general-purpose registers.

INC INC operand Increment (increase by 1).

DEC DEC operand Decrement (decrease by 1).

ADD ADD Dest,Source Add.

ADC ADC Dest,Source Add with carry.

SUB SUB Dest,Source Subtract.

INT INT number Execute an interrupt.

CALL CALL subroutine Call a subroutine.

RET RET Return from this (current, innermost) subroutine.

JMP JMP destination Jump (start executing code starting at the the address "destination")

JE JE destination Jump if equal.

JNE JNE destination Jump if not equal.

JZ JZ destination Jump if zero.

JNZ JNZ destination Jump if not zero.

JP JP destination Jump if parity (parity is even).

JNP JNP destination Jump if no parity (parity is odd).

JPE JPE destination Jump if parity even.

JPO JPO desitination Jump if parity odd.

JCXZ JCXZ destination Jump if CX zero.

JECXZ JECXZ destination Jump if ECX zero.

8.2.8 Scheme

guile

An implementation of "Scheme" programming language. Scheme is a modern dialect of the LISP language (the one that has been promising the artificial intelligence for the last 40 years).

Silly examples for the guile interpreter.

guile

(+ 1 1)

(define a 2)

(/ a 3)

(= a 7)

(display "hello\n")

(system "ls")

(exit)

The first command runs the guile interpreter. The next four commands do addition, definition, division, and comparison using the so-called Polish notation (operator in front of the operants). See the section on reverse Polish notation on this page. The last command exits the guile interpreter.

8.2.9 FORTRAN

g77

GNU FORTRAN. An on-line manual is available at: http://gcc.gnu.org/onlinedocs/g77/. If you are really into FORTRAN, you might also want to check: http://studbolt.physast.uga.edu/templon/fortran.html to find a FORTRAN compiler that suits your particular needs under Linux.

Silly example of a Fortran code. It prints squares and cubes of numbers from 1 to 20:

PROGRAM TRY_FORTRAN

INTEGER X

PRINT 200, "X", "X^2", "X^3"

DO X=1, 20

PRINT 100, X, X**2, X**3

END DO

100 FORMAT (I20, I20, I20)

200 FORMAT (A20, A20, A20)

END

To compile this file, I run the fortran compiler with the option that recognizes the "free-form" source code (I don't like the fixed-code source):

g77 -ffree-form try_fortran.f

and now I can run the resulting executable (which has the default name is a.out):

./a.out

8.2.10 expect

expect

Scripting language for "programmed dialog". See man expect and email us a good illustration of how to use it :)

8.2.11 Delphi

kylix

This is a brand-new (Feb.2001) commercial offering from Borland (aka Inprise). In short, it is a Linux port of the famous object-oriented Pascal ("Delphi"). kylix is unlikely to be on your Linux distribution CD, you must pay for it, but if you want the best rapid application development (RAD) platform with a code portability between Linux, MS Windows and the Web, large number of pre-built components, etc., kylix is likely the best. In my opinion, Delphi is significantly better than MS Visual Basic.

8.2.12 Java

javac

java

The Java language compiler and interpreter. Under Linux, both javac and java are actually scripts which call kaffe with appropriate options (try cat /usr/bin/java).

A trivial example for a java "standalone" program. I use my favourite text editor, e.g. kate (in X terminal) to type in the following java code:

/* Comments are marked like in C++

* A java class to display "Hello World"

*/

class HelloWorldApp {

public static void main(String[] args) {

System.out.println("Hello World."); // Print "Hello World." followed by a newline

}

}

I save this into a file named try_java.java. Now, I can compile it using:

javac try_java.java

This creates a file called HelloWorldApp.class which contains the "bytecode" (semi-compiled code which requires an interpreter to run). I can run it on the command line using:

java HelloWorldApp

For an example on how to embed a simple java applet into an html web page, have a look at http://java.sun.com/docs/books/tutorial/getStarted/cupojava/unix.html from which my java "standalone" program was borrowed.

8.2.13 Using makefiles

make

Run the "make" utility to build (compile, link, etc) a project described in the Makefile found in the current directory.

make is used to bring a system "up to date", whenever a change in one file requires an action elsewhere. make is "intelligent" in that it will not make changes unless the change is required, as determined by the file modification date/time. Normally used for buiding software packages (compiling, linking ...), make is also used for other tasks, e.g., system administration. Makefile looks as follows:

target : prerequisites

[Tab]commands

where target is usually a file (but does not have to be, it can be a "phony" target), and prerequisites are files on which target depends. If target does not exist or is older than any prerequisites, "commands" are executed. The first line above is called "the rule", the second "the action". Please note that any action line must start with the tab character. Here is an example Makefile that makes an executable file called "edit":

my_program : main.o command.o

cc -o my_program main.o command.o

main.o : main.c defs.h

cc -c main.c

command.o : command.c defs.h command.h

cc -c command.c

clean :

rm my_program main.o command.o

To use this Makefile to create an executable file called "my_program', I type: make. It works backwards to determine the dependencies, so first it compiles "command.c" to the object file "command.o", then it compiles "main.c" to "main.o", and finally it links "main.o" and "command.o" into the executable "my_program".

One could also use this makefile to delete the executable file and all the object files from the directory by typing: make clean. Since the target "clean" does not depend on any prerequisites, it is not normally executed unless explicitly called. The target "clean" is an example of a "phony" target.

8.2.14 Extra tools

yes

Generate a never-ending output of strings containing "yes" (it does end when <Ctrl><c> is pressed or when electricity goes off). Sounds like a silly utility, but it can be used to write simple programs on the command line. For example, the following amusing on-liner determines the frequency of digits in 100 000 random numbers (the whole command is a single line):

yes | sed '100000q' | awk 'BEGIN{srand();u=6*log(10)}{printf"%e\n",rand()*exp(rand()*u)}'| cut -c1 | sort | uniq -c

I hope this example does not scare you too much--it surely shows that the old-fashioned UNIX command line can be as complicated (and powerful) as you wish to make it. If you are interested why the frequency of digits varies (it seems intuitively that it is should be constant if the numbers are random), try the website from which I borrowed the example: http://www.newscientist.com/ns/19990731/letters4.html



UNIXguide.net
Suggest a Site