Fun to Program – CLI programs

Date: 2013/08/03 (initial publish), 2021/08/02 (last update)

Source: en/fun2-00003.md

Previous Post Top Next Post

TOC

This was originally written and created around 2013 and may require to be updated. (2021)

CLI programs

The command line interface (CLI) program requires to parse its command line arguments. Here are simple example code snippets.

Please note I chose the coding style which is the most legible for each language. I know there are other ways …

Shell

Shell script (short option only)

Shell program with short command line options.

Source code for the shell script: cli_s

#!/bin/sh
verbose=0
while getopts "af:v" opt ; do
    case $opt in
    a)	echo "Option a"
    	;;
    f)	cat "$OPTARG"
    	;;
    v)	verbose=1
    	;;
    -)	break
    	;;
    ?)	echo "Usage: $0: [-a] [-v] [-f file] args ..."
    	exit 1
    	;;
    esac
done
shift $(($OPTIND - 1))
printf "Remaining arguments are: %s\n" "$*"
 

Please note shell variables are used.

TIP: No long option like “--file ...”.

The POSIX getopts is available as a shell buildin command of BASH/DASH. (Please note s at the end. The older Bell Labs derived external command is called getopt.)

Shell script (long and short option)

Shell program with long and short command line options.

Source code for the shell script: cli_l

#!/bin/sh
verbose=0
while [ "$#" -gt "0" ]; do
    case $1 in
    -a)    echo "Option a"
        ;;
    -f|--file)
        shift
        cat $1
        ;;
    -v)    verbose=1
        ;;
    --long)    echo "Option long"
        ;;
    --longextra)
        shift
        echo "Option longextra with $1"
        ;;
    --)    shift
        break 
        ;;
    -*)    echo "Unknown option: $1"
        echo "Usage: $0 [-a] [-f|--file file] [-v] args ..."
        exit 1
        ;;
    *)    break 
        ;;
    esac
    shift
done
printf "Remaining arguments are: %s\n" "$*"

TIP: You must type as “-a -f ...” and not as “-af ...

Here I avoided the use of getopts/getopt for long option support to gain maximum portability.

Python

Python script with argparse

Simple example program with long and short command line options.

Source code for Python with argparse

#!/usr/bin/python3
# vim:se tw=0 sts=4 ts=4 et cindent:
def main():
    import argparse, sys
    parser = argparse.ArgumentParser(description='This is skelton program.')
    parser.add_argument('-a', action="store_true", dest="opt_a", 
                    default=False, help='operation mode')
    parser.add_argument('-f', '--file', action="store", dest="filename", 
                    help='input filename')
    parser.add_argument('-v', action="store_true", dest="verbose", 
                    default=False, help='vebosity')
    parser.add_argument('args', nargs='*', help='arguments')
    parser.add_argument('--long', action="store_true", dest="opt_long", 
                    help='long mode')
    parser.add_argument('--longextra', action="store", dest="long", 
                    help='long extra mode')
    args = parser.parse_args()
    if args.opt_a:
        print("option a")
    if args.filename:
        print("filename = " + args.filename)
        with open(args.filename) as f:
            for line in f:
                print (line[:-1])
    if args.verbose:
        print("option verbose")
    if args.opt_long:
        print("option long")
    if args.long:
        print("longextra = " + args.long)
    if args.args:
        print("args = " , args.args)

if __name__ == '__main__': 
    main()

Execution examples with auto generated help

$ ./cli --help
usage: cli [-h] [-a] [-f FILENAME] [-v] [--long] [--longextra LONG]
           [args [args ...]]

This is skelton program.

positional arguments:
  args                  arguments

optional arguments:
  -h, --help            show this help message and exit
  -a                    operation mode
  -f FILENAME, --file FILENAME
                        input filename
  -v                    vebosity
  --long                long mode
  --longextra LONG      long extra mode
$ ./cli -avf BOGUS.txt --long --longextra=FOO cli BOGUS.txt
option a
filename = BOGUS.txt
This is BOGUS.txt here.
EOF here :-)
option verbose
option long
longextra = FOO
args =  ['cli', 'BOGUS.txt']
$ ./cli -b
usage: cli [-h] [-a] [-f FILENAME] [-v] [--long] [--longextra LONG]
           [args [args ...]]
cli: error: unrecognized arguments: -b

TIP: Older programs may use getopt module which is not as object oriented as argparse.

See:

Actual module file on the system can be obtained by running The Python interpreter interactively as follows.

$ /usr/bin/python3 -q
>>> import argparse
>>> print (argparse.__file__)
/usr/lib/python3.2/argparse.py

Python script with cliapp

cliapp is a Python framework for Unix-like command line programs and provides a unified supports for the command line and the configuration file.

This seems to be interesting and is used by the backup program obnam(1).

Source code for Python with cliapp

#!/usr/bin/env python
# vim:se tw=0 sts=4 ts=4 et cindent:
'''
Example using cliapp framework. (Python2 only)
'''
import cliapp
import logging

class ExampleApp(cliapp.Application):

    def add_settings(self):
        self.settings.boolean(['append', 'a'], 'append mode')
        self.settings.string(['file', 'f'], 'configuration filename',
                metavar='FILENAME')
        self.settings.boolean(['verbose', 'v'], 'verbose mode')
        self.settings.boolean(['long'], 'long mode')
        self.settings.string(['longextra'], 'longextra mode',
                metavar='LONG')
    def process_inputs(self, args):
        self.counts = 0
        cliapp.Application.process_inputs(self, args)
        self.output.write('There were %s lines in %s.\n'
            % (self.counts, args))
        print('append=%s' % self.settings['append'])
        print('verbose=%s' % self.settings['verbose'])
        print('long=%s' % self.settings['long'])
        print('longextra=%s' % self.settings['longextra'])
        if self.settings['file']:
           print("filename = %s" % self.settings['file'])
           with open(self.settings['file']) as f:
               for line in f:
                   print (line[:-1])

    def process_input_line(self, name, line):
        self.counts += 1

if __name__ == '__main__':
    app = ExampleApp('Cli', version='0.1',
        description="Cli as a command line program example",
        epilog="Copyright (C) 2012 Osamu Aoki")
    app.settings.config_files = ['example.conf']
    app.run()

Execution examples with auto generated help

$ ./cli --help
Usage: Cli [options]

Cli as a command line program example

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  --output=FILE         write output to FILE, instead of standard output
  -a, --append          append mode
  --no-append
  -f FILENAME, --file=FILENAME
                        configuration filename
  -v, --verbose         verbose mode
  --no-verbose
  --long                long mode
  --no-long
  --longextra=LONG      longextra mode

  Configuration files and settings:
    --dump-config       write out the entire current configuration
    --no-default-configs
                        clear list of configuration files to read
    --config=FILE       add FILE to config files
    --help-all          show all options

  Logging:
    --log=FILE          write log entries to FILE (default is to not write log
                        files at all); use "syslog" to log to system log, or
                        "none" to disable logging
    --log-level=LEVEL   log at LEVEL, one of debug, info, warning, error,
                        critical, fatal (default: debug)
    --log-max=SIZE      rotate logs larger than SIZE, zero for never (default:
                        0)
    --log-keep=N        keep last N logs (10)
    --log-mode=MODE     set permissions of new log files to MODE (octal;
                        default 0600)

  Peformance:
    --dump-memory-profile=METHOD
                        make memory profiling dumps using METHOD, which is one
                        of: none, simple, meliae, or heapy (default: simple)
    --memory-dump-interval=SECONDS
                        make memory profiling dumps at least SECONDS apart

