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