Subversion Repositories HelenOS

Rev

Rev 3397 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3265 post 1
#!/bin/sh
2
# Copyright (C) 2008 Tim Post - All Rights Reserved
3
# Redistribution and use in source and binary forms, with or without
4
# modification, are permitted provided that the following conditions are met:
5
#
6
# Redistributions of source code must retain the above copyright notice, this
7
# list of conditions and the following disclaimer.
8
#
9
# Redistributions in binary form must reproduce the above copyright notice,
10
# this list of conditions and the following disclaimer in the documentation
11
# and/or other materials provided with the distribution.
12
#
13
# Neither the name of the original program's authors nor the names of its
14
# contributors may be used to endorse or promote products derived from this
15
# software without specific prior written permission.
16
#
17
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
 
29
# Script to generate skeletal files for a new command
30
# Uses `getopt', not quite a bash-ism but might be
31
# lacking on some legacy systems.
32
 
33
# If your shell does not support eval, shift (x) or
34
# here-now documents, sorry :) 
35
 
36
usage()
37
{
38
	def="$DEFAULT_COMMAND"
39
	cat << EOF
40
\`$PROGNAME' generates skeletal command files to simplify adding commands
41
Usage: $PROGNAME [options] <location>
42
Options:
43
  -n, --name         Name of the command (default: ${def})
44
  -d, --desc         Short (20 30 chars) description of the command
45
                     (def: "The $def command")
46
  -e, --entry        Entry function of the command (def: cmd_${def})
47
  -h, --help-entry   Entry function for command help (def: help_cmd_${def})
48
  -a, --alias        Alias (nickname) for this command (def: none)
49
  -r, --restrict     Restriction level (interactive, non-interactive, both)
50
                     (def: module is both, builtin is interactive only)
51
  -t, --type         Type of command (module or builtin) (def: module)
52
  -H, --help         This help summary
53
  -V, --version      Print $PROGNAME version and exit normally
54
 
55
Notes:
56
  You must supply at least the name of the command.
57
 
58
  If you do not specify a location (i.e. modules/foo), the command will be
59
  created in modules/command_name or builtins/command_name depending on your
60
  selection.
61
 
62
  This script will only create skeletal files and inform you what headers
63
  need to be modified to incorporate the command. You will also have to
64
  manually update the main Makefile.
65
 
66
  This script is intended only to be a convenience for developers. Example use:
67
    $PROGNAME -n foo -d "Foo power" -a bar -r both -t module modules/foo
68
 
69
  The example would generate a modular command named 'foo', which is also
70
  reached by typing 'bar' and available in either interactive or noninteractive
71
  mode.
72
 
73
  Skeletal files do *not* depend on the autoconf generated "config.h" unless you
74
  include it. This may or may not be desirable depending on your use.
75
 
76
Report bugs to $PROGMAINT
77
 
78
EOF
79
}
80
 
81
# Convert a string to all uppercase
82
toupper()
83
{
84
	local str="$1"
85
 
86
	echo "${str}" | tr 'a-z' 'A-Z'
87
}
88
 
89
# Template stored `here-now' style, this generates all files needed
90
# for a new command according to arguments passed.
91
generate_code()
92
{
3373 post 93
	echo "Creating ${OUTDIR}/${CMDNAME}_def.h ..."
94
	cat << EOF > ${OUTDIR}/${CMDNAME}_def.h
3265 post 95
{
96
	"${CMDNAME}",
97
	"${CMDDESC}",
98
	&${CMDENTRY},
99
	&${HELPENTRY},
100
	${CMDRESTRICT}
101
},
102
 
103
EOF
3373 post 104
	[ -n "${CMDALIAS}" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}_def.h
3265 post 105
{
106
	"${CMDALIAS}",
107
	NULL,
108
	&${CMDENTRY},
109
	&${HELPENTRY},
110
	${CMDRESTRICT}
111
},
112
 
113
EOF
114
	local defname=$(toupper "${CMDNAME}")
115
	echo "Creating ${OUTDIR}/entry.h ..."
116
	cat << EOF > ${OUTDIR}/entry.h
117
#ifndef ${defname}_ENTRY_H
118
#define ${defname}_ENTRY_H
119
 
120
EOF
121
	[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/entry.h
122
/* Entry points for the ${CMDNAME} command */
3492 rimsky 123
extern int ${CMDENTRY}(char **);
124
extern void ${HELPENTRY}(unsigned int);
3265 post 125
 
126
#endif /* ${defname}_ENTRY_H */
127
 
128
EOF
129
	[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/entry.h
130
/* Pick up cliuser_t */
131
#include "scli.h"
132
 
133
/* Entry points for the ${CMDNAME} command */
134
extern int * ${CMDENTRY}(char **, cliuser_t *);
135
extern void * ${HELPENTRY}(unsigned int);
136
 
137
#endif /* ${defname}_ENTRY_H */
138
 
139
EOF
140
	echo "Creating ${OUTDIR}/${CMDNAME}.h ..."
141
	cat << EOF > ${OUTDIR}/${CMDNAME}.h
142
#ifndef ${defname}_H
143
#define ${defname}_H
144
 
145
/* Prototypes for the ${CMDNAME} command, excluding entry points */
146
 
147
 
148
#endif /* ${defname}_H */
149
 
150
EOF
151
	echo "Creating ${OUTDIR}/${CMDNAME}.c ..."
152
	cat << EOF > ${OUTDIR}/${CMDNAME}.c
153
/* Automatically generated by ${PROGNAME} on ${TIMESTAMP}
154
 * This is machine generated output. The author of ${PROGNAME} claims no
155
 * copyright over the contents of this file. Where legally permitted, the
156
 * contents herein are donated to the public domain.
157
 *
158
 * You should apply any license and copyright that you wish to this file,
159
 * replacing this header in its entirety. */
160
 
161
#include <stdio.h>
162
#include <stdlib.h>
3284 post 163
#include "config.h"
3301 post 164
#include "util.h"
3284 post 165
#include "errors.h"
3265 post 166
#include "entry.h"
167
#include "${CMDNAME}.h"
168
#include "cmds.h"
169
 
170
static char *cmdname = "${CMDNAME}";
171
 
172
/* Dispays help for ${CMDNAME} in various levels */
3492 rimsky 173
void ${HELPENTRY}(unsigned int level)
3265 post 174
{
175
	printf("This is the %s help for '%s'.\n",
176
		level ? EXT_HELP : SHORT_HELP, cmdname);
3492 rimsky 177
	return;
3265 post 178
}
179
 
180
EOF
181
	[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c
182
/* Main entry point for ${CMDNAME}, accepts an array of arguments */
3492 rimsky 183
int ${CMDENTRY}(char **argv)
3265 post 184
EOF
185
	[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c
186
/* Main entry point for ${CMDNAME}, accepts an array of arguments and a
187
 * pointer to the cliuser_t structure */
3492 rimsky 188
int ${CMDENTRY}(char **argv, cliuser_t *usr)
3265 post 189
EOF
190
	cat << EOF >> ${OUTDIR}/${CMDNAME}.c
191
{
192
	unsigned int argc;
193
	unsigned int i;
194
 
195
	/* Count the arguments */
196
	for (argc = 0; argv[argc] != NULL; argc ++);
197
 
198
	printf("%s %s\n", TEST_ANNOUNCE, cmdname);
199
	printf("%d arguments passed to %s", argc - 1, cmdname);
200
 
201
	if (argc < 2) {
202
		printf("\n");
3283 post 203
		return CMD_SUCCESS;
3265 post 204
	}
205
 
206
	printf(":\n");
207
	for (i = 1; i < argc; i++)
208
		printf("[%d] -> %s\n", i, argv[i]);
209
 
3283 post 210
	return CMD_SUCCESS;
3265 post 211
}
212
 
213
EOF
3276 post 214
	printf "Done.\n\nYou should now modify %ss/%ss.h and ../Makefile" \
3265 post 215
		"${CMDTYPE}" "${CMDTYPE}"
216
	printf " to include your new command.\n"
217
	[ -n "$CMDALIAS" ] &&  {
218
		printf "\nYou should also modify %ss/%s_aliases.h and " \
219
			"${CMDTYPE}" "${CMDTYPE}"
220
		printf "add %s as an alias for %s\n" \
221
			"${CMDALIAS}" "${CMDNAME}"
222
	}
3276 post 223
	printf "\nOnce completed, re-run make\n\n"
3265 post 224
}
225
 
226
# Main program
227
 
228
TIMESTAMP="$(date)"
229
PROGNAME=$(basename $0)
230
PROGVER="0.0.1"
231
PROGMAINT="Tim Post <echo@echoreply.us>"
232
DEFAULT_COMMAND="cmdname"
233
 
234
# We need at least one
235
[ $# = 0 ] && usage && exit 1;
236
 
237
TEMP=$(getopt -o n:d:e:h:a:r:t:HV \
238
--long name:,desc:,entry:,help-entry:,alias:,restrict:,type:,help,version \
239
-- "$@") || {
240
	echo "Try $PROGNAME --help for help"
241
}
242
 
243
eval set -- "$TEMP"
244
 
245
while true; do
246
	case "$1" in
247
	-n | --name)
248
		CMDNAME="$2"
249
		shift 2
250
		continue
251
	;;
252
	-d | --desc)
253
		CMDDESC="$2"
254
		shift 2
255
		continue
256
	;;
257
	-e | --entry)
258
		CMDENTRY="$2"
259
		shift 2
260
		continue
261
	;;
262
	-h | --help-entry)
263
		HELPENTRY="$2"
264
		shift 2
265
		continue
266
	;;
267
	-a | --alias)
268
		CMDALIAS="$2"
269
		shift 2
270
		continue
271
	;;
272
	-r | --restrict)