Copyright (C) 2012 Osamu Aoki
$ ./cli -avf BOGUS.txt --long --longextra=FOO cli BOGUS.txt
There were 45 lines in ['cli', 'BOGUS.txt'].
append=True
verbose=True
long=True
longextra=FOO
filename = BOGUS.txt
This is BOGUS.txt here.
EOF here :-)
$ ./cli -b
Usage: Cli [options]

Cli: error: no such option: -b

Lua

Lua script (long and short option)

Simple example program with long and short command line options.

Source code for the Lua script: cli

#!/usr/bin/lua
verbose = 0
i = 1
while (i <= #arg) do
    if (arg[i] == '-a') then
        print("Option a")
    elseif (arg[i] == '-f' or arg[i] == '--file') then
        i = i +1
        for line in io.lines(arg[i]) do
            print(line)
        end
    elseif (arg[i] == '-v') then
        verbose = 1
    elseif (arg[i] == '--long') then
        print("Option long")
    elseif (string.sub(arg[i],1,11) == '--longextra') then
        print("Option longextra with " .. string.sub(arg[i], 13))
    elseif (arg[i] == '--') then
        i = i +1
        break
    elseif (string.sub(arg[i], 1, 1) == '-') then
        print("Unknown option: " .. arg[i])
        print("Usage: " .. arg[0] .. 
            " [-a] [-f|--file file] [-v] [--long] [--longextra=value] [args...]")
        return(1)
    else
        break
    end
    i = i + 1
end
i0 = i - 1
for i = 1, #arg - i0, 1 do
    print("ARG[" .. i .. "] = " .. arg[i + i0])
end

Execution examples with auto generated help

$ ./cli --help
Unknown option: --help
Usage: ./cli [-a] [-f|--file file] [-v] [--long] [--longextra=value] [args...]
$ ./cli -a -v -f BOGUS.txt --long --longextra=FOO cli BOGUS.txt
Option a
Option long
Option longextra with FOO
ARG[1] = cli
ARG[2] = BOGUS.txt
$ ./cli -b
Unknown option: -b
Usage: ./cli [-a] [-f|--file file] [-v] [--long] [--longextra=value] [args...]

TIP: You must type as “-a -f ...” and not as “-af ...

Perl

Perl script with Getopt::Long

Simple example program with long and short command line options.

Source code for Perl with Getopt::Long

#!/usr/bin/perl -w
use strict;
use Getopt::Long;
# Global variables
use vars qw(%opt $verbose $helpmsg);
%opt = ();
$verbose = 0;
$helpmsg = "Usage: $0 [-a] [-v] [-f|--file name] [--long] [--longextra extra]...\n";

sub main()
{
    &GetOptions(
        "a"=>\$opt{'a'},
        "f|file=s"=>\$opt{'f'},
        "h|help"=>\$opt{'h'},
        "v"=>\$opt{'v'},
        "long"=>\$opt{'long'},
        "longextra=s"=>\$opt{'longextra'}) or die $helpmsg; 
    if ($opt{'a'}) {
        print "Option a\n";
    }
    if ($opt{'h'}) {
        print $helpmsg;
    }
    if ($opt{'f'}) {
        print("Option f with $opt{'f'}\n");
        open(INPUT_FILE, $opt{'f'})
            or die "Couldn't open $opt{'f'}!";
        while (<INPUT_FILE>) {
            print "$_";
        }
        close(INPUT_FILE)
    }
    if ($opt{'v'}) {
        $verbose = 1;
    }
    if ($opt{'long'}) {
        print "Option long\n";
    }
    if ($opt{'longextra'}) {
        print "Option f with $opt{'longextra'}\n";
    }
    if ($ARGV[0]) {
        print "Other things found on the command line:\n";
    }
    foreach (@ARGV) {
        print "ARG=$_\n";
    }
}

main();

TIP: Older programs with short command line options may use functions such as getopt("af:v") or getopts("af:v") with use Getopt::Std; which set global variables $opt_a, $opt_f, $opt_v.

Execution examples with auto generated help

$ ./cli --help
Usage: ./cli [-a] [-v] [-f|--file name] [--long] [--longextra extra]...
$ ./cli -a -v -f BOGUS.txt --long --longextra=FOO cli BOGUS.txt
Option a
Option f with BOGUS.txt
This is BOGUS.txt here.
EOF here :-)
Option long
Option f with FOO
Other things found on the command line:
ARG=cli
ARG=BOGUS.txt
$ ./cli -b
Unknown option: b
Usage: ./cli [-a] [-v] [-f|--file name] [--long] [--longextra extra]...

C

Writing a code with the iteration over unknown length lines is not easy with C since it requires dynamic memory allocation for the line buffer. We will come back to such coding later.

C with getopt()

Simple example program with short command line options.

Source code for C with getopt()

/* a short command line option example */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h> /* getopt */
int main(int argc, char **argv)
{
    int c;
    int verbose = 0;
    while ((c = getopt(argc, argv, "af:v")) != -1) {
        switch (c) {
        case 'a':
            printf("option a\n");
            break;
        case 'f':
            printf("option f with %s.\n", optarg);
            break;
        case 'v':
            verbose = 1;
            break;
        default:
            printf("unknown option = %c = ascii(0%x)\n",
                    optopt, optopt);
            printf("return value of getopt() = %c\n", c);
        }
    }
    printf("verbose mode = %i\n", verbose);
    if (optind < argc) {
        int j = 1;
        while (optind < argc) {
            printf("argument[%i]=%s\n", j, argv[optind++]);
            j++;
        }
    }
    return EXIT_SUCCESS;
}

Please note few global external variables used.

C with getopt_long()

Simple example program with long and short command line options.

Source code for C with getopt_long()

/* a long command line option example */

#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>        /* getopt_long */

int main(int argc, char **argv)
{
    int c;
    int i = 0;
    int verbose = 0;
    static struct option longopts[] = {
        {"append", no_argument, 0, 'a'},
        {"verbose", no_argument, 0, 'v'},
        {"file", required_argument, 0, 'f'},
        {"long", no_argument, 0, 0},
        {"longextra", required_argument, 0, 0},
        {NULL, 0, NULL, 0}
    };
    while ((c = getopt_long(argc, argv, "af:v", longopts, &i)) != -1) {
        switch (c) {
        case 0: /* for longopts[all][3] == 0 */
            printf ("option %s", longopts[i].name);
            if (optarg)
                printf (" with arg %s", optarg);
            printf ("\n");
            break;
        case 'a':
            printf("option a\n");
            break;
        case 'f':
            printf("option f with %s.\n", optarg);
            break;
        case 'v':
            verbose = 1;
            break;
        default:
            printf("unknown option = %c = ascii(0%x)\n", optopt, optopt);
            printf("return value of getopt_long() = %c\n", c);
        }
    }
    printf("verbose mode = %i\n", verbose);
    if (optind < argc) {
        int j = 1;
        while (optind < argc) {
            printf("argument[%i]=%s\n", j, argv[optind++]);
            j++;
        }
    }
    return EXIT_SUCCESS;
}

Please note few global external variables used just like getopt().

In order to avoid GNU vs. BSD incompatibility, the following may be a good idea:

See FreeBSD 8.0 getopt_long(3) manual.

C++

The golden rule of C++ programing: “If you can not find something in the C++ Standard Library, look for it in Boost libraries.”

Simple example program with long and short command line options.

Source code for C++ with boost::program_options

#include <boost/program_options.hpp>
#include <iostream>
#include <iterator>
#include <stdlib.h>
using namespace std;

// A helper function to simplify the main part.
template<class T>
ostream& operator<<(ostream& os, const vector<T>& v)
{
    copy(v.begin(), v.end(), ostream_iterator<T>(cout, " "));
    return os;
}


