PreviousUpNext

15.4.17  src/app/c-glue-maker/main.pkg

## main.pkg - Driver routine ("main") for c-glue-maker.
#
# In this file, we digest the commandline switches,
# then call gen::gen with the digested switches
# plus the list of C sourcefiels to process.
#
# See ../README for an overview, and
# ../c-glue-lib/doc/* for additional info.

# Compiled by:
#     src/app/c-glue-maker/c-glue-maker.lib


stipulate
    package fil =  file__premicrothread;                                # file__premicrothread          is from   src/lib/std/src/posix/file--premicrothread.pkg
herein

    package main {
        #
        stipulate
            #
            package re
                =
                regular_expression_matcher_g (                          # regular_expression_matcher_g  is from   src/lib/regex/glue/regular-expression-matcher-g.pkg
                    #
                    package p =  awk_syntax;                            # awk_syntax                    is from   src/lib/regex/front/awk-syntax.pkg
                    package e =  dfa_engine;                            # dfa_engine                    is from   src/lib/regex/backend/dfa-engine.pkg
                );


            stipulate
                fun target (name, sizes, shift)
                    =
                    { name, sizes, shift };

            herein
                default_target
                    =
                    target (
                        default_name::name,
                        default_sizes::sizes,
                        default_endian::shift
                    );

                target_table
                    =
                    [ target ("sparc32-posix", sizes_sparc32::sizes, endian_big::shift   ),
                      target ("intel32-posix", sizes_intel32::sizes, endian_little::shift),
                      target ("intel32-win32", sizes_intel32::sizes, endian_little::shift),
                      target ("pwrpc32-posix", sizes_pwrpc32::sizes, endian_little::shift)
                      #  needs to be extended ... 
                    ];
            end;
                                                                        # sizes_sparc32                 is from   src/app/c-glue-maker/sizes-sparc32.pkg
                                                                        # sizes_intel32                 is from   src/app/c-glue-maker/sizes-intel32.pkg
                                                                        # sizes_pwrpc32                 is from   src/app/c-glue-maker/sizes-pwrpc32.pkg
                                                                        # list                          is from   src/lib/std/src/list.pkg
                                                                        # string                        is from   src/lib/std/string.pkg


            fun find_target target
                =
                case (list::find   (\\ x =   target == x.name)   target_table)
                    #
                    THE t => t;
                    NULL  => raise exception DIE (cat ["unknown target: " + target]);
                esac;


            fun main0 (arg0, args)
                =
                # 'arg0' is the program name, which we ignore.
                #
                # 'args' is the list of commandline arguments,
                # which consists of switches ('-foo') followed
                # by C sourcefile names.
                #
                # We eat the switches, then call gen::gen
                # with the digested switch info plus the
                # list of source files to process:
                #
                proc args
                where
                    fun substitute (tmpl, opts, s, t)                # Make %s %t %o substitutions
                        =
                        loop (string::explode tmpl, [])
                        where
                            fun loop ([],            a) =>   string::implode (reverse a);
                                loop ('%' ! 's' ! l, a) =>   loop (l, push (s,    a));
                                loop ('%' ! 't' ! l, a) =>   loop (l, push (t,    a));
                                loop ('%' ! 'o' ! l, a) =>   loop (l, push (opts, a));
                                loop (       c  ! l, a) =>   loop (l, c ! a);
                            end 

                            also
                            fun push (x, a)
                                =
                                list::reverse_and_prepend (string::explode x, a);

                        end;

                    dir               =   REF "glue";
                    makelib_file        =   REF "glue.lib";

                    prefix            =   REF "";
                    gstem             =   REF "";

                    extra_members     =   REF [];
                    library_handle    =   REF "library::lib_handle";

                    asu               =   REF FALSE;            # I think "asu" == "all struct union". FWIW.
                    width             =   REF NULL;

                    mythryl_opts      =   REF [];
                    noguid            =   REF TRUE;

                    target            =   REF default_target;
                    weight_request    =   REF NULL;

                    named_args        =   REF FALSE;
                    collect_enums     =   REF TRUE;

                    enum_constructors =   REF FALSE;
                    cpp_options       =   REF "";
                    regexp            =   REF NULL;

                    # We're called with the list of non-switch
                    # commandline arguments, which is to say,
                    # with a list of C source files to process:

                                                            # winix__premicrothread             is from   src/lib/std/winix--premicrothread.pkg
                                                            # string                    is from   src/lib/std/string.pkg
                    fun do_cfiles cfiles
                        =
                        {   fun preprocess_c_sourcefile cfile
                                =
                                {   ifile =   winix__premicrothread::file::tmp_name ();
                                    #
                                    cpp_template
                                        =
                                        the_else (
                                            winix__premicrothread::process::get_env "FFIGEN_CPP",
                                            "gcc -E -U__GNUC__ %o %s > %t"
                                        );

                                    cpp =   substitute (cpp_template, *cpp_options, cfile, ifile);


                                    if (winix__premicrothread::process::bin_sh'  cpp   !=   winix__premicrothread::process::success)
                                        #
                                        raise exception DIE ("C-preprocessor failed: " + cpp);
                                    fi;

                                    ifile;
                                };

                            match
                                =
                                {   fun match_string scan_g s
                                        =
                                        {   n =   size s;

                                            fun getc i          # Return i-th char from string 's', else NULL.
                                                =
                                                i < n   ??   THE (string::get_byte_as_char (s, i), i + 1)
                                                        ::   NULL;

                                            case (scan_g  getc  0)
                                                #
                                                THE (x, k)   =>   k == n;
                                                NULL         =>   FALSE;
                                            esac;
                                        };

                                    case *regexp
                                        #
                                        NULL   =>  \\ _ = FALSE;
                                        THE re =>  match_string  (re::prefix  re);
                                    esac;
                                };

                            gen::gen { cfiles,
                                       match,
                                       preprocess_c_sourcefile,

                                       dirname        => *dir,
                                       makelib_file     => *makelib_file,
                                       prefix         => *prefix,

                                       gensym_stem    => *gstem,
                                       extra_members  => *extra_members,
                                       library_handle => *library_handle,

                                       all_su         => *asu,
                                       mythryl_options => reverse *mythryl_opts,
                                       noguid         => *noguid,

                                       weightreq      => *weight_request,
                                       wid            => the_else (*width, 75),
                                       namedargs      => *named_args,

                                       collect_enums  => *collect_enums,
                                       enumcons       => *enum_constructors,
                                       target         => *target
                                     };

                            winix__premicrothread::process::success;
                        };

                    # Recognize options for cpp (the C pre-processor):
                    fun is_cpp_option option
                        =
                        size option   >   2
                        and
                        string::get_byte_as_char (option, 0) == '-'
                        and
                        char::contains "IDU" (string::get_byte_as_char (option, 1));

                    fun note_cpp_option option
                        =
                        cpp_options :=  case *cpp_options
                                            #
                                            ""      =>   option;
                                            options =>   cat [options, " ", option];
                                        esac;



                    # Process commandline switches, then
                    # call 'do_cfiles' on remaining commandline args,
                    # which will be the C source files to process:
                    #
                    fun proc ("-allSU" ! l)                             => { asu := TRUE;                          proc l; };
                        proc (("-width" | "-w") ! i ! l)                => { width := int::from_string i;          proc l; };
                        proc (("-mythryl-option" | "-opt") ! s ! l)     => { mythryl_opts := s ! *mythryl_opts;    proc l; };

                        proc ("-guids" ! l)                             => { noguid := FALSE;                      proc l; };
                        proc (("-target" | "-t") ! tg ! l)              => { target := find_target tg;             proc l; };
                        proc (("-light" | "-l") ! l)                    => { weight_request := THE FALSE;  proc l; };

                        proc (("-heavy" | "-h") ! l)                    => { weight_request := THE TRUE;   proc l; };
                        proc (("-namedargs" | "-na") ! l)               => { named_args := TRUE;           proc l; };
                        proc (("-libhandle" | "-lh") ! lh ! l)          => { library_handle := lh;         proc l; };

                        proc (("-prefix" | "-p") ! p ! l)               => { prefix  := p;                         proc l; };
                        proc (("-gensym" | "-g") ! g ! l)               => { gstem   := g;                         proc l; };

                        proc (("-dir" | "-d") ! d ! l)                  => { dir     := d;                 proc l; };
                        proc (("-libfile" | "-m7") ! f ! l)             => { makelib_file := f;            proc l; };
                        proc ("-cppopt" ! opt ! l)                      => { note_cpp_option opt;          proc l; };

                        proc ("-nocollect" ! l)                         => { collect_enums := FALSE;       proc l; };
                        proc (("-ec" | "-enum-constructors") ! l)       => { enum_constructors := TRUE;    proc l; };

                        proc (("-include" | "-add") ! es ! l)           => { extra_members := es ! *extra_members; proc l; };
                        proc (("-match" | "-m") ! re ! l)               => { regexp := THE (re::compile_string re);  proc l; };
                        proc ("--" ! cfiles)                            => do_cfiles cfiles;

                        proc ("-version" ! _)
                            =>
                            {   fil::write  (fil::stdout,  gen::version + "\n");
                                #
                                winix__premicrothread::process::exit_x 0;
                            };

                        proc (l0 as (option ! l))
                            =>
                            if (is_cpp_option  option)
                                #
                                note_cpp_option  option;
                                proc l;
                            else
                                do_cfiles l0;
                            fi;

                        proc cfiles
                            =>
                            do_cfiles  cfiles;
                    end;
                end;              # fun main0

        herein

            fun print_history (h ! hs)
                    =>
                    {   fil::write (fil::stderr, cat ["\t", h, "\n"]);
                        #
                        print_history hs;
                    };

                print_history []
                    =>
                    ();
            end;

            fun main args
                =
                main0 args
                except
                    exn =  {    fil::write (fil::stderr, exceptions::exception_message exn);
                                fil::write (fil::stderr, "\n");
                                print_history  (lib7::exception_history exn);
                                winix__premicrothread::process::failure;
                           };
        end;                    # stipulate
    };                          # pkg main
end;


## (C) 2004  The Fellowship of SML/NJ
## author: Matthias Blume (blume@tti-c.org)
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext