[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

getopt



This is a SysV-style getopt module for limbo. 

#----- cut --------------------------------------------------------
# getopts.m
# SysV style getopts

GetOpts: module
{
    PATH:  con "/dis/getopts.dis";

    opts: adt
    {
        argv: array of string;
        argc: int;
        optind: int;
        optarg: string; 
        getopt: fn(o: self ref opts) : int;
    };
    
    init: fn(params: list of string, optstr: string): ref opts;
    
};

#----- cut --------------------------------------------------------
# getopts.b
implement GetOpts;

include "getopts.m";
include "sys.m";
include "lib.m";

sys: Sys;
str: String;
newarg: int;    #if 0, advance to argv[x+1], else do (more of) argv[x]
optstring: string;


init(params: list of string, optstr: string) : ref opts
{
    str = load String String->PATH;         
    argc := len params;
    newarg = 1;
    optstring = optstr; 
    argv := array[argc + 1] of string;
    
    for(j := 0; params != nil; params = tl params)
        argv[j++] = hd params;
    #argv[argc] initialized to nil in definition
    o := ref opts(argv, n, 1, "");
    return o;   

}

opts.getopt(o: self ref opts) : int
{
    j, flg: int;    
    o.optarg = nil;
            
    if(o.optind == o.argc)
        return 0;   
    arg := o.argv[o.optind];
    
    if(newarg == 1)
        if(arg == "-"){
            if(o.optind < o.argc - 1 && o.argv[o.optind + 1] == "-")
                o.optind += 2;
            return 0;
        }else if(arg[0] != '-')
            return 0;
        else
            arg = arg[1:];

    (pre, suf) := str->splitl(optstring, arg[0:1]);
    if(suf == nil)
        return '?';
    flg = arg[0];
    if(len suf > 1 && suf[1] == ':'){
        newarg = 1;
        if(len arg > 1){   #option argument is suffixed to option letter
            o.optarg = arg[1:];
            o.optind++;
        }else if(o.optind + 1 == o.argc) #option argument missing
            flg = '?';
        else{              #option argument is next element of argv
            o.optind++;
            o.optarg = o.argv[o.optind++];
        }
    }else if(len arg == 1){
        o.optind++;
        newarg = 1;
    }else{                #more option letters in current element of
argv
        newarg = 0;
        o.argv[o.optind] = arg[1:];
    }

    return flg;
}