int main(int argc, char **argv)
{
    string file;
    string extra;
    try {
        namespace po = boost::program_options;
        po::options_description visible("SYNTAX: cli [OPTION ...] files ...");
        visible.add_options()
            ("append,a", "append option")
            ("help,h", "help message")
            ("verbose,v", "verbose option")
            ("file,f", po::value<string>(&file), "file option")
            ("long", "long option")
            ("longextra", po::value<string>(&extra), "longextra option")
        ;
        po::options_description hidden;
        hidden.add_options()
            ("input-file", po::value< vector<string> >(), "input file")
        ;        
        po::positional_options_description p;
        p.add("input-file", -1);

        po::options_description desc;
        desc.add(visible).add(hidden);

        po::variables_map vm;
        po::store(po::command_line_parser(argc, argv)
            .options(desc).positional(p).run(), vm);
        po::notify(vm);    

        if (vm.count("help")) {
            cout << visible << "\n";
            return EXIT_FAILURE;
        }
        if (vm.count("append")) {
            cout << "append mode\n";
        }
        if (vm.count("verbose")) {
            cout << "verbose mode\n";
        }
        if (vm.count("file")) {
            cout << "Filename: " 
                 << file << "\n";
        } else {
            cout  << "Filename: (unset)\n";
        }
        if (vm.count("long")) {
            cout << "long mode\n";
        }
        if (vm.count("longextra")) {
            cout << "Longextra: " 
                 << extra << "\n";
        } else {
            cout  << "Longextra: (unset)\n";
        }
        if (vm.count("input-file")) {
            cout << "Input files are: "
                 << vm["input-file"].as< vector<string> >() << "\n";
        }
    }
    catch(exception& e) {
        cerr << "E: " << e.what() << "\n";
        return EXIT_FAILURE;
    }
    catch(...) {
        cerr << "E: unknown type!\n";
    }

    return EXIT_SUCCESS;
}

Let’s compile cli.cxx to create the ELF object cli and run it.

$ g++ -Wall -lboost_program_options -o cli cli.cxx
$ ./cli -avf BOGUS.txt --long --longextra=FOO X1 X2
append mode
verbose mode
Filename: BOGUS.txt
long mode
Longextra: FOO
Input files are: X1 X2
$ ./cli -b
E: unknown option -b
$ ./cli --help
SYNTAX: cli [OPTION ...] files ...:
  -a [ --append ]       append option
  -h [ --help ]         help message
  -v [ --verbose ]      verbose option
  -f [ --file ] arg     file option
  --long                long option
  --longextra arg       longextra option

Vala

Simple Vala example programs with long and short command line options using GLib.

Simple non-OOP style (no class)

Source code cli-1.vala in Vala language

static bool append = false;
static bool verbose = false;
static bool op_long = false;
static string filename = null;
static string longextra = null;

// sources is a string array containing all non-option arguments
// https://mail.gnome.org/archives/vala-list/2009-March/msg00090.html
[CCode (array_length = false, array_null_terminated = true)]
static string[] sources;

const OptionEntry[] options = {
    { "append",  'a', 0, OptionArg.NONE,     ref append,
        "Set append mode",     null },
    { "verbose", 'v', 0, OptionArg.NONE,     ref verbose,
        "Set verbose mode",    null },
    { "file",    'f', 0, OptionArg.FILENAME, ref filename,
        "Use F file",         "F"},
    { "long",      0, 0, OptionArg.NONE,     ref op_long,
        "Set long mode",      null },
    { "longextra", 0, 0, OptionArg.STRING,   ref longextra,
        "Set longextra to M", "M" },
    { "",    0, 0, OptionArg.FILENAME_ARRAY, ref sources,
        null,                "FILE..." },
    { null }
};


int main (string[] args) {
    // initialize locale
    Intl.setlocale (LocaleCategory.ALL, "");
    //
    stdout.printf ("command  = %s\n", args[0]);
    stdout.printf ("basename = %s\n", Path.get_basename(args[0]));
    try {
        // parse command line options with GLib
        var opt_context = new OptionContext ("- Cli");
        opt_context.set_help_enabled (true);
        opt_context.add_main_entries (options, null);
        opt_context.parse (ref args);
    } catch (OptionError e) {
        stdout.printf ("%s\n", e.message);
        stdout.printf (
"Run '%s --help' to see a full list of available command line options.\n",
            args[0]);
        return 1;
    }

    // print variables
    if (verbose) {
        stdout.printf ("Cli: verbose ON\n");
    }
    if (append) {
        stdout.printf ("Cli: appemd ON\n");
    }
    if (op_long) {
        stdout.printf ("Cli: long ON\n");
    }
    if (filename != null) {
        stdout.printf ("Cli: file = %s\n", filename);
    }
    if (longextra != null) {
        stdout.printf ("Cli: longextra = %s\n", longextra);
    }
    if (sources != null) {
        int i = 0;
        foreach (string s in sources) {
            stdout.printf("sources[%i]=%s\n", i, s);
            i++;
        }
    }
    return 0;
}


TIP: The above example skips specifying GLib for the parent class since it is the default for Vala.

Let’s compile cli-1.vala to create the ELF object cli-1 and run it.

$ valac -v cli-1.vala
/path/to/vala/cli-1.vala.c: In function ‘main’:
/path/to/vala/cli-1.vala.c:204:2: warning: ‘g_type_init’ is deprecated (declared ...
  g_type_init ();
  ^
Loaded package `/usr/share/vala-0.20/vapi/glib-2.0.vapi'
Loaded package `/usr/share/vala-0.20/vapi/gobject-2.0.vapi'
cc -o '/path/to/vala/cli-1' '/path/to/vala/cli-1.vala.c' -I/usr/include/glib-2.0 ...
$ ./cli-1 -avf BOGUS.txt --long --longextra=FOO X1 X2
command  = ./cli-1
basename = cli-1
Cli: verbose ON
Cli: appemd ON
Cli: long ON
Cli: file = BOGUS.txt
Cli: longextra = FOO
sources[0]=X1
sources[1]=X2
$ ./cli-1 -b
command  = ./cli-1
basename = cli-1
Unknown option -b
Run './cli-1 --help' to see a full list of available command line options.
$ ./cli-1 --help
command  = ./cli-1
basename = cli-1
Usage:
  cli-1 [OPTION...] FILE... - Cli

Help Options:
  -h, --help        Show help options

Application Options:
  -a, --append      Set append mode
  -v, --verbose     Set verbose mode
  -f, --file=F      Use F file
  --long            Set long mode
  --longextra=M     Set longextra to M

You can get the C source as:

$ valac -C cli-1.vala
$ wc -l cli-1.vala ; wc -l cli-1.c
75 cli-1.vala
221 cli-1.c
$ cat cli-1.c |sed -e 's/       /    /g'|fold  # tab => 4 spaces
/* cli-1.c generated by valac 0.20.1, the Vala compiler
 * generated from cli-1.vala, do not modify */


#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <stdio.h>

#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_option_context_free0(var) ((var == NULL) ? NULL : (var = (g_option_co
ntext_free (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var),
NULL)))


extern gboolean append;
gboolean append = FALSE;
extern gboolean verbose;
gboolean verbose = FALSE;
extern gboolean op_long;
gboolean op_long = FALSE;
extern gchar* filename;
gchar* filename = NULL;
extern gchar* longextra;
gchar* longextra = NULL;
extern gchar** sources;
gchar** sources = NULL;

gint _vala_main (gchar** args, int args_length1);
static gint _vala_array_length (gpointer array);

