Skip to content

Instantly share code, notes, and snippets.

@eni23
Created July 6, 2015 08:57
Show Gist options
  • Save eni23/b11e6fc0551e89dac20b to your computer and use it in GitHub Desktop.
Save eni23/b11e6fc0551e89dac20b to your computer and use it in GitHub Desktop.
#!/bin/bash
# genstatic.sh-0.1.3
# by eni@e23.ch
usage(){
cat << 'EOF'
genstatic.sh
Generate xxd-include & header from a directory
Usage:
genstatic.sh -i -c -h [--rsn] [--dtn] [--stn] [--mtn] [--fnl] [--fng] [--xxd]
Arguments:
-i input directory
-h output header filename
-c output source filename
--rsn resource name
--dtn DATATABLE name (default: datatable)
--stn size table name (default: datatable_size)
--mtn mime table name (default: datatable_mime)
--fnl lookup function name (default: lookup_file)
--fng getter function name (defaut: get_file)
--xxd xxd binary
EOF
exit
}
DATA_TABLE_NAME="datatable"
SIZE_TABLE_NAME="datatable_size"
MIME_TABLE_NAME="datatable_mime"
RESOURCE_PREFIX="staticfile_"
LOOKUP_FUNCTION_NAME="lookup_file"
GETTER_FUNCTION_NAME="get_file"
XXD="/usr/bin/xxd"
eval set -- $(getopt -o i:h:c: -l rsn:,dtn:,stn:,fnl:,fng:xxd:,mtn:,help -- "$@")
while true; do
case "$1" in
-i)
shift;
INPUT_DIR=$1
;;
-h)
shift;
HEADER_FILENAME=$1
;;
-c)
shift;
SOURCE_FILENAME=$1
;;
--rsn)
shift;
RESOURCE_PREFIX=$1
;;
--dtn)
shift;
DATA_TABLE_NAME=$1
;;
--stn)
shift;
SIZE_TABLE_NAME=$1
;;
--mfn)
shift;
MIME_TABLE_NAME=$1
;;
--fnl)
shift;
LOOKUP_FUNCTION_NAME=$1
;;
--fng)
shift;
GETTER_FUNCTION_NAME=$1
;;
--xxd)
shift;
XXD=$1
;;
--help)
usage
;;
--)
shift
break
;;
esac
shift
done
if [ ! -d "$INPUT_DIR" ]; then
echo "Directory $INPUT_DIR does not exists"
exit 1
fi
INPUT_COUNT=$( find $INPUT_DIR -not -empty -type f | wc -l)
if (("$INPUT_COUNT"<1)); then
echo "Directory $INPUT_DIR does not contain any files"
exit 1
fi
SOURCENAME=$(basename $SOURCE_FILENAME)
HEADNAME=$(basename $HEADER_FILENAME)
TEMPDIR=$(mktemp -d --suffix=genstatic.sh)
TEMPSOURCE="$TEMPDIR/$SOURCENAME"
TEMPHEAD="$TEMPDIR/$HEADNAME"
touch $TEMPSOURCE
touch $TEMPHEAD
# head template
cat << 'EOF' > $TEMPHEAD
/*
* Embedded static files, header
* generated: #!gendate
*
* This FILE is autogenerated, do not edit manually
*/
#ifndef STATICFILES_H
#define STATICFILES_H
#include "Arduino.h"
int #!lookupfn(const char *name);
const uint32_t staticfile_get_size(int staticfile_id);
const char *staticfile_get_mime(int staticfile_id);
extern const char *staticfile_mimetable[];
extern PROGMEM uint8_t *datatable[];
extern const uint32_t staticfile_sizetable[];
#endif
EOF
# source template
cat << 'EOF' > $TEMPSOURCE
/*
* Embedded static files, source
* generated: #!gendate
*
* This FILE is autogenerated, do not edit manually
*/
#include "Arduino.h"
#include "#!headfilename"
int #!lookupfn(const char *name){
typedef struct item_t { const char *name; int id; } item_t;
item_t table[] = {
#!LOOKUPTABLE { 0, 0 }
};
for (item_t *p = table; p->name != 0; ++p) {
if (strcmp(p->name, name) == 0) {
return p->id;
}
}
return 0;
}
const uint32_t staticfile_sizetable[]={
#!sizetable
};
const char *staticfile_mimetable[]={
#!mimetable
};
const uint32_t staticfile_get_size(int staticfile_id){
return staticfile_sizetable[staticfile_id+1];
}
const char *staticfile_get_mime(int staticfile_id){
return staticfile_mimetable[staticfile_id+1];
}
EOF
IFS=$'\n' FILES=($( find $INPUT_DIR -not -empty -type f | sed "s:^$INPUT_DIR/::" ))
FLENGTH=${#FILES[@]}
LOOKUPTABLE=""
DATATABLE=""
SIZETABLE=""
MIMETABLE=""
RESID=1
TOTALSIZE=0
for (( i=0; i<${FLENGTH}; i++ )); do
IFS=$'\n' FILE="${FILES[$i]}"
REALFILE=$INPUT_DIR/$FILE
RESVAR=$RESOURCE_PREFIX$RESID
TEMPFILE=$TEMPDIR/$RESVAR
echo "$RESID: $FILE"
FILEINFO=$(file $REALFILE | sed "s:^$INPUT_DIR/::")
FILEMIME=$(file -b --mime-type $REALFILE)
FILEINFO_SHORT=${FILEINFO:0:80}
FILESIZE=$(ls -lh $REALFILE | awk '{print $5}')
FSIZE=$(stat -c%s $REALFILE)
echo "/* $FILEINFO_SHORT" > $TEMPFILE
echo " * Size: $FILESIZE */" >> $TEMPFILE
$XXD -i $REALFILE >> $TEMPFILE
XXDRESNAME=$( cat $TEMPFILE | head -n3 | tail -n1 | awk '{print $3}' | sed 's:\[\]$::g')
XXDRESSIZE=$( cat $TEMPFILE | tail -n1 | awk '{print $5}' | sed 's:;::g' )
sed -i "s:$XXDRESNAME:$RESVAR:g" $TEMPFILE
#sed -i "s:$RESVAR\[\]:$RESVAR\[$XXDRESSIZE\]:g" $TEMPFILE
sed -i "s:unsigned char:PROGMEM uint8_t:g" $TEMPFILE
echo -e "\n" >> $TEMPFILE
cat $TEMPFILE >> $TEMPSOURCE
LOOKUPENTRY=" { \"$FILE\", $RESID },\n"
DATAENTRY=" $RESVAR,\n"
LOOKUPTABLE=$LOOKUPTABLE$LOOKUPENTRY
SIZETABLE="$SIZETABLE $FSIZE,\n"
MIMETABLE="$MIMETABLE \"$FILEMIME\",\n"
DATATABLE="$DATATABLE $RESVAR,\n"
let RESID=RESID+1
let TOTALSIZE=$TOTALSIZE+$XXDRESSIZE
done
SIZETABLE=$(echo $SIZETABLE | sed 's/.\{3\}$//')
MIMETABLE=$(echo $MIMETABLE | sed 's/.\{3\}$//')
sed -i "s|#!lookupfn|$LOOKUP_FUNCTION_NAME|g" $TEMPSOURCE
sed -i "s|#!LOOKUPTABLE|$LOOKUPTABLE|g" $TEMPSOURCE
sed -i "s|#!DATATABLE|$DATATABLE|g" $TEMPSOURCE
sed -i "s|#!mimetable|$MIMETABLE|g" $TEMPSOURCE
sed -i "s|#!sizetable|$SIZETABLE|g" $TEMPSOURCE
sed -i "s|#!gendate|$(date) on $(hostname)|g" $TEMPSOURCE
sed -i "s|#!sourcefilename|$SOURCENAME|g" $TEMPSOURCE
sed -i "s|#!sourcefilename|$SOURCENAME|g" $TEMPHEAD
sed -i "s|#!headfilename|$HEADNAME|g" $TEMPSOURCE
sed -i "s|#!lookupfn|$LOOKUP_FUNCTION_NAME|g" $TEMPSOURCE
sed -i "s|#!lookupfn|$LOOKUP_FUNCTION_NAME|g" $TEMPHEAD
sed -i "s|#!gendate|$(date) on $(hostname)|g" $TEMPHEAD
echo "PROGMEM prog_uchar *$DATA_TABLE_NAME[] = {" >> $TEMPSOURCE
echo -e $DATATABLE >> $TEMPSOURCE
echo "};" >> $TEMPSOURCE
mv $TEMPSOURCE $SOURCE_FILENAME
mv $TEMPHEAD $HEADER_FILENAME
rm -r $TEMPDIR
echo "Total using $(numfmt --to=iec --suffix=B $TOTALSIZE) ($TOTALSIZE bytes)" | xargs -0 -I{} echo -e "\e[01;32m{}\e[0m"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment