Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 233 lines (199 sloc) 4.9 KB
#!/bin/bash
#
# Generates C "Object" Skeletons Simply and Properly
# Justine Tunney <jtunney@lobstertech.com>
# Licensed MIT
#
function ask {
dest=$1
descrip=$2
default=$3
[[ ! $default ]] && default=$4
[[ ! $default ]] && default=$5
echo -n "$descrip "
[[ $default ]] && echo -n "[$default] "
read $dest
[[ ! $(eval echo $dest) ]] && eval $dest="$default"
}
[[ $NAME ]] || NAME="$1"
[[ $NAME ]] || ask NAME "object name?"
[[ $NAME ]] || exit 1
[[ $PROJ ]] || PROJ="$2"
[[ $PROJ ]] || ask PROJ "project name?"
[[ $PROJ ]] || exit 1
[[ $DESCRIP ]] || ask DESCRIP "description?" "$PROJ"
[[ $EMAIL ]] || ask EMAIL "author email?" "$(git config user.email)" "$USER@$(hostname -f)"
[[ $AUTHOR ]] || ask AUTHOR "author name?" "$(git config user.name)" "$USER"
[[ $LICENSE ]] || ask LICENSE "license?" "GNU AGPL v3 or later"
UPPROJ=$(echo $PROJ | tr a-z A-Z)
UPNAME=$(echo $NAME | tr a-z A-Z)
echo "generating $NAME.h..."
(
cat <<EOF
/*
* $PROJ -- $DESCRIP
* Copyright (c) $(date +%Y) $AUTHOR
* Licensed $LICENSE
*/
/**
* @file ${NAME}.h
* @brief ${NAME} object
*/
#ifndef ${UPPROJ}_${UPNAME}_H
#define ${UPPROJ}_${UPNAME}_H
#include <assert.h>
#define ${UPPROJ}_${UPNAME}_TOKEN 0xACAB
typedef struct ${PROJ}_${NAME}_s ${PROJ}_${NAME}_t;
struct ${PROJ}_${NAME}_s {
EOF
if [[ $USE_SOFIA ]]; then
echo " su_home_t home[1]; /**< Binary-compat with sofia mem pool */"
else
echo " int refs; /**< reference count of object */"
fi
echo " int token; /**< ${UPPROJ}_${UPNAME}_TOKEN if not destroyed */"
cat <<EOF
};
/**
* Allocates a $NAME object
*
* @return $NAME object or NULL or error.
* @sa ${PROJ}_${NAME}_unref(), ${PROJ}_${NAME}_destroy()
*/
${PROJ}_${NAME}_t *${PROJ}_${NAME}_new();
/**
* Increase dictionary object reference count
*
* @param ${NAME} ${NAME} object
* @return Pointer to same object or NULL on error.
* @sa ${PROJ}_${NAME}_unref()
*/
${PROJ}_${NAME}_t *${PROJ}_${NAME}_ref(${PROJ}_${NAME}_t *${NAME});
/**
* Decrease dictionary object reference count
*
* If ref count reaches zero, object will be freed immediately.
*
* @param ${NAME} ${NAME} object
* @return Pointer to same object or NULL on error.
* @sa ${PROJ}_${NAME}_unref()
*/
int ${PROJ}_${NAME}_unref(${PROJ}_${NAME}_t *${NAME});
/**
* Is your pointer valid?
*
* @param ${NAME} ${NAME} object
* @return 1 if NULL, 0 if good, crash if bad memory
*/
int ${PROJ}_${NAME}_badmem(${PROJ}_${NAME}_t *${NAME});
#endif /* ${UPPROJ}_${UPNAME}_H */
/* For Emacs:
* Local Variables:
* indent-tabs-mode:nil
* tab-width:4
* c-basic-offset:4
* c-file-style:nil
* End:
* For VIM:
* vim:set expandtab softtabstop=4 shiftwidth=4 tabstop=4:
*/
EOF
) >$NAME.h
echo "generating $NAME.c..."
(
cat <<EOF
/*
* $PROJ -- $DESCRIP
* Copyright (c) $(date +%Y) $AUTHOR
* Licensed $LICENSE
*/
/**
* @file ${NAME}.c
* @brief ${NAME} object implementation
*/
#include "${PROJ}_private.h"
EOF
if [[ $USE_SOFIA ]]; then
cat <<EOF
static void destroy(void *arg)
{
${PROJ}_${NAME}_t *${NAME} = arg;
if (${PROJ}_${NAME}_badmem(${NAME}))
return;
${NAME}->token = 0;
}
${PROJ}_${NAME}_t *${PROJ}_${NAME}_new()
{
${PROJ}_${NAME}_t *${NAME} = su_home_new(sizeof(${PROJ}_${NAME}_t));
su_home_destructor(${NAME}->home, destroy);
${NAME}->token = ${UPPROJ}_${UPNAME}_TOKEN;
return ${NAME};
}
${PROJ}_${NAME}_t *${PROJ}_${NAME}_ref(${PROJ}_${NAME}_t *${NAME})
{
return (${PROJ}_${NAME}_t *)su_home_ref((su_home_t *)${NAME});
}
int ${PROJ}_${NAME}_unref(${PROJ}_${NAME}_t *${NAME})
{
return su_home_unref((su_home_t *)${NAME});
}
EOF
else
cat <<EOF
static void destroy(${PROJ}_${NAME}_t *${NAME})
{
if (${PROJ}_${NAME}_badmem(${NAME}))
return;
${NAME}->token = 0;
free(${NAME});
}
${PROJ}_${NAME}_t *${PROJ}_${NAME}_new()
{
${PROJ}_${NAME}_t *${NAME} = calloc(1, sizeof(${PROJ}_${NAME}_t));
${NAME}->token = ${UPPROJ}_${UPNAME}_TOKEN;
return ${PROJ}_${NAME}_ref(${NAME});
}
${PROJ}_${NAME}_t *${PROJ}_${NAME}_ref(${PROJ}_${NAME}_t *${NAME})
{
if (!${PROJ}_${NAME}_badmem(${NAME})) {
${NAME}->refs++;
return ${NAME};
} else {
return NULL;
}
}
int ${PROJ}_${NAME}_unref(${PROJ}_${NAME}_t *${NAME})
{
if (${PROJ}_${NAME}_badmem(${NAME}))
return 1;
if (--${NAME}->refs == 0) {
${PROJ}_${NAME}_destroy(${NAME});
return 1;
}
return 0;
}
EOF
fi
cat <<EOF
int ${PROJ}_${NAME}_badmem(${PROJ}_${NAME}_t *${NAME})
{
if (!${NAME})
return true;
if (${NAME}->token != ${UPPROJ}_${UPNAME}_TOKEN) {
fprintf(stderr, "${PROJ}_${NAME}_t memory error detected\n");
return true;
}
return false;
}
/* For Emacs:
* Local Variables:
* indent-tabs-mode:nil
* tab-width:4
* c-basic-offset:4
* c-file-style:nil
* End:
* For VIM:
* vim:set expandtab softtabstop=4 shiftwidth=4 tabstop=4:
*/
EOF
) >$NAME.c
Something went wrong with that request. Please try again.