const GOptionEntry options[7] = {{"append", 'a', 0, G_OPTION_ARG_NONE, &append,
"Set append mode", NULL}, {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Set
verbose mode", NULL}, {"file", 'f', 0, G_OPTION_ARG_FILENAME, &filename, "Use F
file", "F"}, {"long", (gchar) 0, 0, G_OPTION_ARG_NONE, &op_long, "Set long mode"
, NULL}, {"longextra", (gchar) 0, 0, G_OPTION_ARG_STRING, &longextra, "Set longe
xtra to M", "M"}, {"", (gchar) 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &sources, NULL
, "FILE..."}, {NULL}};

gint _vala_main (gchar** args, int args_length1) {
    gint result = 0;
    FILE* _tmp0_;
    gchar** _tmp1_;
    gint _tmp1__length1;
    const gchar* _tmp2_;
    FILE* _tmp3_;
    gchar** _tmp4_;
    gint _tmp4__length1;
    const gchar* _tmp5_;
    gchar* _tmp6_ = NULL;
    gchar* _tmp7_;
    gboolean _tmp18_;
    gboolean _tmp20_;
    gboolean _tmp22_;
    const gchar* _tmp24_;
    const gchar* _tmp27_;
    gchar** _tmp30_;
    gint _tmp30__length1;
    GError * _inner_error_ = NULL;
    setlocale (LC_ALL, "");
    _tmp0_ = stdout;
    _tmp1_ = args;
    _tmp1__length1 = args_length1;
    _tmp2_ = _tmp1_[0];
    fprintf (_tmp0_, "command  = %s\n", _tmp2_);
    _tmp3_ = stdout;
    _tmp4_ = args;
    _tmp4__length1 = args_length1;
    _tmp5_ = _tmp4_[0];
    _tmp6_ = g_path_get_basename (_tmp5_);
    _tmp7_ = _tmp6_;
    fprintf (_tmp3_, "basename = %s\n", _tmp7_);
    _g_free0 (_tmp7_);
    {
        GOptionContext* _tmp8_;
        GOptionContext* opt_context;
        GOptionContext* _tmp9_;
        GOptionContext* _tmp10_;
        GOptionContext* _tmp11_;
        _tmp8_ = g_option_context_new ("- Cli");
        opt_context = _tmp8_;
        _tmp9_ = opt_context;
        g_option_context_set_help_enabled (_tmp9_, TRUE);
        _tmp10_ = opt_context;
        g_option_context_add_main_entries (_tmp10_, options, NULL);
        _tmp11_ = opt_context;
        g_option_context_parse (_tmp11_, &args_length1, &args, &_inner_error_);
        if (_inner_error_ != NULL) {
            _g_option_context_free0 (opt_context);
            if (_inner_error_->domain == G_OPTION_ERROR) {
                goto __catch0_g_option_error;
            }
            _g_option_context_free0 (opt_context);
            g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FIL
E__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain)
, _inner_error_->code);
            g_clear_error (&_inner_error_);
            return 0;
        }
        _g_option_context_free0 (opt_context);
    }
    goto __finally0;
    __catch0_g_option_error:
    {
        GError* e = NULL;
        FILE* _tmp12_;
        GError* _tmp13_;
        const gchar* _tmp14_;
        FILE* _tmp15_;
        gchar** _tmp16_;
        gint _tmp16__length1;
        const gchar* _tmp17_;
        e = _inner_error_;
        _inner_error_ = NULL;
        _tmp12_ = stdout;
        _tmp13_ = e;
        _tmp14_ = _tmp13_->message;
        fprintf (_tmp12_, "%s\n", _tmp14_);
        _tmp15_ = stdout;
        _tmp16_ = args;
        _tmp16__length1 = args_length1;
        _tmp17_ = _tmp16_[0];
        fprintf (_tmp15_, "Run '%s --help' to see a full list of available comma
nd line options.\n", _tmp17_);
        result = 1;
        _g_error_free0 (e);
        return result;
    }
    __finally0:
    if (_inner_error_ != NULL) {
        g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, _
_LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inn
er_error_->code);
        g_clear_error (&_inner_error_);
        return 0;
    }
    _tmp18_ = verbose;
    if (_tmp18_) {
        FILE* _tmp19_;
        _tmp19_ = stdout;
        fprintf (_tmp19_, "Cli: verbose ON\n");
    }
    _tmp20_ = append;
    if (_tmp20_) {
        FILE* _tmp21_;
        _tmp21_ = stdout;
        fprintf (_tmp21_, "Cli: appemd ON\n");
    }
    _tmp22_ = op_long;
    if (_tmp22_) {
        FILE* _tmp23_;
        _tmp23_ = stdout;
        fprintf (_tmp23_, "Cli: long ON\n");
    }
    _tmp24_ = filename;
    if (_tmp24_ != NULL) {
        FILE* _tmp25_;
        const gchar* _tmp26_;
        _tmp25_ = stdout;
        _tmp26_ = filename;
        fprintf (_tmp25_, "Cli: file = %s\n", _tmp26_);
    }
    _tmp27_ = longextra;
    if (_tmp27_ != NULL) {
        FILE* _tmp28_;
        const gchar* _tmp29_;
        _tmp28_ = stdout;
        _tmp29_ = longextra;
        fprintf (_tmp28_, "Cli: longextra = %s\n", _tmp29_);
    }
    _tmp30_ = sources;
    _tmp30__length1 = _vala_array_length (sources);
    if (_tmp30_ != NULL) {
        gint i;
        gchar** _tmp31_;
        gint _tmp31__length1;
        i = 0;
        _tmp31_ = sources;
        _tmp31__length1 = _vala_array_length (sources);
        {
            gchar** s_collection = NULL;
            gint s_collection_length1 = 0;
            gint _s_collection_size_ = 0;
            gint s_it = 0;
            s_collection = _tmp31_;
            s_collection_length1 = _tmp31__length1;
            for (s_it = 0; s_it < _tmp31__length1; s_it = s_it + 1) {
                gchar* _tmp32_;
                gchar* s = NULL;
                _tmp32_ = g_strdup (s_collection[s_it]);
                s = _tmp32_;
                {
                    FILE* _tmp33_;
                    gint _tmp34_;
                    const gchar* _tmp35_;
                    gint _tmp36_;
                    _tmp33_ = stdout;
                    _tmp34_ = i;
                    _tmp35_ = s;
                    fprintf (_tmp33_, "sources[%i]=%s\n", _tmp34_, _tmp35_);
                    _tmp36_ = i;
                    i = _tmp36_ + 1;
                    _g_free0 (s);
                }
            }
        }
    }
    result = 0;
    return result;
}


int main (int argc, char ** argv) {
    g_type_init ();
    return _vala_main (argv, argc);
}


static gint _vala_array_length (gpointer array) {
    int length;
    length = 0;
    if (array) {
        while (((gpointer*) array)[length]) {
            length++;
        }
    }
    return length;
}



Since no OOP techniques are used, the resulting C code does not have GObject related macros.

But some libraries from GLib are used, the resulting C code has automatically generated memory management codes such as _g_option_context_free0, _g_error_free0, and _g_free0.

OOP style (main outside of class)

Source code cli-2.vala in Vala language

class Cli : Object {
    private static bool append = false;
    private static bool verbose = false;
    private static bool op_long = false;
    private static string filename = null;
    private static string longextra = null;

    // sources is a string array containing all non-option arguments
    // https://mail.gnome.org/archives/vala-list/2009-March/msg00090.html
    [CCode (array_length = false, array_null_terminated = true)]
    private static string[] sources;