273
		CMDRESTRICT="$2"
274
		shift 2
275
		continue
276
	;;
277
	-t | --type)
278
		CMDTYPE="$2"
279
		shift 2
280
		continue
281
	;;
282
	-H | --help)
283
		usage
284
		exit 0
285
	;;
286
	-V | --version)
287
		echo "$PROGVER"
288
		exit 0
289
	;;
290
	--)
291
		break
292
	;;
293
	esac
294
done
295
 
296
# Pick up a location if one was specified
297
eval set -- "$*"
298
[ -n "$2" ] && OUTDIR="$2"
299
 
300
# Fill in defaults for whatever was not specified
301
[ -n "$CMDNAME" ] || CMDNAME="$DEFAULT_COMMAND"
302
[ -n "$CMDDESC" ] || CMDDESC="The $CMDNAME command"
303
[ -n "$CMDENTRY" ] || CMDENTRY="cmd_${CMDNAME}"
304
[ -n "$HELPENTRY" ] || HELPENTRY="help_cmd_${CMDNAME}"
305
[ -n "$CMDTYPE" ] || CMDTYPE="module"
306
[ -n "$OUTDIR" ] || OUTDIR="${CMDTYPE}s/${CMDNAME}"
307
 
308
# Builtins typically only need to be available in interactive mode,
309
# set the default accordingly.
310
[ -n "$CMDRESTRICT" ] || {
311
	[ "$CMDTYPE" = "module" ] && CMDRESTRICT="both"
312
	[ "$CMDTYPE" = "builtin" ] && CMDRESTRICT="interactive"
313
}
314
 
315
# Set the restriction level as the structure expects to see it
316
case "$CMDRESTRICT" in
317
 
318
		CMDRESTRICT="0"
319
	;;
320
	1 | non-interactive)
321
		CMDRESTRICT="1"
322
	;;
323
	-1 | interactive)
324
		CMDRESTRICT="-1"
325
	;;
326
	*)
327
		usage
328
		exit 1
329
	;;
330
esac
331
 
332
# Do a little sanity
333
[ -d $OUTDIR ] && {
334
	echo "$OUTDIR already exists, remove it to proceed."
335
	exit 1
336
}
337
 
338
mkdir -p ${OUTDIR} >/dev/null 2>&1 || {
339
	echo "Could not create ${OUTDIR}, aborting!"
340
	exit 1
341
}
342
 
343
# Generate the files and inform on how to include them based on options
344
generate_code
345
 
346
exit 0
347