1 | /*****
2 | ** ** Module Header ******************************************************* **
3 | ** **
4 | ** Modules Revision 3.0 **
5 | ** Providing a flexible user environment **
6 | ** **
7 | ** File: cmdVersion.c **
8 | ** First Edition: 1995/12/28 **
9 | ** **
10 | ** Authors: Jens Hamisch, jens@Strawberry.COM **
11 | ** **
12 | ** Description: The Tcl module-version routine which provides the **
13 | ** definition of symbolic version names and the module- **
14 | ** alias command providing the definition of module and **
15 | ** version aliases **
16 | ** **
17 | ** Exports: cmdModuleVersion **
18 | ** cmdModuleAlias **
19 | ** CleanupVersion **
20 | ** AliasLookup **
21 | ** ExpandVersions **
22 | ** **
23 | ** Notes: This module defines the callback functions for the defi- **
24 | ** nition of symbolic module names and module aliases. The **
25 | ** syntax of the according commands is defined as: **
26 | ** **
27 | ** Module-Versions: **
28 | ** module-version <module>/<version> <name> [ <name> ... ] **
29 | ** module-version /<version> <name> [ <name> ... ] **
30 | ** module-version <module> <name> [ <name> ... ] **
31 | ** module-version <alias> <name> [ <name> ... ] **
32 | ** **
33 | ** Module-Alias: **
34 | ** module-alias <alias> <module>/<version> **
35 | ** module-alias <alias> /<version> **
36 | ** module-alias <alias> <module> **
37 | ** module-alias <alias> <alias> **
38 | ** **
39 | ** **
40 | ** ************************************************************************ **
41 | ****/
42 |
43 | /** ** Copyright *********************************************************** **
44 | ** **
45 | ** Copyright 1991-1994 by John L. Furlan. **
46 | ** see LICENSE.GPL, which must be provided, for details **
47 | ** **
48 | ** ************************************************************************ **/
49 |
50 | static char Id[] = "@(#)$Id: cmdVersion.c.src.html,v 1.6 2006/01/18 05:35:11 rkowen Exp $";
51 | static void *UseId[] = { &UseId, Id };
52 |
53 | /** ************************************************************************ **/
54 | /** HEADERS **/
55 | /** ************************************************************************ **/
56 |
57 | #include "modules_def.h"
58 |
59 | /** ************************************************************************ **/
60 | /** LOCAL DATATYPES **/
61 | /** ************************************************************************ **/
62 |
63 | /** ************************************************************************ **/
64 | /** **/
65 | /** The whole thing is handled in memory. The structure is build of module **/
66 | /** and name records. There are 3 types of name records: version, name **/
67 | /** and alias. **/
68 | /** **/
69 | /** | | **/
70 | /** +---+---+<-------------------------------+ +---+---+ **/
71 | /** | module| ------------------------+ | | alias | **/
72 | /** +---+---+ --------+ | | +-------+ **/
73 | /** | ^ +----+----+ | | | **/
74 | /** | +--- | version | +--+--+ | +---+---+ **/
75 | /** | | +----+----+ | name|---+ <-----| alias | **/
76 | /** | | | +--+--+ | +---+---+ **/
77 | /** | | +----+----+ | | | **/
78 | /** | +--- | version |------>+--+--+ | +---+---+ **/
79 | /** | | +----+----+<-+--- | name|---+ | alias | **/
80 | /** | | | | +- +--+--+ | +---+---+ **/
81 | /** | | +----+----+ | | | | | **/
82 | /** | +--- | version | | | +--+--+ | +---+---+ **/
83 | /** | | +----+----+ | | | name|---+ <-----| alias | **/
84 | /** | | | | | +--+--+ | +---+---+ **/
85 | /** | | | | | | **/
86 | /** | | +->+--+--+ | +---+---+ **/
87 | /** +---+---+ +--- | name|---+ | alias | **/
88 | /** | module| +--+--+ | +---+---+ **/
89 | /** +---+---+ | | | **/
90 | /** | **/
91 | /** alphabetic ordered alphabtic ordered **/
92 | /** list of names depending list of aliases **/
93 | /** to a single module file **/
94 | /** **/
95 | /** Each module name points to a list of symbolic names and versions. **/
96 | /** The versions themselfes can be symbolic names and therefore are of the **/
97 | /** same record type as the names. **/
98 | /** The name and the version list is alphabetically sorted (even the **/
99 | /** module list is). A version record points to a related name record **/
100 | /** containing a symbolic name for the version. Starting at this record, **/
101 | /** the name records built a queue of symbolic names for the version. **/
102 | /** Both, the version and the name record do have a backward pointer to **/
103 | /** the module record. **/
104 | /** **/
105 | /** The alias list builds a alphabetic ordered list of defined aliases. **/
106 | /** Each alias record points to the related name record. **/
107 | /** **/
108 | /** ************************************************************************ **/
109 |
110 | typedef struct _mod_module {
111 | struct _mod_module *next; /** alphabetic queue **/
112 | struct _mod_name *version; /** version queue **/
113 | struct _mod_name *name; /** name queue **/
114 | char *module; /** the name itsself **/
115 | } ModModule;
116 |
117 | typedef struct _mod_name {
118 | struct _mod_name *next; /** alphabetic queue **/
119 | struct _mod_name *ptr; /** logical next **/
120 | struct _mod_name *version; /** backwards version pointer **/
121 | struct _mod_module *module; /** related module **/
122 | char *name; /** the name itsself **/
123 | } ModName;
124 |
125 | /** ************************************************************************ **/
126 | /** CONSTANTS **/
127 | /** ************************************************************************ **/
128 |
129 | #define HISTTAB 100
130 |
131 | /** ************************************************************************ **/
132 | /** MACROS **/
133 | /** ************************************************************************ **/
134 |
135 | /** not applicable **/
136 |
137 | /** ************************************************************************ **/
138 | /** LOCAL DATA **/
139 | /** ************************************************************************ **/
140 |
141 | static char module_name[] = "cmdVersion.c"; /** File name of this module **/
142 | #if WITH_DEBUGGING_CALLBACK
143 | static char _proc_cmdModuleVersion[] = "cmdModuleVersion";
144 | static char _proc_cmdModuleAlias[] = "cmdModuleAlias";
145 | #endif
146 | #if WITH_DEBUGGING_UTIL_2
147 | static char _proc_CleanupVersion[] = "CleanupVersion";
148 | #endif
149 | #if WITH_DEBUGGING_UTIL_1
150 | static char _proc_AddModule[] = "AddModule";
151 | static char _proc_FindModule[] = "FindModule";
152 | static char _proc_AddName[] = "AddName";
153 | static char _proc_FindName[] = "FindName";
154 | #endif
155 |
156 | /**
157 | ** The module and aliases list
158 | **/
159 |
160 | static ModModule *modlist = (ModModule *) NULL;
161 | static ModName *aliaslist = (ModName *) NULL;
162 |
163 | /** ************************************************************************ **/
164 | /** PROTOTYPES **/
165 | /** ************************************************************************ **/
166 |
167 | static void CleanupVersionSub( ModModule *ptr);
168 |
169 | static void CleanupName( ModName *ptr);
170 |
171 | static ModModule *AddModule( char *name);
172 |
173 | static ModModule *FindModule( char *name,
174 | ModModule **prev);
175 |
176 | static ModName *AddName( char *name,
177 | ModName **start,
178 | ModModule *module);
179 |
180 | static ModName *FindName( char *name,
181 | ModName *start,
182 | ModName **prev);
183 |
184 | static char *CheckModuleVersion( char *name);
185 |
186 | static char *scan_versions( char *buffer,
187 | char *base,
188 | ModName *ptr,
189 | ModModule *modptr);
190 |
191 | /*++++
192 | ** ** Function-Header ***************************************************** **
193 | ** **
194 | ** Function: cmdModuleVersion **
195 | ** **
196 | ** Description: Callback function for 'version' **
197 | ** **
198 | ** First Edition: 1995/12/28 **
199 | ** **
200 | ** Parameters: ClientData client_data **
201 | ** Tcl_Interp *interp According Tcl interp.**
202 | ** int argc Number of arguments **
203 | ** char *argv[] Argument array **
204 | ** **
205 | ** Result: int TCL_OK Successfull completion **
206 | ** TCL_ERROR Any error **
207 | ** **
208 | ** Attached Globals: modlist List containing all version names **
209 | ** g_flags These are set up accordingly before **
210 | ** this function is called in order to **
211 | ** control everything **
212 | ** **
213 | ** ************************************************************************ **
214 | ++++*/
215 |
216 | int cmdModuleVersion( ClientData client_data,
217 | Tcl_Interp *interp,
218 | int argc,
219 | CONST84 char *argv[])
220 | {
221 | char *version, *module;
222 | ModModule *modptr;
223 | ModName *versptr, *nameptr, *tmp, *ptr;
224 | int i;
225 |
226 | #if WITH_DEBUGGING_CALLBACK
227 | ErrorLogger( NO_ERR_START, LOC, _proc_cmdModuleVersion, NULL);
228 | #endif
229 |
230 | /**
231 | ** Whatis mode?
232 | **/
233 |
234 | if( g_flags & M_WHATIS)
235 | return( TCL_OK); /** ------- EXIT PROCEDURE -------> **/
236 |
237 | /**
238 | ** Parameter check
239 | **/
240 |
241 | if( argc < 3) {
242 | if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], " modulename ",
243 | " symbolic-version [symbolic-version ...] ", NULL))
244 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
245 | }
246 |
247 | if((char *) NULL == (module = CheckModuleVersion( (char *) argv[1]))) {
248 | ErrorLogger( ERR_BADMODNAM, LOC, argv[1], NULL);
249 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
250 | }
251 |
252 | /**
253 | ** Display mode?
254 | **/
255 |
256 | if( g_flags & M_DISPLAY) {
257 | fprintf( stderr, "%s\t ", argv[ 0]);
258 | for( i=1; i<argc; i++)
259 | fprintf( stderr, "%s ", argv[ i]);
260 | fprintf( stderr, "\n");
261 | }
262 |
263 | /**
264 | ** get the version from the argument
265 | **/
266 |
267 | if((char *) NULL == (version = strrchr( module, '/'))) {
268 | if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
269 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
270 | }
271 | *version++ = '\0';
272 |
273 | /**
274 | ** Now we have a module and a version.
275 | ** Check wheter it exists (cond. create them). Check both, the version
276 | ** and the name queue in order to locate the desired version ...
277 | **/
278 |
279 | if((ModModule *) NULL == (modptr = AddModule( module))) {
280 | ErrorLogger( ERR_BADMODNAM, LOC, argv[1], NULL);
281 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
282 | }
283 |
284 | if((ModName *) NULL == (ptr = FindName( version, modptr->version, &tmp))) {
285 | if((ModName *) NULL == (ptr = FindName( version, modptr->name, &tmp)))
286 | versptr = AddName( version, &modptr->version, modptr);
287 | else
288 | versptr = ptr->version;
289 | } else
290 | versptr = ptr;
291 |
292 | /**
293 | ** Check all symbolic names now and allocate a name record for them
294 | **/
295 |
296 | for( i=2; i<argc; i++) {
297 |
298 | if( FindName( (char *) argv[ i], modptr->name, &tmp)) {
299 | if( OK != ErrorLogger( ERR_DUP_SYMVERS, LOC, argv[ i], NULL))
300 | break;
301 | else
302 | continue;
303 | }
304 |
305 | if((ModName *)NULL == (nameptr = AddName((char *)argv[ i],&modptr->name,
306 | modptr))) {
307 | if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
308 | break;
309 | else
310 | continue;
311 | }
312 |
313 | /**
314 | ** Concat the new element at the beginning of the name queue ...
315 | **/
316 |
317 | nameptr->ptr = versptr->ptr;
318 | versptr->ptr = nameptr;
319 | nameptr->version = versptr;
320 | }
321 |
322 | #if WITH_DEBUGGING_CALLBACK
323 | ErrorLogger( NO_ERR_END, LOC, _proc_cmdModuleVersion, NULL);
324 | #endif
325 |
326 | return( TCL_OK);
327 |
328 | } /** End of 'cmdModuleVersion' **/
329 |
330 | /*++++
331 | ** ** Function-Header ***************************************************** **
332 | ** **
333 | ** Function: ExpandVersions **
334 | ** **
335 | ** Description: Callback function for 'version' **
336 | ** **
337 | ** First Edition: 1995/12/28 **
338 | ** **
339 | ** Parameters: char *name Name to be expanded **
340 | ** **
341 | ** Result: char* NULL No symbols found **
342 | ** Otherwise Pointer to the list string **
343 | ** **
344 | ** ************************************************************************ **
345 | ++++*/
346 |
347 | char *ExpandVersions( char *name)
348 | {
349 | char *version, *module, *s;
350 | static char buffer[ BUFSIZ];
351 | ModModule *modptr, *tmp1;
352 | ModName *ptr, *tmp2;
353 |
354 | #if WITH_DEBUGGING_CALLBACK
355 | ErrorLogger( NO_ERR_START, LOC, _proc_cmdModuleVersion, NULL);
356 | #endif
357 |
358 | /**
359 | ** Parameter check
360 | **/
361 |
362 | if((char *) NULL == (module = CheckModuleVersion( name)))
363 | return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
364 |
365 | if((char *) NULL == (version = strrchr( module, '/'))) {
366 | if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
367 | return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
368 | }
369 |
370 | *version++ = '\0';
371 |
372 | /**
373 | ** Now we have a module and a version.
374 | ** Check wheter it exists
375 | **/
376 |
377 | if((ModModule *) NULL == (modptr = FindModule( module, &tmp1)))
378 | return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
379 |
380 | if((ModName *) NULL == (ptr = FindName( version, modptr->version, &tmp2))) {
381 | if((ModName *) NULL == (ptr = FindName( version, modptr->name, &tmp2)))
382 | return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
383 | ptr = ptr->version;
384 | }
385 |
386 | if( !ptr->ptr)
387 | return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
388 |
389 | /**
390 | ** Now scan in all the symbolic version names
391 | **/
392 |
393 | *buffer = '\0';
394 | if( s = scan_versions( buffer, buffer, ptr->ptr, modptr))
395 | *--s = '\0'; /** remove trailing ':' **/
396 |
397 | #if WITH_DEBUGGING_CALLBACK
398 | ErrorLogger( NO_ERR_END, LOC, _proc_cmdModuleVersion, NULL);
399 | #endif
400 |
401 | return( buffer);
402 |
403 | } /** End of 'ExpandVersions' **/
404 |
405 | /*++++
406 | ** ** Function-Header ***************************************************** **
407 | ** **
408 | ** Function: scan_versions **
409 | ** **
410 | ** Description: Scan all symbolic versions pointed to be the passed **
411 | ** ModName pointer and print them as a list into the **
412 | ** passed buffer. **
413 | ** **
414 | ** First Edition: 1995/12/28 **
415 | ** **
416 | ** Parameters: char *buffer Buffer for printing in **
417 | ** ModName *ptr Name structure pointer **
418 | ** ModModule *modptr Assigned module name **
419 | ** **
420 | ** Result: char* NULL Nothing printed into the **
421 | ** buffer **
422 | ** Otherwise Pointer to the end of the **
423 | ** string in the buffer **
424 | ** **
425 | ** ************************************************************************ **
426 | ++++*/
427 |
428 | static char *scan_versions( char *buffer,
429 | char *base,
430 | ModName *ptr,
431 | ModModule *modptr)
432 | {
433 | ModName *tmp, *vers;
434 | char *s;
435 |
436 | /**
437 | ** Recursively print the queue of names
438 | **/
439 |
440 | if( !ptr)
441 | return((char *) NULL); /** ------ EXIT (END) -----> **/
442 |
443 | if( !ptr->name) {
444 | if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
445 | return((char *) NULL); /** ---- EXIT (FAILURE) ---> **/
446 |
447 | } else {
448 |
449 | /**
450 | ** Prevent endless loops
451 | **/
452 |
453 | if( strstr( base, ptr->name)) {
454 | ErrorLogger( ERR_SYMLOOP, LOC, ptr->name, NULL);
455 | return((char *) NULL); /** ---- EXIT (FAILURE) ---> **/
456 | }
457 |
458 | /**
459 | ** Now print ...
460 | **/
461 |
462 | /* sprintf( buffer, "%s:", ptr->name); */
463 | strcpy( buffer, ptr->name);
464 | strcat( buffer, ":");
465 | buffer += strlen( buffer);
466 |
467 | /**
468 | ** Check wheter this is a version name again ...
469 | ** This is a recursion, too
470 | **/
471 |
472 | if((ModName *) NULL != (vers = FindName( ptr->name, modptr->version,
473 | &tmp))) {
474 | if( s = scan_versions( buffer, base, vers->ptr, modptr))
475 | buffer = s;
476 | }
477 | }
478 |
479 | /**
480 | ** This is the recursion. Preserve the buffer end pointer
481 | **/
482 |
483 | if( s = scan_versions( buffer, base, ptr->ptr, modptr))
484 | buffer = s;
485 |
486 | return( buffer);
487 |
488 | } /** End of 'scan_versions' **/
489 |
490 | /*++++
491 | ** ** Function-Header ***************************************************** **
492 | ** **
493 | ** Function: CheckModuleVersion **
494 | ** **
495 | ** Description: Reduce the passed module name into a <mod>/<vers> **
496 | ** string **
497 | ** **
498 | ** First Edition: 1995/12/28 **
499 | ** **
500 | ** Parameters: char *name name to be checked **
501 | ** **
502 | ** Result: char* NULL any error **
503 | ** Otherwise Pointer to a <mod>/<vers> **
504 | ** string **
505 | ** **
506 | ** Attached Globals: modlist List containing all version names **
507 | ** aliaslist List containing all alises **
508 | ** g_current_module The module which is handled **
509 | ** by the current command **
510 | ** **
511 | ** ************************************************************************ **
512 | ++++*/
513 |
514 | static char *CheckModuleVersion( char *name)
515 | {
516 | static char buffer[ BUFSIZ];
517 | char *s, *t;
518 |
519 | /**
520 | ** Check the first parameter and extract modulename and version
521 | **/
522 |
523 | if( '/' == *name) { /** only the version specified **/
524 |
525 | /**
526 | ** get the module name from the current module ...
527 | **/
528 |
529 | if( !g_current_module)
530 | return((char *) NULL);
531 |
532 | strcpy( buffer, g_current_module);
533 | if((char *) NULL == (t = strrchr( buffer, '/')))
534 | t = buffer + strlen( buffer);
535 | *t++ = '/';
536 | *t = '\0';
537 |
538 | /**
539 | ** The version has been specified as a parameter
540 | **/
541 |
542 | if( s = strrchr( name, '/')) {
543 | s++;
544 | } else {
545 | ErrorLogger( ERR_INTERAL, LOC, NULL);
546 | return((char *) NULL);
547 | }
548 |
549 | strcpy( t, s);
550 |
551 | } else { /** Maybe an alias or a module **/
552 |
553 | strcpy( buffer, name);
554 | if( !strrchr( buffer, '/')) {
555 |
556 | /**
557 | ** Check wheter this is an alias ...
558 | **/
559 |
560 | if( AliasLookup( buffer, &s, &t)) {
561 |
562 | /* sprintf( buffer, "%s/%s", s, t); */
563 | strcpy( buffer, s);
564 | strcat( buffer, "/");
565 | strcat( buffer, t);
566 |
567 | } else {
568 |
569 | /**
570 | ** The default version is being selected
571 | **/
572 |
573 | t = buffer + strlen( buffer);
574 | if( '/' != *t)
575 | *t++ = '/';
576 | strcpy( t, _default);
577 | }
578 | }
579 | }
580 |
581 | /**
582 | ** Pass the buffer reference to the caller
583 | **/
584 |
585 | return( buffer);
586 |
587 | } /** End of 'CheckModuleVersion' **/
588 |
589 | /*++++
590 | ** ** Function-Header ***************************************************** **
591 | ** **
592 | ** Function: cmdModuleAlias **
593 | ** **
594 | ** Description: Callback function for 'alias' **
595 | ** **
596 | ** First Edition: 1995/12/28 **
597 | ** **
598 | ** Parameters: ClientData client_data **
599 | ** Tcl_Interp *interp According Tcl interp.**
600 | ** int argc Number of arguments **
601 | ** char *argv[] Argument array **
602 | ** **
603 | ** Result: int TCL_OK Successfull completion **
604 | ** TCL_ERROR Any error **
605 | ** **
606 | ** Attached Globals: aliaslist List containing all alises **
607 | ** g_flags These are set up accordingly before **
608 | ** this function is called in order to **
609 | ** control everything **
610 | ** **
611 | ** ************************************************************************ **
612 | ++++*/
613 |
614 | int cmdModuleAlias( ClientData client_data,
615 | Tcl_Interp *interp,
616 | int argc,
617 | CONST84 char *argv[])
618 | {
619 | ModName *tmp, *ptr;
620 | char *version, *module;
621 | ModName *trg_alias;
622 | ModModule *modptr;
623 |
624 | #if WITH_DEBUGGING_CALLBACK
625 | ErrorLogger( NO_ERR_START, LOC, _proc_cmdModuleAlias, NULL);
626 | #endif
627 |
628 | /**
629 | ** Parameter check
630 | **/
631 |
632 | if( argc != 3) {
633 | if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], " aliasname ",
634 | "modulename", NULL))
635 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
636 | }
637 |
638 | /**
639 | ** Whatis mode?
640 | **/
641 |
642 | if( g_flags & M_WHATIS)
643 | return( TCL_OK); /** ------- EXIT PROCEDURE -------> **/
644 |
645 | if( g_flags & M_DISPLAY) {
646 | fprintf( stderr, "%s\t %s %s\n", argv[ 0], argv[ 1], argv[ 2]);
647 | }
648 |
649 | /**
650 | ** Check if the target is an alias ...
651 | ** Conditionally split up the passed <module>/<version> pair.
652 | **/
653 |
654 | trg_alias = FindName( (char *) argv[ 2], aliaslist, &tmp);
655 | if( !trg_alias) {
656 |
657 | if((char *) NULL == (module = CheckModuleVersion( (char *) argv[2])))
658 | module = (char *) argv[ 2];
659 |
660 | if((char *) NULL != (version = strrchr( module, '/')))
661 | *version++ = '\0';
662 | }
663 |
664 | /**
665 | ** Any alias record existing with this name?
666 | ** If it does, we're finished ...
667 | **/
668 |
669 | if( ptr = FindName( (char *) argv[ 1], aliaslist, &tmp)) {
670 |
671 | if( !ptr->ptr || !ptr->ptr->name ||
672 | !trg_alias && (!ptr->ptr->module || !ptr->ptr->module->module) ) {
673 | ErrorLogger( ERR_INTERAL, LOC, NULL);
674 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
675 | }
676 |
677 | if( trg_alias && !strcmp( ptr->ptr->name, argv[ 2]) ||
678 | !trg_alias && !strcmp( ptr->ptr->name, version) &&
679 | !strcmp( ptr->ptr->module->module, module))
680 | return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/
681 |
682 | if( OK != ErrorLogger( ERR_DUP_ALIAS, LOC, argv[1], NULL))
683 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
684 |
685 | } else {
686 |
687 | /**
688 | ** We have to allocate a new alias entry
689 | **/
690 |
691 | if((ModName *) NULL == (ptr = AddName((char *) argv[ 1],
692 | &aliaslist,NULL))) {
693 | ErrorLogger( ERR_INTERAL, LOC, NULL);
694 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
695 | }
696 | }
697 |
698 | /**
699 | ** Now ptr points to the affected module alias record ...
700 | ** Conditionally we have to create the module and the version record now.
701 | **/
702 |
703 | if( trg_alias) {
704 | ptr->ptr = trg_alias;
705 |
706 | } else {
707 | if((ModModule *) NULL == (modptr = AddModule( module))) {
708 | ErrorLogger( ERR_BADMODNAM, LOC, argv[2], NULL);
709 | ptr->ptr = (ModName *) NULL;
710 | return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
711 | }
712 | ptr->ptr = AddName( (version ? version : _default), &modptr->version,
713 | modptr);
714 | }
715 |
716 | #if WITH_DEBUGGING_CALLBACK
717 | ErrorLogger( NO_ERR_END, LOC, _proc_cmdModuleAlias, NULL);
718 | #endif
719 |
720 | return( TCL_OK);
721 |
722 | } /** End of 'cmdModuleAlias' **/
723 |
724 | /*++++
725 | ** ** Function-Header ***************************************************** **
726 | ** **
727 | ** Function: AliasLookup **
728 | ** **
729 | ** Description: Resolves a given alias to a module/version string **
730 | ** **
731 | ** First Edition: 1995/12/28 **
732 | ** **
733 | ** Parameters: char *alias Name of the alias to be re- **
734 | ** solved **
735 | ** char **module Buffer for the module name **
736 | ** char **version Buffer for the module version**
737 | ** **
738 | ** Result: int 1 Success, value in the buffer **
739 | ** is valid **
740 | ** 0 Any error, or not found **
741 | ** **
742 | ** Attached Globals: aliaslist List containing all alises **
743 | ** **
744 | ** ************************************************************************ **
745 | ++++*/
746 |
747 | int AliasLookup( char *alias,
748 | char **module,
749 | char **version)
750 | {
751 | ModName *ptr, *tmp, *oldptr = NULL;
752 |
753 | while( 1) {
754 |
755 | /**
756 | ** Lokate the alias entry and check intergrity
757 | **/
758 |
759 | if((ModName *) NULL == (ptr = FindName( alias, aliaslist, &tmp)))
760 | return( 0); /** ------- EXIT (not found) ------> **/
761 |
762 | if( ptr == oldptr || !ptr->ptr || !ptr->ptr->name ) {
763 | ErrorLogger( ERR_INTERAL, LOC, NULL);
764 | return( 0); /** -------- EXIT (FAILURE) -------> **/
765 | }
766 |
767 | /**
768 | ** Do we have to loop? Another alias has no module reference ...
769 | **/
770 |
771 | if( !ptr->ptr->module) {
772 | alias = ptr->ptr->name;
773 | oldptr = ptr;
774 | continue;
775 | }
776 |
777 | /**
778 | ** Got it. Get the module name and the version from the found
779 | ** entry.
780 | ** Dereference symbolic module versions
781 | **/
782 |
783 | *module = ptr->ptr->module->module;
784 | *version = ptr->ptr->name;
785 |
786 | if((ModName *) NULL != (ptr = FindName( *version,
787 | ptr->ptr->module->name, &tmp))) {
788 | if( !ptr->version || !ptr->version->name) {
789 | if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
790 | return( 0);
791 | } else
792 | *version = ptr->version->name;
793 | }
794 |
795 | break;
796 |
797 | } /** while **/
798 |
799 | return( 1);
800 |
801 | } /** End of 'AliasLookup' **/
802 |
803 | /*++++
804 | ** ** Function-Header ***************************************************** **
805 | ** **
806 | ** Function: VersionLookup **
807 | ** **
808 | ** Description: Resolves a given alias to a module/version string **
809 | ** **
810 | ** First Edition: 1995/12/28 **
811 | ** **
812 | ** Parameters: char *alias Name of the alias to be re- **
813 | ** solved **
814 | ** char **module Buffer for the module name **
815 | ** char **version Buffer for the module version**
816 | ** **
817 | ** Result: int 1 Success, value in the buffer **
818 | ** is valid **
819 | ** 0 Any error, or not found **
820 |
821 | ** Attached Globals: g_current_module The module which is handled **
822 | ** by the current command **
823 | ** **
824 | ** ************************************************************************ **
825 | ++++*/
826 |
827 | int VersionLookup( char *name, char **module, char **version)
828 | {
829 | static char buffer[ BUFSIZ];
830 | ModModule *mptr, *mtmp;
831 | ModName *vptr, *vtmp;
832 | ModName **history;
833 | char *s, *t;
834 | int histsize = 0, histndx = 0, i;
835 |
836 | /**
837 | ** Check whether this is an alias ...
838 | ** BTW: Alias lookups return the FQMN (full qualifed module name ;-)
839 | **/
840 |
841 | if( '/' == *name) {
842 | strcpy( buffer, g_current_module);
843 | if( s = strrchr( buffer, '/'))
844 | *s = '\0';
845 | *module = buffer;
846 | *version = name + 1;
847 |
848 | } else {
849 |
850 | strcpy( buffer, name);
851 | *module = buffer;
852 |
853 | if((char *) NULL == (*version = strrchr( buffer, '/'))) {
854 |
855 | if( AliasLookup( buffer, &s, &t)) {
856 | *module = s; *version = t;
857 |
858 | } else
859 | *version = _default;
860 |
861 | } else
862 | *(*version)++ = '\0';
863 | }
864 |
865 | /**
866 | ** Look up modulename ...
867 | ** We call it success, if we do not find a registerd name.
868 | ** In this case <module>/<version> will be returned as passed.
869 | **/
870 | if((ModModule *) NULL == (mptr = FindModule( *module, &mtmp))) {
871 | return( 1); /** -------- EXIT (SUCCESS) -------> **/
872 | }
873 |
874 | /**
875 | ** This is for preventing from endless loops
876 | **/
877 | histsize = HISTTAB;
878 | histndx = 0;
879 |
880 | if((ModName **) NULL == (history = (ModName **) malloc( histsize *
881 | sizeof( ModName *)))) {
882 | ErrorLogger( ERR_ALLOC, LOC, NULL);
883 | return( 0); /** -------- EXIT (FAILURE) -------> **/
884 | }
885 |
886 | /**
887 | ** Now look up the version name. Check symbolic names first. If some-
888 | ** thing is found, check if the related version record itsself relates
889 | ** to a name record ...
890 | **/
891 | while( 1) {
892 |
893 | /**
894 | ** Check the symbolic names ...
895 | **/
896 | if((ModName *) NULL != (vptr = FindName( *version, mptr->name, &vtmp))){
897 | if( !vptr->version || !vptr->version->name) {
898 | if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
899 | *version = (char *) NULL;
900 | break;
901 | }
902 |
903 | *version = vptr->version->name;
904 |
905 | /**
906 | ** Prevent from looping ...
907 | **/
908 | for( i=0; i<histndx; i++) {
909 | if( history[ i] == vptr) { /** That's the loop **/
910 | ErrorLogger( ERR_SYMLOOP, LOC, *version, NULL);
911 | *version = (char *) NULL;
912 | break;
913 | }
914 | }
915 |
916 | if( !*version)
917 | break;
918 |
919 | if( histndx >= histsize) {
920 | histsize += HISTTAB;
921 |
922 | if((ModName **) NULL == (history = (ModName **) realloc(
923 | history, histsize * sizeof( ModName *)))) {
924 | ErrorLogger( ERR_ALLOC, LOC, NULL);
925 | return( 0); /** -------- EXIT (FAILURE) -------> **/
926 | }
927 | }
928 |
929 | history[ histndx++] = vptr;
930 |
931 | } else {
932 | break;
933 |
934 | } /** if( FindName) **/
935 | } /** while( 1) **/
936 |
937 | /**
938 | ** Free the loop preventing list
939 | ** If version is NULL now, something went wrong in the lookup loop above
940 | **/
941 | null_free((void *) &history);
942 | return((char *) NULL != *version);
943 |
944 | } /** End of 'VersionLookup' **/
945 |
946 | /*++++
947 | ** ** Function-Header ***************************************************** **
948 | ** **
949 | ** Function: CleanupVersion **
950 | ** **
951 | ** Description: Cleanup the version structure **
952 | ** **
953 | ** First Edition: 1995/12/28 **
954 | ** **
955 | ** Parameters: - **
956 | ** **
957 | ** Result: - **
958 | ** **
959 | ** Attached Globals: modlist List containing all version names **
960 | ** aliaslist List containing all alises **
961 | ** **
962 | ** ************************************************************************ **
963 | ++++*/
964 |
965 | void CleanupVersion(ModModule *ptr)
966 | {
967 | #if WITH_DEBUGGING_UTIL_2
968 | ErrorLogger( NO_ERR_START, LOC, _proc_CleanupVersion, NULL);
969 | #endif
970 |
971 | CleanupVersionSub( modlist);
972 | modlist = (ModModule *) NULL;
973 |
974 | CleanupName( aliaslist);
975 | aliaslist = (ModName *) NULL;
976 |
977 | } /** End of 'CleanupVersion' **/
978 |
979 | static void CleanupVersionSub( ModModule *ptr)
980 | {
981 | /**
982 | ** Recursion
983 | **/
984 |
985 | if( !ptr)
986 | return;
987 |
988 | CleanupVersion( ptr->next);
989 |
990 | /**
991 | ** Cleanup everything that relates to this record
992 | **/
993 |
994 | CleanupName( ptr->version);
995 | CleanupName( ptr->name);
996 | null_free((void *) &(ptr->module));
997 |
998 | } /** End of 'CleanupVersionSub' **/
999 |
1000 | static void CleanupName( ModName *ptr)
1001 | {
1002 | /**
1003 | ** Recursion
1004 | **/
1005 |
1006 | if( !ptr)
1007 | return;
1008 |
1009 | CleanupName( ptr->next);
1010 |
1011 | /**
1012 | ** Cleanup everything that relates to this record
1013 | **/
1014 |
1015 | null_free((void *) &(ptr->name));
1016 |
1017 | } /** End of 'CleanupName' **/
1018 |
1019 | /*++++
1020 | ** ** Function-Header ***************************************************** **
1021 | ** **
1022 | ** Function: AddModule **
1023 | ** **
1024 | ** Description: Add a new entry to the modules queue **
1025 | ** **
1026 | ** First Edition: 1995/12/28 **
1027 | ** **
1028 | ** Parameters: char *name Name of the new module **
1029 | ** **
1030 | ** Result: ModModule* NULL Any error **
1031 | ** Else Pointer to the new record **
1032 | ** **
1033 | ** Attached Globals: modlist List containing all version names **
1034 | ** **
1035 | ** ************************************************************************ **
1036 | ++++*/
1037 |
1038 | static ModModule *AddModule( char *name)
1039 | {
1040 | ModModule *app_ptr, *ptr;
1041 |
1042 | #if WITH_DEBUGGING_UTIL_1
1043 | ErrorLogger( NO_ERR_START, LOC, _proc_AddModule, NULL);
1044 | #endif
1045 |
1046 | /**
1047 | ** We do not trust in NULL module names
1048 | **/
1049 |
1050 | if( !name || !*name)
1051 | return((ModModule *) NULL);
1052 |
1053 | /**
1054 | ** Check if the module name already exists and save the 'prev' pointer
1055 | ** for appending the new one.
1056 | **/
1057 |
1058 | if( ptr = FindModule( name, &app_ptr))
1059 | return( ptr);
1060 |
1061 | /**
1062 | ** Allocate a new guy
1063 | **/
1064 |
1065 | if((ModModule *) NULL == (ptr = (ModModule *) malloc( sizeof(ModModule)))) {
1066 | ErrorLogger( ERR_ALLOC, LOC, NULL);
1067 | return((ModModule *) NULL);
1068 | }
1069 |
1070 | /**
1071 | ** Fill the name in and put it in the queue
1072 | **/
1073 |
1074 | if((char *) NULL == (ptr->module = strdup( name))) {
1075 | ErrorLogger( ERR_ALLOC, LOC, NULL);
1076 | null_free((void *) &ptr);
1077 | return((ModModule *) NULL);
1078 | }
1079 |
1080 | if( app_ptr) {
1081 | ptr->next = app_ptr->next;
1082 | app_ptr->next = ptr;
1083 | } else {
1084 | ptr->next = modlist;
1085 | modlist = ptr;
1086 | }
1087 |
1088 | ptr->version = (ModName *) NULL;
1089 | ptr->name = (ModName *) NULL;
1090 |
1091 | /**
1092 | ** Pass back the pointer to the new entry
1093 | **/
1094 |
1095 | #if WITH_DEBUGGING_UTIL_1
1096 | ErrorLogger( NO_ERR_END, LOC, _proc_AddModule, NULL);
1097 | #endif
1098 |
1099 | return( ptr);
1100 |
1101 | } /** End of 'AddModule' **/
1102 |
1103 | /*++++
1104 | ** ** Function-Header ***************************************************** **
1105 | ** **
1106 | ** Function: FindModule **
1107 | ** **
1108 | ** Description: Find a new entry in the modules queue **
1109 | ** **
1110 | ** First Edition: 1995/12/28 **
1111 | ** **
1112 | ** Parameters: char *name Name of be found **
1113 | ** ModModule **prev Buffer for the 'previous' **
1114 | ** pointer **
1115 | ** **
1116 | ** Result: ModModule* NULL Any error or not found **
1117 | ** Else Pointer to the record **
1118 | ** **
1119 | ** Attached Globals: modlist List containing all version names **
1120 | ** **
1121 | ** ************************************************************************ **
1122 | ++++*/
1123 |
1124 | static ModModule *FindModule( char *name,
1125 | ModModule **prev)
1126 | {
1127 | ModModule *ptr = modlist;
1128 | int cmp = 1;
1129 |
1130 | #if WITH_DEBUGGING_UTIL_1
1131 | ErrorLogger( NO_ERR_START, LOC, _proc_FindModule, NULL);
1132 | #endif
1133 |
1134 | *prev = (ModModule *) NULL;
1135 | while( ptr && 0 < (cmp = strcmp( name, ptr->module))) {
1136 | *prev = ptr;
1137 | ptr = ptr->next;
1138 | }
1139 |
1140 | #if WITH_DEBUGGING_UTIL_1
1141 | ErrorLogger( NO_ERR_END, LOC, _proc_FindModule, NULL);
1142 | #endif
1143 |
1144 | return( cmp ? (ModModule *) NULL : ptr);
1145 |
1146 | } /** End of 'FindModule' **/
1147 |
1148 | /*++++
1149 | ** ** Function-Header ***************************************************** **
1150 | ** **
1151 | ** Function: AddName **
1152 | ** **
1153 | ** Description: Add a new entry to the name queue **
1154 | ** **
1155 | ** First Edition: 1995/12/28 **
1156 | ** **
1157 | ** Parameters: char *name Name of the new entry **
1158 | ** ModName **start Start of the queue **
1159 | ** ModModule *module Parent module record pointer **
1160 | ** **
1161 | ** Result: ModName* NULL Any error **
1162 | ** Else Pointer to the new record **
1163 | ** **
1164 | ** ************************************************************************ **
1165 | ++++*/
1166 |
1167 | static ModName *AddName( char *name,
1168 | ModName **start,
1169 | ModModule *module)
1170 | {
1171 | ModName *app_ptr, *ptr;
1172 |
1173 | #if WITH_DEBUGGING_UTIL_1
1174 | ErrorLogger( NO_ERR_START, LOC, _proc_AddName, NULL);
1175 | #endif
1176 |
1177 | /**
1178 | ** Check if the name already exists and save the 'prev' pointer
1179 | ** for appending the new one.
1180 | **/
1181 |
1182 | if( ptr = FindName( name, *start, &app_ptr))
1183 | return( ptr);
1184 |
1185 | /**
1186 | ** Allocate a new guy
1187 | **/
1188 |
1189 | if((ModName *) NULL == (ptr = (ModName *) malloc( sizeof(ModName)))) {
1190 | ErrorLogger( ERR_ALLOC, LOC, NULL);
1191 | return((ModName *) NULL);
1192 | }
1193 |
1194 | /**
1195 | ** Fill the name in and put it in the queue
1196 | **/
1197 |
1198 | if((char *) NULL == (ptr->name = strdup( name))) {
1199 | ErrorLogger( ERR_ALLOC, LOC, NULL);
1200 | null_free((void *) &ptr);
1201 | return((ModName *) NULL);
1202 | }
1203 |
1204 | if( app_ptr) {
1205 | ptr->next = app_ptr->next;
1206 | app_ptr->next = ptr;
1207 | } else {
1208 | ptr->next = *start;
1209 | *start = ptr;
1210 | }
1211 |
1212 | ptr->module = module;
1213 | ptr->version = ptr->ptr = (ModName *) NULL;
1214 |
1215 | /**
1216 | ** Pass back the pointer to the new entry
1217 | **/
1218 |
1219 | #if WITH_DEBUGGING_UTIL_1
1220 | ErrorLogger( NO_ERR_END, LOC, _proc_AddName, NULL);
1221 | #endif
1222 |
1223 | return( ptr);
1224 |
1225 | } /** End of 'AddName' **/
1226 |
1227 | /*++++
1228 | ** ** Function-Header ***************************************************** **
1229 | ** **
1230 | ** Function: FindName **
1231 | ** **
1232 | ** Description: Find a new entry in the modules queue **
1233 | ** **
1234 | ** First Edition: 1995/12/28 **
1235 | ** **
1236 | ** Parameters: char *name Name of be found **
1237 | ** ModName *start Start of the name queue **
1238 | ** ModName **prev Buffer for the 'previous' **
1239 | ** pointer **
1240 | ** **
1241 | ** Result: ModName* NULL Any error or not found **
1242 | ** Else Pointer to the record **
1243 | ** **
1244 | ** ************************************************************************ **
1245 | ++++*/
1246 |
1247 | static ModName *FindName( char *name,
1248 | ModName *start,
1249 | ModName **prev)
1250 | {
1251 | ModName *ptr = start;
1252 | int cmp = 1;
1253 |
1254 | #if WITH_DEBUGGING_UTIL_1
1255 | ErrorLogger( NO_ERR_START, LOC, _proc_FindName, NULL);
1256 | #endif
1257 |
1258 | *prev = (ModName *) NULL;
1259 | while( ptr && 0 < (cmp = strcmp( name, ptr->name))) {
1260 | *prev = ptr;
1261 | ptr = ptr->next;
1262 | }
1263 |
1264 | #if WITH_DEBUGGING_UTIL_1
1265 | ErrorLogger( NO_ERR_END, LOC, _proc_FindName, NULL);
1266 | #endif
1267 |
1268 | return( cmp ? (ModName *) NULL : ptr);
1269 |
1270 | } /** End of 'FindName' **/