    private const OptionEntry[] options = {
        { "append",  'a', 0, OptionArg.NONE,     ref append,
            "Set append mode",     null },
        { "verbose", 'v', 0, OptionArg.NONE,     ref verbose,
            "Set verbose mode",    null },
        { "file",    'f', 0, OptionArg.FILENAME, ref filename,
            "Use F file",         "F"},
        { "long",      0, 0, OptionArg.NONE,     ref op_long,
            "Set long mode",      null },
        { "longextra", 0, 0, OptionArg.STRING,   ref longextra,
            "Set longextra to M", "M" },
        { "",    0, 0, OptionArg.FILENAME_ARRAY, ref sources,
            null,                "FILE..." },
        { null }
    };

    public int parse (string[] args) {
	// parse command line
        try {
            // parse command line options with GLib
            var opt_context = new OptionContext ("- Cli");
            opt_context.set_help_enabled (true);
            opt_context.add_main_entries (options, null);
            opt_context.parse (ref args);
        } catch (OptionError e) {
            stdout.printf ("%s\n", e.message);
            stdout.printf (
    "Run '%s --help' to see a full list of available command line options.\n",
                args[0]);
            return 1;
        }
        return 0;
    }

    public int run () {
        // print variables
        if (verbose) {
            stdout.printf ("Cli: verbose ON\n");
        }
        if (append) {
            stdout.printf ("Cli: appemd ON\n");
        }
        if (op_long) {
            stdout.printf ("Cli: long ON\n");
        }
        if (filename != null) {
            stdout.printf ("Cli: file = %s\n", filename);
        }
        if (longextra != null) {
            stdout.printf ("Cli: longextra = %s\n", longextra);
        }
        if (sources != null) {
            int i = 0;
            foreach (string s in sources) {
                stdout.printf("sources[%i]=%s\n", i, s);
                i++;
            }
        }
        return 0;
    }

}
int main (string[] args) {
    // initialize locale
    Intl.setlocale (LocaleCategory.ALL, "");
    //
    stdout.printf ("command  = %s\n", args[0]);
    stdout.printf ("basename = %s\n", Path.get_basename(args[0]));

    var cli = new Cli ();
    cli.parse (args);
    return cli.run ();
}

TIP: The above example skips specifying GLib for the parent class since it is the default for Vala.

Let’s compile cli-2.vala to create the ELF object cli-2 and run it.

$ valac -v cli-2.vala
/path/to/vala/cli-2.vala.c: In function ‘main’:
/path/to/vala/cli-2.vala.c:304:2: warning: ‘g_type_init’ is deprecated (declared ...
  g_type_init ();
  ^
Loaded package `/usr/share/vala-0.20/vapi/glib-2.0.vapi'
Loaded package `/usr/share/vala-0.20/vapi/gobject-2.0.vapi'
cc -o '/path/to/vala/cli-2' '/path/to/vala/cli-2.vala.c' -I/usr/include/glib-2.0 ...
$ ./cli-2 -avf BOGUS.txt --long --longextra=FOO X1 X2
command  = ./cli-2
basename = cli-2
Cli: verbose ON
Cli: appemd ON
Cli: long ON
Cli: file = BOGUS.txt
Cli: longextra = FOO
sources[0]=X1
sources[1]=X2
$ ./cli-2 -b
command  = ./cli-2
basename = cli-2
Unknown option -b
Run './cli-2 --help' to see a full list of available command line options.
$ ./cli-2 --help
command  = ./cli-2
basename = cli-2
Usage:
  cli-2 [OPTION...] FILE... - Cli

Help Options:
  -h, --help        Show help options

Application Options:
  -a, --append      Set append mode
  -v, --verbose     Set verbose mode
  -f, --file=F      Use F file
  --long            Set long mode
  --longextra=M     Set longextra to M

You can get the C source as:

$ valac -C cli-2.vala
$ wc -l cli-2.vala ; wc -l cli-2.c
86 cli-2.vala
321 cli-2.c
$ cat cli-2.c |sed -e 's/       /    /g'|fold  # tab => 4 spaces
/* cli-2.c generated by valac 0.20.1, the Vala compiler
 * generated from cli-2.vala, do not modify */


#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <locale.h>


#define TYPE_CLI (cli_get_type ())
#define CLI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CLI, Cli))
#define CLI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CLI, CliClass))
#define IS_CLI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CLI))
#define IS_CLI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CLI))
#define CLI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CLI, CliClass
))

typedef struct _Cli Cli;
typedef struct _CliClass CliClass;
typedef struct _CliPrivate CliPrivate;
#define _g_option_context_free0(var) ((var == NULL) ? NULL : (var = (g_option_co
ntext_free (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var),
NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (va
r), NULL)))

struct _Cli {
    GObject parent_instance;
    CliPrivate * priv;
};

struct _CliClass {
    GObjectClass parent_class;
};


static gpointer cli_parent_class = NULL;
static gboolean cli_append;
static gboolean cli_append = FALSE;
static gboolean cli_verbose;
static gboolean cli_verbose = FALSE;
static gboolean cli_op_long;
static gboolean cli_op_long = FALSE;
static gchar* cli_filename;
static gchar* cli_filename = NULL;
static gchar* cli_longextra;
static gchar* cli_longextra = NULL;
static gchar** cli_sources;
static gchar** cli_sources = NULL;

GType cli_get_type (void) G_GNUC_CONST;
enum  {
    CLI_DUMMY_PROPERTY
};
gint cli_parse (Cli* self, gchar** args, int args_length1);
gint cli_run (Cli* self);
Cli* cli_new (void);
Cli* cli_construct (GType object_type);
static void cli_finalize (GObject* obj);
gint _vala_main (gchar** args, int args_length1);
static gint _vala_array_length (gpointer array);

static const GOptionEntry CLI_options[7] = {{"append", 'a', 0, G_OPTION_ARG_NONE
, &cli_append, "Set append mode", NULL}, {"verbose", 'v', 0, G_OPTION_ARG_NONE,
&cli_verbose, "Set verbose mode", NULL}, {"file", 'f', 0, G_OPTION_ARG_FILENAME,
 &cli_filename, "Use F file", "F"}, {"long", (gchar) 0, 0, G_OPTION_ARG_NONE, &c
li_op_long, "Set long mode", NULL}, {"longextra", (gchar) 0, 0, G_OPTION_ARG_STR
ING, &cli_longextra, "Set longextra to M", "M"}, {"", (gchar) 0, 0, G_OPTION_ARG
_FILENAME_ARRAY, &cli_sources, NULL, "FILE..."}, {NULL}};

gint cli_parse (Cli* self, gchar** args, int args_length1) {
    gint result = 0;
    GError * _inner_error_ = NULL;
    g_return_val_if_fail (self != NULL, 0);
    {
        GOptionContext* _tmp0_;
        GOptionContext* opt_context;
        GOptionContext* _tmp1_;
        GOptionContext* _tmp2_;
        GOptionContext* _tmp3_;
        _tmp0_ = g_option_context_new ("- Cli");
        opt_context = _tmp0_;
        _tmp1_ = opt_context;
        g_option_context_set_help_enabled (_tmp1_, TRUE);
        _tmp2_ = opt_context;
        g_option_context_add_main_entries (_tmp2_, CLI_options, NULL);
        _tmp3_ = opt_context;
        g_option_context_parse (_tmp3_, &args_length1, &args, &_inner_error_);
        if (_inner_error_ != NULL) {
            _g_option_context_free0 (opt_context);
            if (_inner_error_->domain == G_OPTION_ERROR) {
                goto __catch0_g_option_error;
            }
            _g_option_context_free0 (opt_context);
            g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FIL
E__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain)
, _inner_error_->code);
            g_clear_error (&_inner_error_);
            return 0;
        }
        _g_option_context_free0 (opt_context);
    }
    goto __finally0;
    __catch0_g_option_error:
    {
        GError* e = NULL;
        FILE* _tmp4_;
        GError* _tmp5_;
        const gchar* _tmp6_;
        FILE* _tmp7_;
        gchar** _tmp8_;
        gint _tmp8__length1;
        const gchar* _tmp9_;
        e = _inner_error_;
        _inner_error_ = NULL;
        _tmp4_ = stdout;
        _tmp5_ = e;
        _tmp6_ = _tmp5_->message;
        fprintf (_tmp4_, "%s\n", _tmp6_);
        _tmp7_ = stdout;
        _tmp8_ = args;
        _tmp8__length1 = args_length1;
        _tmp9_ = _tmp8_[0];
        fprintf (_tmp7_, "Run '%s --help' to see a full list of available comman
d line options.\n", _tmp9_);
        result = 1;
        _g_error_free0 (e);
        return result;
    }
    __finally0:
    if (_inner_error_ != NULL) {
        g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, _
_LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inn
er_error_->code);
        g_clear_error (&_inner_error_);
        return 0;
    }
    result = 0;
    return result;
}


