# Control structures {{{
snippet     if
options     head
abbr        if () {}
    if (${1:#:condition}) {
        ${0:TARGET}
    }

# No head option in else/elseif so it can be expanded after "}"
snippet     else
abbr        else {}
    else {
        ${0:TARGET}
    }

snippet     elseif
abbr        else () {}
    else if (${1:#:condition}) {
        ${0:TARGET}
    }

snippet     ifelse
options     head
abbr        if () {} else {}
    if (${1:#:condition}) {
        ${2:TARGET}
    } else {
        ${3}
    }

snippet     for
options     head
abbr        for () {}
    for (${1:int} ${2:i} = ${3:0}; $2 < ${4}; $2++) {
        ${0:#:TARGET}
    }

# Counter based for's (don't ask for the type or count start)
snippet     fori
options     head
abbr        for (int x;...; x++) {}
    for (int ${1:i} = 0; $1 < ${2}; $1++) {
        ${0:#:TARGET}
    }

# For reverse counter
snippet     forri
options     head
abbr        for (int x; ...; x--) {}
    for (int ${1:i} = ${2}; $1 >= 0; $1--) {
        ${0:#:TARGET}
    }

snippet     while
options     head
abbr        while () {}
    while (${1:#:condition}) {
        ${0:TARGET}
    }

snippet     do_while
options     head
alias       do
    do {
        ${0:TARGET:code}
    } while (${1:#:condition});

snippet     switch
options     head
abbr        switch () {}
	switch (${1:#:var}) {
		case ${2:#:val}:
			${0:TARGET}
			break;
	}

snippet     case
options     head
abbr        case: break;
	case ${1}:
		${0}
		break;

# Ternary conditional operator
snippet conditional
    (${1:#:condition}) ? ${2:#:a} : ${3:#:b}

# }}}

# Definition bodies {{{
snippet     function
options     head
alias       func
abbr        func() {}
    ${1:void} ${2:#:func_name}(${3:void}) {
        ${0:TARGET}
    }

snippet     struct
options     head
abbr        struct {}
    struct ${1:#:name} {
        ${0:TARGET:data}
    };

# Typedef struct
snippet     struct_typedef
options     head
    typedef struct ${1:#:name} {
        ${0:TARGET:data}
    };

snippet     enum
options     head
abbr        enum {}
    enum ${1:#:name} {
        ${0:TARGET}
    };

# hard-tab is necessary; C indent doesn't support this.
snippet     main
options     head
	int main(int argc, char const* argv[])
	{
		${0:TARGET}
		return 0;
	}

snippet     helloworld
options     head
    #include <stdio.h>
    int main(int argc, char const* argv[])
    {
        puts("hello, world!");
        return 0;
    }

# }}}

# Preprocessing directives {{{
# #include <...>
snippet     inc
options     head
alias       #inc, #include
    #include <${1:stdio}.h>

# #include "..."
snippet     inc2
options     head
alias       #inc2, #include2
    #include "${1}.h"

snippet     #if
options     head
    #if ${1}
    ${0}
    #endif

snippet     ifdef
options     head
alias       #ifdef
abbr        #ifdef ... #endif
    #ifdef ${1:#:SYMBOL}
    ${0}
    #endif

snippet     ifndef
options     head
alias       #ifndef
abbr #ifndef ... #define ... #endif
    #ifndef $1
    #define ${1:#:SYMBOL}
    #endif${0}

# This snippet used the placeholder instead of a trailing space
snippet     def
options     head
alias       #def, #define
    #define ${1}

# Include-Guard
snippet     once
options     head
alias       include-guard
abbr #ifndef ... #define ... #endif
    #ifndef ${1:#:SYMBOL}
        #define $1

        ${0:TARGET}
    #endif /* end of include guard */

# }}}

# Built-in function calls {{{
snippet printf
abbr    printf("...\n", ...);
    printf("${1}\n"${2});

snippet scanf
abbr    scanf("...", ...);
    scanf("${1}", ${2});

snippet fprintf
abbr    fprintf(..., "...\n", ...);
    fprintf(${1:stderr}, "${2}\n"${3});

snippet fopen
abbr fopen("...", "...");
	fopen("${1:PATH}", "${2:MODE}");
	${0:TARGET}
	fclose(${3:FD});

snippet fgets
abbr    fgets(row, length, file);
    fgets(${0:ROW}, ${1:LENGTH}, ${2:stdin});

snippet fscanf
abbr    fscanf(file, "...", ...);
    fscanf(${1:stdin}, "${2}", ${3});

snippet fwrite
abbr    fwrite(......, file)
    fwrite(${1:ARRAY}, sizeof(${2:TYPE}), ${3:N_MEMBERS}, ${4:FILE})

snippet fread
abbr    fread(......, file)
    fread(${1:ARRAY}, sizeof(${2:TYPE}), ${3:N_MEMBERS}, ${4:FILE})

snippet memcpy
abbr    memcpy(dest, src, nbytes)
    memcpy(${1:DEST}, ${2:SRC}, ${3:NBYTES})

snippet malloc
abbr    malloc(size)
	($2 *)malloc(${1:N_MEMBERS} * sizeof(${2:TYPE}));
	${0}
	free(${3:MEM});

snippet calloc
abbr    calloc(n, size)
	($2 *)calloc(${1:N_MEMBERS}, sizeof(${2:TYPE}));
	${0}
	free(${3:MEM});

snippet realloc
abbr    realloc(old, size)
	($3 *)realloc(${1:OLD}, ${2:N_MEMBERS} * sizeof(${3:TYPE}));
	${0}

snippet seed_rand
    srand(time(NULL));
# }}}

# Built-in operators and alias {{{
snippet typedef
    typedef ${1:#:base_type} ${2:#:custom_type};

snippet sizeof
alias   size
    sizeof(${0:TARGET})

snippet sizeof_array
alias   array_size
    (sizeof(${1:#:array}) / sizeof(*($1)))

snippet _Static_assert
alias   _static_assert
options head
    _Static_assert(${1:#:condition}, ${2:#:message});

snippet static_assert
options head
    static_assert(${1:#:condition}, ${2:#:message});

snippet _Generic
alias   generic, select
    _Generic(${1:#:expression}, ${2:#:association-list})

snippet va_list
options head
abbr    va_start(va_list, last_arg); ... ; va_end()
	va_list ${1:ap};
	va_start($1, ${2:LAST_ARG});
	${0}
	va_end($1);
# }}}

# Comments {{{
snippet comment
alias   /*
    /* ${1:#:comment} */
    ${0}

snippet     doxy
abbr        /** @brief ...
options     head
    /**
     * @brief    ${1:function description}
     *
     * @details  ${2:detailed description}
     *
     * @param    ${3:param}
     *
     * @return   ${4:return type}
     */

# }}}

# vim: fdm=marker
