C-code generator for docopt language.

Related tags

Utilities docopt.c
Overview

C-code generator for docopt language

Note, at this point the code generator handles only options (positional arguments, commands and pattern matching will follow).

Step 1. Describe your CLI in docopt language

Naval Fate.

Usage:
  naval_fate.py ship create <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored|--drifting]
  naval_fate.py --help
  naval_fate.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

Step 2. Generate the C code

$ python docopt_c.py -o docopt.c example.docopt

or by using pipe

$ cat example.docopt | python docopt_c.py > docopt.c

Step 3. Include the generated docopt.c into your program

#include "docopt.c"

int main(int argc, char *argv[])
{
    DocoptArgs args = docopt(argc, argv, /* help */ 1, /* version */ "2.0rc2");

    printf("Commands\n");
    printf("    mine == %s\n", args.mine ? "true" : "false");
    printf("    move == %s\n", args.move ? "true" : "false");
    printf("    create == %s\n", args.create ? "true" : "false");
    printf("    remove == %s\n", args.remove ? "true" : "false");
    printf("    set == %s\n", args.set ? "true" : "false");
    printf("    ship == %s\n", args.ship ? "true" : "false");
    printf("    shoot == %s\n", args.shoot ? "true" : "false");
    printf("Arguments\n");
    printf("    x == %s\n", args.x);
    printf("    y == %s\n", args.y);
    printf("Flags\n");
    printf("    --drifting == %s\n", args.drifting ? "true" : "false");
    printf("    --help == %s\n", args.help ? "true" : "false");
    printf("    --moored == %s\n", args.moored ? "true" : "false");
    printf("    --version == %s\n", args.version ? "true" : "false");
    printf("Options\n");
    printf("    --speed == %s\n", args.speed);
    return 0;
}

Step 4. Profit!

$ c99 example.c -o example.out
$ ./example.out mine --drifting --speed=20
Commands
    mine == true
    move == false
    create == false
    remove == false
    set == false
    ship == false
    shoot == false
Arguments
    x == (null)
    y == (null)
Flags
    --drifting == true
    --help == false
    --moored == false
    --version == false
Options
    --speed == 20

Development

See the Python version's page for more info on developing.