gint cli_run (Cli* self) {
    gint result = 0;
    gboolean _tmp0_;
    gboolean _tmp2_;
    gboolean _tmp4_;
    const gchar* _tmp6_;
    const gchar* _tmp9_;
    gchar** _tmp12_;
    gint _tmp12__length1;
    g_return_val_if_fail (self != NULL, 0);
    _tmp0_ = cli_verbose;
    if (_tmp0_) {
        FILE* _tmp1_;
        _tmp1_ = stdout;
        fprintf (_tmp1_, "Cli: verbose ON\n");
    }
    _tmp2_ = cli_append;
    if (_tmp2_) {
        FILE* _tmp3_;
        _tmp3_ = stdout;
        fprintf (_tmp3_, "Cli: appemd ON\n");
    }
    _tmp4_ = cli_op_long;
    if (_tmp4_) {
        FILE* _tmp5_;
        _tmp5_ = stdout;
        fprintf (_tmp5_, "Cli: long ON\n");
    }
    _tmp6_ = cli_filename;
    if (_tmp6_ != NULL) {
        FILE* _tmp7_;
        const gchar* _tmp8_;
        _tmp7_ = stdout;
        _tmp8_ = cli_filename;
        fprintf (_tmp7_, "Cli: file = %s\n", _tmp8_);
    }
    _tmp9_ = cli_longextra;
    if (_tmp9_ != NULL) {
        FILE* _tmp10_;
        const gchar* _tmp11_;
        _tmp10_ = stdout;
        _tmp11_ = cli_longextra;
        fprintf (_tmp10_, "Cli: longextra = %s\n", _tmp11_);
    }
    _tmp12_ = cli_sources;
    _tmp12__length1 = _vala_array_length (cli_sources);
    if (_tmp12_ != NULL) {
        gint i;
        gchar** _tmp13_;
        gint _tmp13__length1;
        i = 0;
        _tmp13_ = cli_sources;
        _tmp13__length1 = _vala_array_length (cli_sources);
        {
            gchar** s_collection = NULL;
            gint s_collection_length1 = 0;
            gint _s_collection_size_ = 0;
            gint s_it = 0;
            s_collection = _tmp13_;
            s_collection_length1 = _tmp13__length1;
            for (s_it = 0; s_it < _tmp13__length1; s_it = s_it + 1) {
                gchar* _tmp14_;
                gchar* s = NULL;
                _tmp14_ = g_strdup (s_collection[s_it]);
                s = _tmp14_;
                {
                    FILE* _tmp15_;
                    gint _tmp16_;
                    const gchar* _tmp17_;
                    gint _tmp18_;
                    _tmp15_ = stdout;
                    _tmp16_ = i;
                    _tmp17_ = s;
                    fprintf (_tmp15_, "sources[%i]=%s\n", _tmp16_, _tmp17_);
                    _tmp18_ = i;
                    i = _tmp18_ + 1;
                    _g_free0 (s);
                }
            }
        }
    }
    result = 0;
    return result;
}


Cli* cli_construct (GType object_type) {
    Cli * self = NULL;
    self = (Cli*) g_object_new (object_type, NULL);
    return self;
}


Cli* cli_new (void) {
    return cli_construct (TYPE_CLI);
}


static void cli_class_init (CliClass * klass) {
    cli_parent_class = g_type_class_peek_parent (klass);
    G_OBJECT_CLASS (klass)->finalize = cli_finalize;
}


static void cli_instance_init (Cli * self) {
}


static void cli_finalize (GObject* obj) {
    Cli * self;
    self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_CLI, Cli);
    G_OBJECT_CLASS (cli_parent_class)->finalize (obj);
}


GType cli_get_type (void) {
    static volatile gsize cli_type_id__volatile = 0;
    if (g_once_init_enter (&cli_type_id__volatile)) {
        static const GTypeInfo g_define_type_info = { sizeof (CliClass), (GBaseI
nitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) cli_class_init, (GClas
sFinalizeFunc) NULL, NULL, sizeof (Cli), 0, (GInstanceInitFunc) cli_instance_ini
t, NULL };
        GType cli_type_id;
        cli_type_id = g_type_register_static (G_TYPE_OBJECT, "Cli", &g_define_ty
pe_info, 0);
        g_once_init_leave (&cli_type_id__volatile, cli_type_id);
    }
    return cli_type_id__volatile;
}


gint _vala_main (gchar** args, int args_length1) {
    gint result = 0;
    FILE* _tmp0_;
    gchar** _tmp1_;
    gint _tmp1__length1;
    const gchar* _tmp2_;
    FILE* _tmp3_;
    gchar** _tmp4_;
    gint _tmp4__length1;
    const gchar* _tmp5_;
    gchar* _tmp6_ = NULL;
    gchar* _tmp7_;
    Cli* _tmp8_;
    Cli* cli;
    gchar** _tmp9_;
    gint _tmp9__length1;
    gint _tmp10_ = 0;
    setlocale (LC_ALL, "");
    _tmp0_ = stdout;
    _tmp1_ = args;
    _tmp1__length1 = args_length1;
    _tmp2_ = _tmp1_[0];
    fprintf (_tmp0_, "command  = %s\n", _tmp2_);
    _tmp3_ = stdout;
    _tmp4_ = args;
    _tmp4__length1 = args_length1;
    _tmp5_ = _tmp4_[0];
    _tmp6_ = g_path_get_basename (_tmp5_);
    _tmp7_ = _tmp6_;
    fprintf (_tmp3_, "basename = %s\n", _tmp7_);
    _g_free0 (_tmp7_);
    _tmp8_ = cli_new ();
    cli = _tmp8_;
    _tmp9_ = args;
    _tmp9__length1 = args_length1;
    cli_parse (cli, _tmp9_, _tmp9__length1);
    _tmp10_ = cli_run (cli);
    result = _tmp10_;
    _g_object_unref0 (cli);
    return result;
}


int main (int argc, char ** argv) {
    g_type_init ();
    return _vala_main (argv, argc);
}


static gint _vala_array_length (gpointer array) {
    int length;
    length = 0;
    if (array) {
        while (((gpointer*) array)[length]) {
            length++;
        }
    }
    return length;
}



It is obvious that the Vala code is much shorter than the generated C code. The Vala compiler took care chores of generating CPP macros for GObject with.

OOP style (main inside of class)

Source code cli-3.vala in Vala language

class Cli : Object {
    private static bool append = false;
    private static bool verbose = false;
    private static bool op_long = false;
    private static string filename = null;
    private static string longextra = null;

    // sources is a string array containing all non-option arguments
    // https://mail.gnome.org/archives/vala-list/2009-March/msg00090.html
    [CCode (array_length = false, array_null_terminated = true)]
    private static string[] sources;

