/[ascend]/trunk/tcltk98/generic/interface/HelpProc.c
ViewVC logotype

Contents of /trunk/tcltk98/generic/interface/HelpProc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 17 - (show annotations) (download) (as text)
Tue Dec 7 17:37:58 2004 UTC (15 years, 2 months ago) by aw0a
File MIME type: text/x-csrc
File size: 13232 byte(s)
moved interface directory one level deeper in tree
1 /*
2 * HelpProc.c
3 * ASCEND IV interface help functions.
4 * by Benjamin Andrew Allan
5 * Created April 29, 1997
6 * Version: $Revision: 1.12 $
7 * Version control file: $RCSfile: HelpProc.c,v $
8 * Date last modified: $Date: 2003/08/23 18:43:06 $
9 * Last modified by: $Author: ballan $
10 *
11 * This file is part of the ASCEND Tcl/Tk interface
12 *
13 * Copyright 1997, Carnegie Mellon University
14 *
15 * The ASCEND Tcl/Tk interface is free software; you can redistribute
16 * it and/or modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of the
18 * License, or (at your option) any later version.
19 *
20 * The ASCEND Tcl/Tk interface is distributed in hope that it will be
21 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with the program; if not, write to the Free Software Foundation,
27 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
28 * COPYING. COPYING is found in ../compiler.
29 */
30
31
32 #include <stdarg.h>
33 #include "tcl.h"
34 #include "utilities/ascConfig.h"
35 #include "utilities/ascMalloc.h"
36 #include "general/list.h"
37 #include "general/pool.h"
38 #include "interface/HelpProc.h"
39
40 #ifndef lint
41 static CONST char HelpProcRCS[] = "$Id: HelpProc.c,v 1.12 2003/08/23 18:43:06 ballan Exp $";
42 #endif
43
44 struct HelpData {
45 struct HelpData *next; /* if we decide we need a hash table use this */
46 CONST char *name; /* just as defined in the Asc_HelpDefine header */
47 CONST char *group; /* " */
48 CONST char *usage; /* " */
49 CONST char *shorth; /* " */
50 CONST char *longh; /* " */
51 };
52
53 struct HelpGroup {
54 CONST char *gname; /* the name of the group */
55 CONST char *explanation; /* an explanation for the group */
56 struct gl_list_t *data; /* the list of HelpData in this group */
57 };
58
59 static struct gl_list_t *g_helplist = NULL;
60 /* this list is responsible for all allocated HelpData. */
61
62 static struct gl_list_t *g_helpgroups = NULL;
63 /* this list is responsible for all allocated HelpGroup. */
64
65
66 char *HelpBuildString(char *first,...)
67 {
68 char *argv[MAXHELPARGS];
69 int argl[MAXHELPARGS];
70 char *str;
71 char *result;
72 int c,argc,len;
73 char *tmp;
74 va_list ap;
75
76 va_start(ap,first);
77 argv[0] = first;
78 argl[0] = strlen(first);
79 argc = 1;
80 len = argl[0];
81 while ( (str = va_arg(ap,char *)) != NULL && argc < MAXHELPARGS) {
82 argv[argc] = str;
83 argl[argc] = strlen(str);
84 if (argl[argc]==0) {
85 FPRINTF(ASCERR,"Empty string passed to HelpBuildString.\n%s%s%s",
86 "\nPrevious string was:\n",argv[argc-1],"\nExpect core.\n");
87 va_end(ap);
88 return NULL;
89 } else {
90 if (argl[argc]>=509) {
91 FPRINTF(ASCERR,"String %d long passed to HelpBuildString.\n>>%s\n%s",
92 argl[argc], str, "<<This is non-portable\n");
93 }
94 }
95 len += argl[argc];
96 argc++;
97 }
98 va_end(ap);
99 len++;
100 result = (char *)malloc(len);
101 if (result == NULL) {
102 return NULL;
103 }
104 tmp = result;
105 for (c = 0; c <argc; c++) {
106 if (argv[c]!=NULL) {
107 strcpy(tmp,argv[c]);
108 tmp += argl[c];
109 }
110 }
111 tmp[0] = '\0';
112 return result;
113 }
114
115 int Asc_HelpCheck(ClientData cdata, Tcl_Interp *interp,
116 int argc, CONST84 char *argv[])
117 {
118 (void)cdata; /* shut up gcc */
119 if (argc >=2 && argv[1][0]=='-') {
120 if (argv[1][1]=='h') {
121 Tcl_AppendResult(interp,argv[0],":\n",(char *)NULL);
122 (void)Asc_HelpGetShort(interp,argv[0]);
123 Tcl_AppendResult(interp,"\n",(char *)NULL);
124 (void)Asc_HelpGetUsage(interp,argv[0]);
125 return TCL_BREAK;
126 }
127 if (argv[1][1]=='H') {
128 Tcl_AppendResult(interp,argv[0],":\n",(char *)NULL);
129 (void)Asc_HelpGetLong(interp,argv[0]);
130 return TCL_BREAK;
131 }
132 }
133 return TCL_OK;
134 }
135
136
137 int Asc_HelpInit(void)
138 {
139 assert(g_helplist==NULL);
140 assert(g_helpgroups==NULL);
141 g_helplist = gl_create(200L);
142 g_helpgroups = gl_create(20L);
143 return TCL_OK;
144 }
145
146 static
147 void DestroyHelpGroup(void *g)
148 {
149 gl_destroy(((struct HelpGroup *)g)->data);
150 }
151
152 static
153 void DestroyHelpData(void *g)
154 {
155 if (((struct HelpData *)g)->longh != NULL) {
156 ascfree((void *)(((struct HelpData *)g)->longh));
157 }
158 }
159
160 int Asc_HelpDestroy(void)
161 {
162 gl_iterate(g_helpgroups,DestroyHelpGroup);
163 gl_free_and_destroy(g_helpgroups);
164 gl_iterate(g_helplist,DestroyHelpData);
165 gl_free_and_destroy(g_helplist);
166 g_helplist = g_helpgroups = NULL;
167 return TCL_OK;
168 }
169
170 /* returns the strcmp of the names of two helpdata */
171 static
172 int CompareHelpData(struct HelpData *h1,struct HelpData *h2)
173 {
174 if (h1==h2) {
175 return 0;
176 }
177 if (h1==NULL || h1->name == NULL) {
178 return 1;
179 }
180 if (h2==NULL || h2->name == NULL) {
181 return -1;
182 }
183 return strcmp(h1->name,h2->name);
184 }
185
186 /* returns the strcmp of the names of two helpgroup */
187 static
188 int CompareHelpGroup(struct HelpGroup *h1,struct HelpGroup *h2)
189 {
190 if (h1==h2) {
191 return 0;
192 }
193 if (h1==NULL || h1->gname == NULL) {
194 return 1;
195 }
196 if (h2==NULL || h2->gname == NULL) {
197 return -1;
198 }
199 return strcmp(h1->gname,h2->gname);
200 }
201
202 /*
203 * Return the data corresponding to the command name given, or NULL if no
204 * such command is known.
205 */
206 static
207 struct HelpData *FindHelpData(CONST char *name)
208 {
209 struct HelpData srch;
210 unsigned long pos;
211
212 srch.name = name;
213 pos = gl_search(g_helplist,&srch,(CmpFunc)CompareHelpData);
214 if (pos==0) {
215 return NULL;
216 } else {
217 return((struct HelpData *)gl_fetch(g_helplist,pos));
218 }
219 }
220
221 /*
222 * Return the data corresponding to the command name given, or NULL if no
223 * such command is known.
224 */
225 static
226 struct HelpGroup *FindHelpGroup(CONST char *group)
227 {
228 struct HelpGroup srch;
229 unsigned long pos;
230
231 srch.gname = group;
232 pos = gl_search(g_helpgroups,&srch,(CmpFunc)CompareHelpGroup);
233 if (pos==0) {
234 return NULL;
235 } else {
236 return((struct HelpGroup *)gl_fetch(g_helpgroups,pos));
237 }
238 }
239
240 /* creates a group with the explanation given and
241 * inserts it in the global list.
242 * Returns NULL if error occurs.
243 */
244 static
245 struct HelpGroup *CreateHelpGroup(CONST char *group, CONST char *explanation)
246 {
247 struct HelpGroup *g;
248 g = (struct HelpGroup *)ascmalloc(sizeof(struct HelpGroup));
249 if (g == NULL) {
250 return NULL;
251 }
252 g->gname = group;
253 g->explanation = explanation;
254 g->data = gl_create(30L);
255 if (g->data == NULL) {
256 ascfree(g);
257 return NULL;
258 }
259 gl_insert_sorted(g_helpgroups,g,(CmpFunc)CompareHelpGroup);
260 return g;
261 }
262
263 /*
264 * This sets or resets the group field of the help structure
265 * and the group structures that point to the command.
266 * Returns tcl style int values.
267 */
268 static
269 int AssignHelpGroup(struct HelpData *d, CONST char *group)
270 {
271 struct HelpGroup *g;
272 unsigned long pos;
273
274 if (d->group != NULL) {
275 /* reassigning, which means we may need to get it out of the
276 * prior group.
277 */
278 if (strcmp(group,d->group) != 0) {
279 g = FindHelpGroup(d->group);
280 assert(g!=NULL);
281 pos = gl_search(g->data,d,(CmpFunc)CompareHelpData);
282 assert(pos!=0);
283 gl_delete(g->data,pos,0);
284 }
285 }
286 d->group = group;
287 g = FindHelpGroup(group);
288 if (g == NULL) {
289 g = CreateHelpGroup(group,"Explanation: none given yet.");
290 if (g==NULL) {
291 return TCL_ERROR;
292 }
293 }
294 gl_insert_sorted(g->data,d,(CmpFunc)CompareHelpData);
295 return TCL_OK;
296 }
297
298 /* Inserts help information into the list, or if the same
299 * command already exists, replaces that information with
300 * the new information.
301 * Returns tcl return codes.
302 * Currently only possible error is insufficient memory.
303 */
304 static
305 int AddHelpData(CONST char *name,
306 CONST char *group,
307 CONST char *usage,
308 CONST char *shorth,
309 CONST char *longh)
310 {
311 struct HelpData *d;
312
313 d = FindHelpData(name);
314 if (d == NULL) {
315 d = (struct HelpData *)ascmalloc(sizeof(struct HelpData));
316 if (d==NULL) {
317 return TCL_ERROR;
318 }
319 d->group = NULL;
320 }
321 d->next = NULL;
322 d->name = name;
323 d->usage = usage;
324 d->shorth = shorth;
325 d->longh = longh;
326 AssignHelpGroup(d,group);
327 gl_insert_sorted(g_helplist,d,(CmpFunc)CompareHelpData);
328 return TCL_OK;
329 }
330
331 int Asc_HelpDefineGroup(CONST char *group, CONST char *explanation)
332 {
333 struct HelpGroup *g;
334 if (explanation==NULL ||
335 strlen(explanation)<11 ||
336 strncmp(explanation,"Explanation",11)!=0) {
337 return TCL_ERROR;
338 }
339 g = FindHelpGroup(group);
340 if (g == NULL) {
341 g = CreateHelpGroup(group,explanation);
342 if (g==NULL) {
343 return TCL_ERROR;
344 }
345 return TCL_OK;
346 } else {
347 g->explanation = explanation;
348 }
349 return TCL_OK;
350 }
351
352
353 int Asc_HelpDefine(CONST char *name,
354 CONST char *group,
355 CONST char *usage,
356 CONST char *shorth,
357 HLFunc bigstring)
358 {
359 assert(g_helplist!=NULL);
360 assert(g_helpgroups!=NULL);
361 if (bigstring != NULL) {
362 return AddHelpData(name,group,usage,shorth,bigstring());
363 } else {
364 return AddHelpData(name,group,usage,shorth,NULL);
365 }
366 }
367
368 CONST char *Asc_HelpGetShort(Tcl_Interp *interp, CONST84 char *name)
369 {
370 struct HelpData *d;
371 d = FindHelpData(name);
372 if (d==NULL) {
373 return NULL;
374 } else {
375 Tcl_AppendResult(interp,d->shorth,(char *)NULL);
376 return d->shorth;
377 }
378 }
379
380 CONST char *Asc_HelpGetLong(Tcl_Interp *interp, CONST84 char *name)
381 {
382 struct HelpData *d;
383 d = FindHelpData(name);
384 if (d==NULL) {
385 return NULL;
386 } else {
387 Tcl_AppendResult(interp,d->longh,(char *)NULL);
388 return d->longh;
389 }
390 }
391
392 CONST char *Asc_HelpGetUsage(Tcl_Interp *interp, CONST84 char *name)
393 {
394 struct HelpData *d;
395 d = FindHelpData(name);
396 if (d==NULL) {
397 return NULL;
398 } else {
399 Tcl_AppendResult(interp,d->usage,(char *)NULL);
400 return d->usage;
401 }
402 }
403
404 static
405 void AppendHelpElements(Tcl_Interp *interp,struct gl_list_t *dlist)
406 {
407 unsigned long c,len;
408 struct HelpData *d;
409
410 if (interp==NULL || dlist==NULL){
411 return;
412 }
413 len = gl_length(dlist);
414 for (c=1;c <=len; c++) {
415 d = (struct HelpData *)gl_fetch(dlist,c);
416 Tcl_AppendElement(interp,(char *)d->name);
417 }
418 return;
419 }
420
421 static
422 void AppendGroupElements(Tcl_Interp *interp, struct HelpGroup *g)
423 {
424 assert(g!=NULL);
425 AppendHelpElements(interp,g->data);
426 }
427
428 int Asc_HelpGetGroup(Tcl_Interp *interp, CONST84 char *gname)
429 {
430 struct HelpGroup *g;
431
432 g = FindHelpGroup(gname);
433 if (g==NULL) {
434 Tcl_SetResult(interp, "{Help group undefined}", TCL_STATIC);
435 return TCL_ERROR;
436 }
437 if (g->explanation !=NULL) {
438 Tcl_AppendElement(interp,(char *)g->explanation);
439 }
440 AppendGroupElements(interp,g);
441 return TCL_OK;
442 }
443
444
445 int Asc_HelpCommandGroups(Tcl_Interp *interp)
446 {
447 unsigned long c,len;
448 struct HelpGroup *g;
449
450 if (interp==NULL || g_helpgroups==NULL){
451 return TCL_ERROR;
452 }
453 len = gl_length(g_helpgroups);
454 for (c=1;c <=len; c++) {
455 g = (struct HelpGroup *)gl_fetch(g_helpgroups,c);
456 Tcl_AppendElement(interp,(char *)g->gname);
457 }
458 return TCL_OK;
459 }
460
461 int Asc_HelpCommandList(Tcl_Interp *interp)
462 {
463 if (interp==NULL || g_helplist==NULL){
464 return TCL_ERROR;
465 }
466 AppendHelpElements(interp,g_helplist);
467 return TCL_OK;
468 }
469
470 int Asc_HelpCommandsByGroups(Tcl_Interp *interp)
471 {
472 unsigned long c,len;
473 struct HelpGroup *g;
474
475 if (g_helpgroups==NULL) {
476 return TCL_ERROR;
477 }
478 len = gl_length(g_helpgroups);
479 for (c=1;c <=len; c++) {
480 g = (struct HelpGroup *)gl_fetch(g_helpgroups,c);
481 Tcl_AppendResult(interp," {GROUP ",g->gname,":} ",(char *)NULL);
482 AppendGroupElements(interp,g);
483 }
484 return TCL_OK;
485 }
486
487 STDHLF(Asc_HelpCmd,(Asc_HelpCmdHL1,Asc_HelpCmdHL2,Asc_HelpCmdHL3,
488 Asc_HelpCmdHL4,HLFSTOP));
489
490 #define ADDHELPSTR(s) Tcl_AppendResult(interp,s,(char *)NULL)
491 /* appends s to the tcl result */
492
493 int Asc_HelpCmd(ClientData cdata, Tcl_Interp *interp, int argc, CONST84 char *argv[])
494 {
495 CONST char *um, *sm, *lm;
496 (void)cdata; /* stop gcc whine about unused parameter */
497
498 ASCUSE;
499
500 if (argc==1) {
501 Asc_HelpGetLong(interp,argv[0]);
502 return TCL_OK;
503 }
504 /* isn't -H* or -h* */
505 if (argc==2) {
506 if (Asc_HelpGetGroup(interp,argv[1]) == TCL_OK) {
507 return TCL_OK;
508 }
509 /* isn't a group */
510 Tcl_ResetResult(interp);
511 ADDHELPSTR("Usage: ");
512 um = Asc_HelpGetUsage(interp,argv[1]);
513 ADDHELPSTR("\nSummary: ");
514 sm = Asc_HelpGetShort(interp,argv[1]);
515 ADDHELPSTR("\nDetails:\n");
516 lm = Asc_HelpGetLong(interp,argv[1]);
517 if (um == NULL && sm == NULL && lm == NULL) {
518 Tcl_ResetResult(interp);
519 /* isn't a regular command, could be a help subcommand. */
520 if (strcmp(argv[1],"all") == 0) {
521 Asc_HelpCommandList(interp);
522 return TCL_OK;
523 }
524 if (strcmp(argv[1],"commands") == 0) {
525 Asc_HelpCommandsByGroups(interp);
526 return TCL_OK;
527 }
528 if (strcmp(argv[1],"groups") == 0) {
529 Asc_HelpCommandGroups(interp);
530 return TCL_OK;
531 }
532 ADDHELPSTR("Unknown or undocumented command: ");
533 ADDHELPSTR(argv[1]);
534 return TCL_ERROR;
535 } else {
536 return TCL_OK;
537 }
538 }
539 /* may want more here later. */
540 Tcl_SetResult(interp, "Too many arguments to help. Try help -h", TCL_STATIC);
541 return TCL_ERROR;
542 }
543

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22