Comments
  • We should not use __str__.replace()

    We should not use __str__.replace()

    Instead of: out = out.replace('<<<???>>>', substition)

    we should use something like [1] or

    "%(tag_identifier)s is great!" % {'tag_identifier': 'docopt'}

    [1] http://docs.python.org/2/library/string.html#template-strings

    opened by ffunenga 5
  • IMO, docopt.c.py has a bad CLI

    IMO, docopt.c.py has a bad CLI

    Currently, the user workflow when using docopt.c.py has two things that IMO are bad. This

    cat example.docopt | python docopt.c.py > docopt.c

    and the header of example.c file:

    #include "docopt.c"

    This is a bad CLI and a bad C implementation:

    • This is a sub-project of docopt and, as such, it should make use of it.
    • If you have a "big" project, normally you create a header file for the source of the module and then compile it separately.

    Proposed Solution

    Use the following docopt string, like I've implemented here [1]:

    usage: docopt_c.py [options] [DOCOPT]
    
    Processes a docopt formatted string, from either stdin or a file, and
    outputs the equivalent C code to parse the CLI, to either the stdout or a
    set of two files (.c and .h).
    
    Options:
      -o OUTNAME --output-name=OUTNAME
                    Filename used to write OUTNAME.h and OUTNAME.c.
                    If not present, an equivalent C file is printed to stdout.
      -d TEMPLATE --dev=TEMPLATE
                    Filename used to read TEMPLATE.c and TEMPLATE.h.
      -v <level> --verbosity=<level>
                    Set the verbosity level of stderr debug messages [default: 0]
      -h,--help     Show this help message and exit
    
    Arguments:
      DOCOPT        Input file describing your CLI in docopt language.
    
    

    Be aware of the comments inside the if __name__ == '__main__': at the end and the comments inside def __parse_cli(): in line 396.

    [1] https://github.com/ffunenga/docopt.c/blob/feature/update-workflow/src/docopt_c.py

    opened by ffunenga 5
  • IMO, repo has clutter

    IMO, repo has clutter

    I dont understand why the following files are in the repository:

    • docopt.c
    • log.h
    • test_docopt.c

    IMO, all the files in the upstream repo should have a justification why they are where they are.

    I know @halst and @kblomqvist have shown their preference for all files go to level 0 but I don't see any reason why NOT to:

    • organize the files into subfolders
    • not have any personal files in the main repo (proposed solution: put them somewhere else.... wiki, public link to dropbox, etc)
    postponed 
    opened by ffunenga 4
  • Organizes tree of files and copies license from docopt.py

    Organizes tree of files and copies license from docopt.py

    Create three folders: - src: with python scripts (docopt.py and docopt_c.py) - example: with the appropriate files from the example - dev: other files used for development purposes Adds license file copied from the docopt python project

    opened by ffunenga 3
  • Support for positional and ... arguments

    Support for positional and ... arguments

    I needed handling of positional arguments as well as one or more arguments so I made some changes which you can find here.

    https://github.com/jkcko/docopt.c/commit/23a68dd845985bf1cdeed1cc94dbae9e48a19e49

    The Command type now includes a pointer to an Argument array which lists the positional arguments for the command.

    Additional Argument arrays with prefix docopt_ are generated for each command.

    parse_argcmd will now assign value in the matching argument of elements->arguments and the positional docopt_ arrays. argument->value = argument value argument->count = number of arguments on the command line including this one (for counting ...) argument->array = points to argv for this argument (for ...)

    Usage for positional arguments would be something like.

       cfg command <arg1> <arg2> <arg3>
    
       if (arg.arg1 != NULL) {
           printf("arg1 %s\n", arg.arg1);
       }
       if (arg.arg2 != NULL) {
           printf("arg2 %s\n", arg.arg2);
       }
       if (arg.arg3 != NULL) {
           printf("arg3 %s\n", arg.arg3);
       }
    

    Usage for ... would be something like.

       cmd command <list-item>...
    
        if (docopt_command[0].count > 1) {
            /* more than one */
            char **array = docopt_command[0].array;
            for (i=0; i < count; i++) {
                list_item[i] = array[i];
            }
        }
        else {
            /* one */
            char *strp = args->command;
        }
    
    

    Caveat: [options] combined with positional arguments is not supported.

    opened by jkcko 2
  • Fixed docopt_c to work in python 3.

    Fixed docopt_c to work in python 3.

    There was only one problem, really. Python 3 doesn't understand the long keyword, since in python 3, longs are the same as ints. I added an if statement to detect which version of python is being used. It then either expects long or not as appropriate.

    I tested this change by following the example, and everything seems to work.

    opened by tokuchan 2
  • Unit tests are broken

    Unit tests are broken

    Just realized that Tokens* tokens_new() wasn't just a rename from Tokens tokens_create()... @ffunenga I'm not sure why do we added that extra param of Tokens itself in to the argument list of the function, and why do we return a pointer:

    Tokens* tokens_new(Tokens *ts, int argc, char **argv) {
        struct Tokens update = {argc, argv, 0, argv[0]};
        (*ts) = update;
        return ts;
    }
    

    If an update function is needed then let's add it separately.

    bug 
    opened by kblomqvist 2
  • How are we going to handle the

    How are we going to handle the "struct DocoptArgs" element's names?

    Currently we've got the Naval Fate example being converted from this:

    --- LeafNodes ---
      Argument('<y>', None)
      Argument('<x>', None)
      Argument('<name>', None)
      Command('remove', False)
      Command('set', False)
      Command('mine', False)
      Command('shoot', False)
      Command('ship', False)
      Command('move', False)
      Command('new', False)
      Option('--version', False)
      Option('--help', False)
      Option('--drifting', False)
      Option('--moored', False)
      Option('--speed', '10')
    

    to this:

    typedef struct {
        /* flag options */
        int help;
        int version;
        int moored;
        int drifting;
        /* options with arguments */
        char *speed;
        /* special */
        const char *usage_pattern;
        const char *help_message;
    } DocoptArgs;
    

    How do we translate CLI syntax into C valid struct elements?

    • if --help becomes DocoptArgs.help, what happens to <y>?
    • What about conflicts, are they possible? Example: there is a command called help (related with the application context) and there is the generic --help (related with the CLI context). Is this possible? How do we solve it?

    Valid variable names in C respect the following three rules:

    Variable names in C are made up of letters (upper and lower case) and digits.
    The underscore character ("_") is also permitted.
    Names must not begin with a digit.
    

    [EDIT1] Is this (a bad idea | ugly | not universal C)? leafname = ''.join(('_' if c in '<>-' else c) for c in leaf.name)

    originating in:

    typedef struct {
        int remove;
        int set;
        int mine;
        int shoot;
        int ship;
        int move;
        int new;
        int __version;
        int __help;
        int __drifting;
        int __moored;
        char *_y_;
        char *_x_;
        char *_name_;
        char *__speed;
        const char *usage_pattern;
        const char *help_message;
    } DocoptArgs;
    

    In my PC, it compiles and executes.

    [EDIT2] Possible conflict: an argument called __remove and an option named --remove wich will become __remove. Its crazy/strange to have an argument named __remove.

    Maybe Arguments not starting in letters should be prohibited upstream. @docopt/docopt @halst Or maybe only docopt_c.py should prohibit it.

    tbd 
    opened by ffunenga 2
  • why is the main script called docopt.c.py instead of the initial docopt_c.py?

    why is the main script called docopt.c.py instead of the initial docopt_c.py?

    This is problematic (and very restrictive) because this project is still in the beginning and deciding something like this will restrict the option of, in the future, make a python script have this:

    import docopt_c
    # or
    from docopt_c import docopt_c
    

    which BTW does not work if written like this:

    >>> import docopt.c
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ImportError: No module named c
    

    We need to think five years ahead of our time, always!

    opened by ffunenga 2
  • Add support for docopt's [options] shortcut (closes issue #22)

    Add support for docopt's [options] shortcut (closes issue #22)

    When the [options] shortcut is detected on the usage section, we use the contents of the options section to get the full list of options, rather than just getting those options that are explicitly mentioned on the usage section.

    opened by AngelEzquerra 1
  • Feature/change string replace

    Feature/change string replace

    results_new results_old

    Just to make sure, I've tested out the times between the two methods in my PC and string.Template turned out to be ((232-187)/232 =) 19% faster than __str__.replace

    opened by ffunenga 1
  • missing template.c file

    missing template.c file

    ls ./.local/lib/python3.10/site-packages/docopt_c/ docopt_c.py docopt.py init.py main.py pycache

    python3 -m docopt_c -o lol haha [Errno 2] No such file or directory: '/home/me/.local/lib/python3.10/site-packages/docopt_c/_data/template.c'

    opened by activedecay 4
  • Add support for position arguments

    Add support for position arguments

    I wanted this type of usage pattern to work:

    myApp <filename> [--debug=LEVEL]
    

    So, I enabled the argument processing. For some reason, the iteration included argv[0] (the launching program), so I skip that. I presume that bug is why command processing didn't work before either, but I don't have a use case for command processing, and didn't investigate that any further.

    opened by tony-jacobs 0
  • Example not working

    Example not working

    Generating code using the "Naval Fate" example produces broken header. Line 97 & 98.

    struct DocoptArgs {
        
        /* commands */
        size_t create;
        size_t mine;
        size_t move;
        size_t remove;
        size_t set;
        size_t ship;
        size_t shoot;
        /* arguments */
        char *name;
    {indent}char *x;
    {indent}char *y;
        /* options without arguments */
        size_t drifting;
        size_t help;
        size_t moored;
        size_t version;
        /* options with arguments */
        char *speed;
        /* special */
        const char *usage_pattern;
        const char *help_message[16];
    };
    

    I'm running Python 3.10.0

    opened by andreas-jonsson 0
  • Add support for variable prefix

    Add support for variable prefix

    It is currently not possible to use an option or command name that happesn to be a C keyword. So for example trying to have a command named "register" will fail with a compilation error.

    This introduces support for setting a prefix for the variable names defined in the struct. So for example using prefix _ would mean you access the command via args._register instead.

    opened by JoakimSoderberg 0
  • Fix for Issue #32 arguments not working

    Fix for Issue #32 arguments not working

    I would like my changes to support positional arguments (Issue #32) to be considered for merging.

    The naval fate example now works with options before or after the positional arguments.

    opened by jkcko 3
Owner
null
My collection of raylib code examples - For learning the C language with 2D and 3D games.

Raylib-Examples My collection of raylib examples. ( https://www.raylib.com/index.html ) For Raylib Version of 4 april 2020 ( Notepad++ windows install

Rudy Boudewijn van Etten 49 Dec 28, 2022
runsc loads 32/64 bit shellcode (depending on how runsc is compiled) in a way that makes it easy to load in a debugger. This code is based on the code from https://github.com/Kdr0x/Kd_Shellcode_Loader by Gary "kd" Contreras.

runsc This code is based on the code from https://github.com/Kdr0x/Kd_Shellcode_Loader by Gary "kd" Contreras and contains additional functionality. T

null 24 Nov 9, 2022
WAFer is a C language-based software platform for scalable server-side and networking applications. Think node.js for C programmers.

WAFer WAFer is a C language-based ultra-light scalable server-side web applications framework. Think node.js for C programmers. Because it's written i

Riolet Corporation 693 Dec 6, 2022
Simple Virtual Machine with its own Bytecode and Assembly language.

BM Simple Virtual Machine with its own Bytecode and Assembly language. Build We are using nobuild build system which requires a bootstrapping step wit

Tsoding 87 Jan 1, 2023
Open Data Description Language

Open Data Description Language This is the reference parser for the Open Data Description Language (OpenDDL), version 3.0. The official language speci

Eric Lengyel 40 Dec 27, 2022
C language utility library

versatile and easy to use C language utility library with functions and macros commonly used in various applications

Tilen Majerle 42 Dec 28, 2022
Statically typed programming language.

Summary Luxury is a statically programming langage which is targeting embedded programming. I will eventually stop using C and fully use this language

null 39 Oct 5, 2022
A interpreter that runs the script which is programmed in the language of FF0 script (or you can call it as Warfarin)

ff0-script A interpreter that runs the script which is programmed in the language of FF0 script (or you can call it as Warfarin) You can do it, unders

null 24 Apr 27, 2022
An implementation of yacc for the janet programming language.

janet-yacc An implementation of yacc for the janet programming language. The implementation is based heavily on https://c9x.me/yacc/. Example from ./e

null 11 Nov 22, 2021
Whitee is a tiny compiler written in C++17, which translates SysY language into ARM-v7a assembly.

Whitee is a tiny compiler written in C++17, which translates SysY language into ARM-v7a assembly. Table of Contents Background Install Usage Ar

null 14 Dec 11, 2022
A tiny programming language that transpiles to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly 🚀

A tiny programming language that transpiles to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly ??

Lingdong Huang 587 Jan 7, 2023
Utilities and common code for use with raylib

Utilities and shared components for use with raylib

Jeffery Myers 86 Dec 1, 2022
Example code for interfacing with a LCD with a Raspberry Pi Pico

picoLCD is a collection of functions to make interfacing with HD44780 based LCD screens easier on the Raspberry Pi Pico. Rather than reading through data sheets to figure out the correct set of instructions to send to the screen, picoLCD attempts to make it a simpler process, while still being extremely versatile.

null 25 Sep 8, 2022
An attempt to restore and adapt to modern Win10 version the Rootkit Arsenal original code samples

rootkit-arsenal-guacamole An attempt to restore and adapt to modern Win10 version the Rootkit Arsenal original code samples All projects have been por

Matteo Malvica 51 Nov 6, 2022
A toolchain for injecting custom code into Super Mario Galaxy 2.

Syati Syati is a custom code loader for Super Mario Galaxy 2. It is able to compile custom code and link to existing functions in the game to create o

shibbs 20 Mar 29, 2022
This project aims to facilitate debugging a kernel driver in windows by adding support for a code change on the fly without reboot/unload, and more!

BSOD Survivor Tired of always telling yourself when you got a BSOD that what if I could just return to the caller function which caused the BSOD, and

Ido Westler 159 Dec 21, 2022
The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.

The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.

Microsoft 7.2k Jan 2, 2023
Source code for Amiga intro Planet Disco Balls

Planet Jazz - Planet Disco Balls (Amiga A500 Intro Source) What is it? This is the 68000 assembler source code for the Planet Jazz "Planet Disco Balls

Jonathan Bennett 21 Oct 1, 2022
MacFlim flim player source code and utilities

MacFlim Video player source code Please do not barf on code quality. It was not in releasable state, but people wanted to use it. You may even be one

Fred Stark 71 Jan 1, 2023