    private const OptionEntry[] options = {
        { "append",  'a', 0, OptionArg.NONE,     ref append,
            "Set append mode",     null },
        { "verbose", 'v', 0, OptionArg.NONE,     ref verbose,
            "Set verbose mode",    null },
        { "file",    'f', 0, OptionArg.FILENAME, ref filename,
            "Use F file",         "F"},
        { "long",      0, 0, OptionArg.NONE,     ref op_long,
            "Set long mode",      null },
        { "longextra", 0, 0, OptionArg.STRING,   ref longextra,
            "Set longextra to M", "M" },
        { "",    0, 0, OptionArg.FILENAME_ARRAY, ref sources,
            null,                "FILE..." },
        { null }
    };

    private int parse (string[] args) {
	// parse command line
        try {
            // parse command line options with GLib
            var opt_context = new OptionContext ("- Cli");
            opt_context.set_help_enabled (true);
            opt_context.add_main_entries (options, null);
            opt_context.parse (ref args);
        } catch (OptionError e) {
            stdout.printf ("%s\n", e.message);
            stdout.printf (
    "Run '%s --help' to see a full list of available command line options.\n",
                args[0]);
            return 1;
        }
        return 0;
    }

    private int run () {
        // print variables
        if (verbose) {
            stdout.printf ("Cli: verbose ON\n");
        }
        if (append) {
            stdout.printf ("Cli: appemd ON\n");
        }
        if (op_long) {
            stdout.printf ("Cli: long ON\n");
        }
        if (filename != null) {
            stdout.printf ("Cli: file = %s\n", filename);
        }
        if (longextra != null) {
            stdout.printf ("Cli: longextra = %s\n", longextra);
        }
        if (sources != null) {
            int i = 0;
            foreach (string s in sources) {
                stdout.printf("sources[%i]=%s\n", i, s);
                i++;
            }
        }
        return 0;
    }

    public static int main (string[] args) {
        // initialize locale
        Intl.setlocale (LocaleCategory.ALL, "");
        //
        stdout.printf ("command  = %s\n", args[0]);
        stdout.printf ("basename = %s\n", Path.get_basename(args[0]));
    
        var cli = new Cli ();
        cli.parse (args);
        return cli.run ();
    }

}

TIP: The above example skips specifying GLib for the parent class since it is the default for Vala.

Let’s compile cli-3.vala to create the ELF object cli-3 and run it.

$ valac -v cli-3.vala
/path/to/vala/cli-3.vala.c: In function ‘main’:
/path/to/vala/cli-3.vala.c:263:2: warning: ‘g_type_init’ is deprecated (declared ...
  g_type_init ();
  ^
Loaded package `/usr/share/vala-0.20/vapi/glib-2.0.vapi'
Loaded package `/usr/share/vala-0.20/vapi/gobject-2.0.vapi'
cc -o '/path/to/vala/cli-3' '/path/to/vala/cli-3.vala.c' -I/usr/include/glib-2.0 ...
$ ./cli-3 -avf BOGUS.txt --long --longextra=FOO X1 X2
command  = ./cli-3
basename = cli-3
Cli: verbose ON
Cli: appemd ON
Cli: long ON
Cli: file = BOGUS.txt
Cli: longextra = FOO
sources[0]=X1
sources[1]=X2
$ ./cli-3 -b
command  = ./cli-3
basename = cli-3
Unknown option -b
Run './cli-3 --help' to see a full list of available command line options.
$ ./cli-3 --help
command  = ./cli-3
basename = cli-3
Usage:
  cli-3 [OPTION...] FILE... - Cli

Help Options:
  -h, --help        Show help options

Application Options:
  -a, --append      Set append mode
  -v, --verbose     Set verbose mode
  -f, --file=F      Use F file
  --long            Set long mode
  --longextra=M     Set longextra to M

You can get the C source as:

$ valac -C cli-3.vala
$ wc -l cli-3.vala ; wc -l cli-3.c
87 cli-3.vala
321 cli-3.c
$ cat cli-3.c |sed -e 's/       /    /g'|fold  # tab => 4 spaces
/* cli-3.c generated by valac 0.20.1, the Vala compiler
 * generated from cli-3.vala, do not modify */


#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <locale.h>


#define TYPE_CLI (cli_get_type ())
#define CLI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CLI, Cli))
#define CLI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CLI, CliClass))
#define IS_CLI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CLI))
#define IS_CLI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CLI))
#define CLI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CLI, CliClass
))

typedef struct _Cli Cli;
typedef struct _CliClass CliClass;
typedef struct _CliPrivate CliPrivate;
#define _g_option_context_free0(var) ((var == NULL) ? NULL : (var = (g_option_co
ntext_free (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var),
NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (va
r), NULL)))

struct _Cli {
    GObject parent_instance;
    CliPrivate * priv;
};

struct _CliClass {
    GObjectClass parent_class;
};


static gpointer cli_parent_class = NULL;
static gboolean cli_append;
static gboolean cli_append = FALSE;
static gboolean cli_verbose;
static gboolean cli_verbose = FALSE;
static gboolean cli_op_long;
static gboolean cli_op_long = FALSE;
static gchar* cli_filename;
static gchar* cli_filename = NULL;
static gchar* cli_longextra;
static gchar* cli_longextra = NULL;
static gchar** cli_sources;
static gchar** cli_sources = NULL;

GType cli_get_type (void) G_GNUC_CONST;
enum  {
    CLI_DUMMY_PROPERTY
};
static gint cli_parse (Cli* self, gchar** args, int args_length1);
static gint cli_run (Cli* self);
gint cli_main (gchar** args, int args_length1);
Cli* cli_new (void);
Cli* cli_construct (GType object_type);
static void cli_finalize (GObject* obj);
static gint _vala_array_length (gpointer array);

static const GOptionEntry CLI_options[7] = {{"append", 'a', 0, G_OPTION_ARG_NONE
, &cli_append, "Set append mode", NULL}, {"verbose", 'v', 0, G_OPTION_ARG_NONE,
&cli_verbose, "Set verbose mode", NULL}, {"file", 'f', 0, G_OPTION_ARG_FILENAME,
 &cli_filename, "Use F file", "F"}, {"long", (gchar) 0, 0, G_OPTION_ARG_NONE, &c
li_op_long, "Set long mode", NULL}, {"longextra", (gchar) 0, 0, G_OPTION_ARG_STR
ING, &cli_longextra, "Set longextra to M", "M"}, {"", (gchar) 0, 0, G_OPTION_ARG
_FILENAME_ARRAY, &cli_sources, NULL, "FILE..."}, {NULL}};

