1 /**
2 * @file useropt.c
3 *
4 * <JA>
5 * @brief �桼��������ץ����
6 * </JA>
7 *
8 * <EN>
9 * @brief User-defined option handling
10 * </EN>
11 *
12 * @author Akinobu Lee
13 * @date Sun Sep 02 19:44:37 2007
14 *
15 * $Revision: 1.2 $
16 *
17 */
18 /*
19 * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University
20 * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
21 * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology
22 * All rights reserved
23 */
24
25 #include <julius/juliuslib.h>
26
27 /**
28 * List of user option data
29 *
30 */
31 static USEROPT *useropt_root = NULL;
32
33 /**
34 * <EN>
35 * Generate a new option data.
36 * </EN>
37 * <JA>
38 * �����ʥ桼�����ץ����ǡ���������.
39 * </JA>
40 *
41 * @return a new user option data.
42 *
43 */
44 static USEROPT *
useropt_new()45 useropt_new()
46 {
47 USEROPT *new;
48
49 new = (USEROPT *)mymalloc(sizeof(USEROPT));
50 new->optstr = NULL;
51 new->desc = NULL;
52 new->argnum = 0;
53 new->reqargnum = 0;
54 new->next = NULL;
55
56 return new;
57 }
58
59 /**
60 * <EN>
61 * �桼�����ץ����ǡ��������.
62 * </EN>
63 * <JA>
64 * Release a user option data.
65 * </JA>
66 *
67 * @param x [in] a user option data to release
68 *
69 */
70 static void
useropt_free(USEROPT * x)71 useropt_free(USEROPT *x)
72 {
73 if (x->optstr) free(x->optstr);
74 if (x->desc) free(x->desc);
75 free(x);
76 }
77
78 /**
79 * <EN>
80 * Release all user option data.
81 * </EN>
82 * <JA>
83 * ���ƤΥ桼�����ץ����ǡ������������.
84 * </JA>
85 *
86 * @callgraph
87 * @callergraph
88 */
89 void
useropt_free_all()90 useropt_free_all()
91 {
92 USEROPT *x, *tmp;
93
94 x = useropt_root;
95 while(x) {
96 tmp = x->next;
97 useropt_free(x);
98 x = tmp;
99 }
100 useropt_root = NULL;
101 }
102
103 /**
104 * <EN>
105 * Add a user-defined option to Julius.
106 * When reqargnum is lower than argnum, the first (reqargnum) arguments
107 * are required and the rest (argnum - reqargnum) options are optional.
108 * </EN>
109 * <JA>
110 * Julius �˥桼��������ץ������ɲä���.
111 * argnum �ˤϰ����κ������reqargnum �Ϥ��Τ���ɬ�ܤǤ�������ο���
112 * ���ꤹ��. argnum > reqargnum �ξ�硤��Ƭ���� reqargnum �Ĥ�ɬ�ܤǡ�
113 * ����ʹߤ� optional �Ȥ��ư�����.
114 * </JA>
115 *
116 * @param fmt [in] option string (should begin with '-')
117 * @param argnum [in] total number of argument for this option (including optional)
118 * @param reqargnum [in] number of required argument
119 * @param desc [in] description string for help
120 * @param func [in] option handling function
121 *
122 * @return TRUE on success, FALSE on failure
123 *
124 * @callgraph
125 * @callergraph
126 * @ingroup engine
127 */
128 boolean
j_add_option(char * fmt,int argnum,int reqargnum,char * desc,boolean (* func)(Jconf * jconf,char * arg[],int argnum))129 j_add_option(char *fmt, int argnum, int reqargnum, char *desc, boolean (*func)(Jconf *jconf, char *arg[], int argnum))
130 {
131 USEROPT *new;
132
133 if (fmt[0] != '-') {
134 jlog("ERROR: j_add_option: option string must start with \'-\': %s\n", fmt);
135 return FALSE;
136 }
137 if (argnum < reqargnum) { /* error */
138 jlog("ERROR: j_add_option: number of required argument (%d) larger than total (%d)\n", reqargnum, argnum);
139 return FALSE;
140 }
141
142 /* allocate new */
143 new = useropt_new();
144 /* set option string */
145 new->optstr = strcpy((char *)mymalloc(strlen(fmt)+1), fmt);
146 /* set number of arguments */
147 new->argnum = argnum;
148 /* set number of required arguments.
149 If less than argnum, the latter options should be optional */
150 new->reqargnum = reqargnum;
151 /* set description string */
152 new->desc = strcpy((char*)mymalloc(strlen(desc)+1),desc);
153
154 /* set user-given function to process this option */
155 new->func = func;
156
157 /* add to list */
158 new->next = useropt_root;
159 useropt_root = new;
160
161 return TRUE;
162 }
163
164
165 /**
166 * <EN>
167 * Inspect for the user-specified options at option parsing
168 * </EN>
169 * <JA>
170 * ���ץ��������ˤ����ƥ桼��������ץ���������Ԥ�.
171 *
172 * </JA>
173 *
174 * @param jconf [in] global configuration variables
175 * @param argv [in] argument array
176 * @param argc [in] number of arguments in argv
177 * @param n [i/o] current position in argv
178 *
179 * @return 1 when the current argument was processed successfully
180 * by one of the user options, 0 when no user option matched for the
181 * current argument, or -1 on error.
182 *
183 * @callgraph
184 * @callergraph
185 */
186 int
useropt_exec(Jconf * jconf,char * argv[],int argc,int * n)187 useropt_exec(Jconf *jconf, char *argv[], int argc, int *n)
188 {
189 USEROPT *x;
190 int narg, i;
191
192 for(x=useropt_root;x;x=x->next) {
193 if (strmatch(argv[*n], x->optstr)) {
194 i = *n + 1;
195 while(i < argc && (argv[i][0] != '-' || (argv[i][1] >= '0' && argv[i][1] <= '9'))) i++;
196
197 narg = i - *n - 1;
198 if (narg > x->argnum || narg < x->reqargnum) {
199 if (x->reqargnum != x->argnum) {
200 jlog("ERROR: useropt_exec: \"%s\" should have at least %d argument(s)\n", x->optstr, x->reqargnum);
201 } else {
202 jlog("ERROR: useropt_exec: \"%s\" should have %d argument(s)\n", x->optstr, x->argnum);
203 }
204 return -1; /* error */
205 }
206
207 if ((*(x->func))(jconf, &(argv[(*n)+1]), narg) == FALSE) {
208 jlog("ERROR: useropt_exec: \"%s\" function returns FALSE\n", x->optstr);
209 return -1; /* error */
210 }
211 *n += narg;
212 return 1; /* processed */
213 }
214 }
215
216 return 0; /* nothing processed */
217 }
218
219 /**
220 * <EN>
221 * Output description of all the registered user options.
222 * </EN>
223 * <JA>
224 * ��Ͽ����Ƥ������ƤΥ桼��������ץ�������������Ϥ���.
225 * </JA>
226 *
227 * @param fp [in] file pointer to output for
228 *
229 * @callgraph
230 * @callergraph
231 */
232 void
useropt_show_desc(FILE * fp)233 useropt_show_desc(FILE *fp)
234 {
235 USEROPT *x;
236 int i;
237
238 if (! useropt_root) return;
239 fprintf(fp, "\n Additional options for application:\n");
240 for(x=useropt_root;x;x=x->next) {
241 fprintf(fp, " [%s", x->optstr);
242 for(i=0;i<x->reqargnum;i++) fprintf(fp, " arg");
243 for(i=x->reqargnum;i<x->argnum;i++) fprintf(fp, " (arg)");
244 fprintf(fp, "]\t%s\n", x->desc);
245 }
246 }
247
248 /* end of file */
249