static gint cli_parse (Cli* self, gchar** args, int args_length1) {
    gint result = 0;
    GError * _inner_error_ = NULL;
    g_return_val_if_fail (self != NULL, 0);
    {
        GOptionContext* _tmp0_;
        GOptionContext* opt_context;
        GOptionContext* _tmp1_;
        GOptionContext* _tmp2_;
        GOptionContext* _tmp3_;
        _tmp0_ = g_option_context_new ("- Cli");
        opt_context = _tmp0_;
        _tmp1_ = opt_context;
        g_option_context_set_help_enabled (_tmp1_, TRUE);
        _tmp2_ = opt_context;
        g_option_context_add_main_entries (_tmp2_, CLI_options, NULL);
        _tmp3_ = opt_context;
        g_option_context_parse (_tmp3_, &args_length1, &args, &_inner_error_);
        if (_inner_error_ != NULL) {
            _g_option_context_free0 (opt_context);
            if (_inner_error_->domain == G_OPTION_ERROR) {
                goto __catch0_g_option_error;
            }
            _g_option_context_free0 (opt_context);
            g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FIL
E__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain)
, _inner_error_->code);
            g_clear_error (&_inner_error_);
            return 0;
        }
        _g_option_context_free0 (opt_context);
    }
    goto __finally0;
    __catch0_g_option_error:
    {
        GError* e = NULL;
        FILE* _tmp4_;
        GError* _tmp5_;
        const gchar* _tmp6_;
        FILE* _tmp7_;
        gchar** _tmp8_;
        gint _tmp8__length1;
        const gchar* _tmp9_;
        e = _inner_error_;
        _inner_error_ = NULL;
        _tmp4_ = stdout;
        _tmp5_ = e;
        _tmp6_ = _tmp5_->message;
        fprintf (_tmp4_, "%s\n", _tmp6_);
        _tmp7_ = stdout;
        _tmp8_ = args;
        _tmp8__length1 = args_length1;
        _tmp9_ = _tmp8_[0];
        fprintf (_tmp7_, "Run '%s --help' to see a full list of available comman
d line options.\n", _tmp9_);
        result = 1;
        _g_error_free0 (e);
        return result;
    }
    __finally0:
    if (_inner_error_ != NULL) {
        g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, _
_LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inn
er_error_->code);
        g_clear_error (&_inner_error_);
        return 0;
    }
    result = 0;
    return result;
}


static gint cli_run (Cli* self) {
    gint result = 0;
    gboolean _tmp0_;
    gboolean _tmp2_;
    gboolean _tmp4_;
    const gchar* _tmp6_;
    const gchar* _tmp9_;
    gchar** _tmp12_;
    gint _tmp12__length1;
    g_return_val_if_fail (self != NULL, 0);
    _tmp0_ = cli_verbose;
    if (_tmp0_) {
        FILE* _tmp1_;
        _tmp1_ = stdout;
        fprintf (_tmp1_, "Cli: verbose ON\n");
    }
    _tmp2_ = cli_append;
    if (_tmp2_) {
        FILE* _tmp3_;
        _tmp3_ = stdout;
        fprintf (_tmp3_, "Cli: appemd ON\n");
    }
    _tmp4_ = cli_op_long;
    if (_tmp4_) {
        FILE* _tmp5_;
        _tmp5_ = stdout;
        fprintf (_tmp5_, "Cli: long ON\n");
    }
    _tmp6_ = cli_filename;
    if (_tmp6_ != NULL) {
        FILE* _tmp7_;
        const gchar* _tmp8_;
        _tmp7_ = stdout;
        _tmp8_ = cli_filename;
        fprintf (_tmp7_, "Cli: file = %s\n", _tmp8_);
    }
    _tmp9_ = cli_longextra;
    if (_tmp9_ != NULL) {
        FILE* _tmp10_;
        const gchar* _tmp11_;
        _tmp10_ = stdout;
        _tmp11_ = cli_longextra;
        fprintf (_tmp10_, "Cli: longextra = %s\n", _tmp11_);
    }
    _tmp12_ = cli_sources;
    _tmp12__length1 = _vala_array_length (cli_sources);
    if (_tmp12_ != NULL) {
        gint i;
        gchar** _tmp13_;
        gint _tmp13__length1;
        i = 0;
        _tmp13_ = cli_sources;
        _tmp13__length1 = _vala_array_length (cli_sources);
        {
            gchar** s_collection = NULL;
            gint s_collection_length1 = 0;
            gint _s_collection_size_ = 0;
            gint s_it = 0;
            s_collection = _tmp13_;
            s_collection_length1 = _tmp13__length1;
            for (s_it = 0; s_it < _tmp13__length1; s_it = s_it + 1) {
                gchar* _tmp14_;
                gchar* s = NULL;
                _tmp14_ = g_strdup (s_collection[s_it]);
                s = _tmp14_;
                {
                    FILE* _tmp15_;
                    gint _tmp16_;
                    const gchar* _tmp17_;
                    gint _tmp18_;
                    _tmp15_ = stdout;
                    _tmp16_ = i;
                    _tmp17_ = s;
                    fprintf (_tmp15_, "sources[%i]=%s\n", _tmp16_, _tmp17_);
                    _tmp18_ = i;
                    i = _tmp18_ + 1;
                    _g_free0 (s);
                }
            }
        }
    }
    result = 0;
    return result;
}


gint cli_main (gchar** args, int args_length1) {
    gint result = 0;
    FILE* _tmp0_;
    gchar** _tmp1_;
    gint _tmp1__length1;
    const gchar* _tmp2_;
    FILE* _tmp3_;
    gchar** _tmp4_;
    gint _tmp4__length1;
    const gchar* _tmp5_;
    gchar* _tmp6_ = NULL;
    gchar* _tmp7_;
    Cli* _tmp8_;
    Cli* cli;
    gchar** _tmp9_;
    gint _tmp9__length1;
    gint _tmp10_ = 0;
    setlocale (LC_ALL, "");
    _tmp0_ = stdout;
    _tmp1_ = args;
    _tmp1__length1 = args_length1;
    _tmp2_ = _tmp1_[0];
    fprintf (_tmp0_, "command  = %s\n", _tmp2_);
    _tmp3_ = stdout;
    _tmp4_ = args;
    _tmp4__length1 = args_length1;
    _tmp5_ = _tmp4_[0];
    _tmp6_ = g_path_get_basename (_tmp5_);
    _tmp7_ = _tmp6_;
    fprintf (_tmp3_, "basename = %s\n", _tmp7_);
    _g_free0 (_tmp7_);
    _tmp8_ = cli_new ();
    cli = _tmp8_;
    _tmp9_ = args;
    _tmp9__length1 = args_length1;
    cli_parse (cli, _tmp9_, _tmp9__length1);
    _tmp10_ = cli_run (cli);
    result = _tmp10_;
    _g_object_unref0 (cli);
    return result;
}


int main (int argc, char ** argv) {
    g_type_init ();
    return cli_main (argv, argc);
}


Cli* cli_construct (GType object_type) {
    Cli * self = NULL;
    self = (Cli*) g_object_new (object_type, NULL);
    return self;
}


Cli* cli_new (void) {
    return cli_construct (TYPE_CLI);
}


static void cli_class_init (CliClass * klass) {
    cli_parent_class = g_type_class_peek_parent (klass);
    G_OBJECT_CLASS (klass)->finalize = cli_finalize;
}


static void cli_instance_init (Cli * self) {
}


static void cli_finalize (GObject* obj) {
    Cli * self;
    self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_CLI, Cli);
    G_OBJECT_CLASS (cli_parent_class)->finalize (obj);
}


GType cli_get_type (void) {
    static volatile gsize cli_type_id__volatile = 0;
    if (g_once_init_enter (&cli_type_id__volatile)) {
        static const GTypeInfo g_define_type_info = { sizeof (CliClass), (GBaseI
nitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) cli_class_init, (GClas
sFinalizeFunc) NULL, NULL, sizeof (Cli), 0, (GInstanceInitFunc) cli_instance_ini
t, NULL };
        GType cli_type_id;
        cli_type_id = g_type_register_static (G_TYPE_OBJECT, "Cli", &g_define_ty
pe_info, 0);
        g_once_init_leave (&cli_type_id__volatile, cli_type_id);
    }
    return cli_type_id__volatile;
}


static gint _vala_array_length (gpointer array) {
    int length;
    length = 0;
    if (array) {
        while (((gpointer*) array)[length]) {
            length++;
        }
    }
    return length;
}



It is obvious that the Vala code is much shorter than the generated C code. The Vala compiler took care chores of generating CPP macros for GObject with.

Previous Post Top Next Post