/**CFile*********************************************************************** FileName [cmdMisc.c] PackageName [cmd] Synopsis [Variable table; miscellaneous commands related to the general system.] Author [SIS] Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.] ******************************************************************************/ #include "cmdInt.h" #include static char rcsid[] UNUSED = "$Id: cmdMisc.c,v 1.59 2009/04/11 18:25:50 fabio Exp $"; /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /* The maximum length of an input line */ #define MAX_STR 32768 /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ avl_tree *cmdAliasTable; avl_tree *cmdFlagTable; static boolean fileCreated; /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int CommandTime(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandEcho(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandSetBddParameters(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandMemoryProfile(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandQuit(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandUsage(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandWhich(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandHistory(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandAlias(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandUnalias(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandSetVariable(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandUnsetVariable(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandHelp(Hrc_Manager_t ** hmgr, int argc, char ** argv); static int CommandSource(Hrc_Manager_t ** hmgr, int argc, char ** argv); static void print_alias(char * value); static char * command_alias_help(char * command); static void FlushBuffers(int sigtype); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Looks up value of flag in table of named values.] Description [The command parser maintains a table of named values. These are manipulated using the 'set' and 'unset' commands. The value of the named flag is returned, or NIL(char) is returned if the flag has not been set.] SideEffects [] ******************************************************************************/ char * Cmd_FlagReadByName( char * flag) { char *value; if (avl_lookup(cmdFlagTable, flag, &value)) { return value; } else { return NIL(char); } } /**Function******************************************************************** Synopsis [Updates a set value by calling instead of set command.] Description [Updates a set value by calling instead of set command.] SideEffects [] ******************************************************************************/ void Cmd_FlagUpdateValue( char * key, char * value) { char *oldValue, *newValue; if (!key) return; if (value) newValue = util_strsav(value); else newValue = util_strsav(""); if (avl_delete(cmdFlagTable, &key, &oldValue)) FREE(oldValue); (void) avl_insert(cmdFlagTable, key, newValue); } /**Function******************************************************************** Synopsis [Deletes a set value by calling instead of unset command.] Description [Deletes a set value by calling instead of unset command.] SideEffects [] ******************************************************************************/ void Cmd_FlagDeleteByName( char * key) { char *value; if (!key) return; if (avl_delete(cmdFlagTable, &key, &value)) { FREE(key); FREE(value); } } /**Function******************************************************************** Synopsis [Initializes the command package.] SideEffects [Commands are added to the command table.] SeeAlso [Cmd_End] ******************************************************************************/ void Cmd_Init(void) { char *path; char *lib_name; cmdCommandTable = avl_init_table((int(*)(const void *, const void *))strcmp); cmdFlagTable = avl_init_table((int(*)(const void *, const void *))strcmp); cmdAliasTable = avl_init_table((int(*)(const void *, const void *))strcmp); Cmd_CommandAdd("alias", CommandAlias, 0); Cmd_CommandAdd("echo", CommandEcho, 0); Cmd_CommandAdd("help", CommandHelp, 0); Cmd_CommandAdd("quit", CommandQuit, 0); Cmd_CommandAdd("source", CommandSource, 0); /* Cmd_CommandAdd("undo", CommandUndo, 0); */ Cmd_CommandAdd("set", CommandSetVariable, 0); Cmd_CommandAdd("unalias", CommandUnalias, 0); Cmd_CommandAdd("unset", CommandUnsetVariable, 0); Cmd_CommandAdd("time", CommandTime, 0); Cmd_CommandAdd("usage", CommandUsage, 0); Cmd_CommandAdd("history", CommandHistory, 0); Cmd_CommandAdd("which", CommandWhich, 0); Cmd_CommandAdd("set_bdd_parameters" , CommandSetBddParameters, 0); Cmd_CommandAdd("_memory_profile", CommandMemoryProfile, 0); fileCreated = FALSE; /* Program the signal of type USR1 to flush vis_stdout and vis_stderr */ #ifdef SIGUSR1 (void) signal(SIGUSR1, FlushBuffers); #endif /* set the default open_path */ lib_name = Vm_VisObtainLibrary(); path = ALLOC(char, strlen(lib_name) + 20); sprintf(path, "set open_path .:%s", lib_name); Cmd_CommandExecute(NULL, path); FREE(lib_name); FREE(path); } /**Function******************************************************************** Synopsis [Ends the command package.] Description [Ends the command package. Tables are freed, and the global error string is freed.] SideEffects [] SeeAlso [Cmd_Init] ******************************************************************************/ void Cmd_End(void) { avl_free_table(cmdFlagTable, (void (*)(char *))free, (void (*)(char *))free); avl_free_table(cmdCommandTable, (void (*)(char *)) 0, CmdCommandFree); avl_free_table(cmdAliasTable, (void (*)(char *)) 0, CmdAliasFree); if (cmdBackupHmgr != NIL(Hrc_Manager_t)) { Hrc_ManagerFree(cmdBackupHmgr); } error_cleanup(); if (fileCreated == TRUE) { (void) fprintf(vis_stdout, "Purify has created a temporary file. The file"); (void) fprintf(vis_stdout, " must be deleted.\n"); } } /**Function******************************************************************** Synopsis [Test that the given string is an integer. Returns 0 if string is not an integer, 1 if the integer is too big for int, and 2 if integer fits in int.] SideEffects [Sets the pointer value if the string is an integer small enough for int.] ******************************************************************************/ int Cmd_StringCheckIsInteger( char *string, int *value) { char *ptr; long l; errno = 0 ; l = strtol (string, &ptr, 0) ; if(*ptr != '\0') return 0; if (errno != 0) return 1; if ((l > MAXINT) || (l < -1 - MAXINT)) return 1 ; *value = (int) l; return 2 ; } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [required] Description [optional] SideEffects [required] SeeAlso [optional] ******************************************************************************/ void CmdFreeArgv(int argc, char ** argv) { int i; for(i = 0; i < argc; i++) { FREE(argv[i]); } FREE(argv); } /**Function******************************************************************** Synopsis [required] Description [optional] SideEffects [required] SeeAlso [optional] ******************************************************************************/ void CmdAliasFree( char * value) { CmdAliasDescr_t *alias = (CmdAliasDescr_t *) value; CmdFreeArgv(alias->argc, alias->argv); FREE(alias->name); /* same as key */ FREE(alias); } /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the time command.] CommandName [time] CommandSynopsis [provide a simple elapsed time value] CommandArguments [\[-h\]\[-u\]] CommandDescription [Prints the processor time used since the last time command, and the total processor time used since VIS was started.

By default, the time reported is the CPU time spent executing instructions of the calling process and the time this process waited for children that terminated.

Command options:

-h
Print the command usage.
-u
Exclude child process time.
] SideEffects [] ******************************************************************************/ static int CommandTime( Hrc_Manager_t ** hmgr, int argc, char ** argv) { static long last_time_u = 0; static long last_time_c = 0; long time; int c; boolean excludeChildren = FALSE; util_getopt_reset(); while ((c = util_getopt(argc,argv,"hu")) != EOF){ switch(c){ case 'h': goto usage; case 'u': excludeChildren = TRUE; break; default: goto usage; } } if (argc != util_optind) { goto usage; } if (excludeChildren) { time = util_cpu_time(); (void) fprintf(vis_stdout, "elapse: %2.1f seconds, total: %2.1f seconds\n", (time - last_time_u) / 1000.0, time / 1000.0); last_time_u = time; } else { time = util_cpu_ctime(); (void) fprintf(vis_stdout, "elapse: %2.1f seconds, total: %2.1f seconds\n", (time - last_time_c) / 1000.0, time / 1000.0); last_time_c = time; } return 0; usage: (void) fprintf(vis_stderr, "usage: time [-h][-u]\n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); (void) fprintf(vis_stderr, " -u \t\texclude child process time\n"); return 1; } /**Function******************************************************************** Synopsis [Implements the echo command.] CommandName [echo] CommandSynopsis [merely echo the arguments] CommandArguments [\[-h\] <args>] CommandDescription [Echoes the arguments to standard output.

Command options:

-h
Print the command usage.
] SideEffects [] ******************************************************************************/ static int CommandEcho( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int i; int c; util_getopt_reset(); while ((c = util_getopt(argc, argv, "h")) != EOF) { switch(c) { case 'h': goto usage; default: goto usage; } } for(i = 1; i < argc; i++) { (void) fprintf(vis_stdout, "%s ", argv[i]); } (void) fprintf(vis_stdout, "\n"); return 0; usage: (void) fprintf(vis_stderr, "usage: echo [-h] string \n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); return (1); } /**Function******************************************************************** Synopsis [Implements the set_bdd_parameters command.] SideEffects [] CommandName [set_bdd_parameters] CommandSynopsis [Creates a table with the value of all the flags currently active in VIS and calls the function bdd_set_parameters with the manager of the current place in the hierarchy and the table.] CommandArguments [\[-h\]\[-s\]] CommandDescription [The command obtains the bdd manager of the current point in the hierarchy. Given this manager and the set of pairs (variable,value) of the VIS environment, the function sets specific BDD parameters to the given values. This command works in conjunction with print_bdd_stats.

Print_bdd_stats first prints a report of the parameters and statistics of the current bdd_manager. By using the command "set", the user may modify the value of any of the parameters of the underlying bdd package. The way to do it is by setting a value in the variable BDD.parameter name where parameter name<\tt> is the name of the parameter exactly as printed by the print_bdd_stats command. In order to "re-program" the underlying bdd package this command must be invoked.

Command options:

-h
Print the command usage.
-s
Print the bdd parameter and statistics after the modification.
] ******************************************************************************/ static int CommandSetBddParameters( Hrc_Manager_t ** hmgr, int argc, char ** argv) { Ntk_Network_t *network; boolean showAfter; int c; showAfter = FALSE; network = Ntk_HrcManagerReadCurrentNetwork(*hmgr); /* * Parse the command line. */ util_getopt_reset(); while ((c = util_getopt(argc, argv, "hs")) != EOF) { switch (c) { case 'h': goto usage; case 's': showAfter = TRUE; break; default: goto usage; } } /* flatten_hierarchy and static_order must have been invoked already. */ if (network == NIL(Ntk_Network_t)) { return 1; } if (!Ntk_NetworkReadMddManager(network)) { (void) fprintf(vis_stderr, "The MDD variables have not been ordered. "); (void) fprintf(vis_stderr, "Use static_order.\n"); return 1; } /* Create the table of variable->value */ bdd_set_parameters(Ntk_NetworkReadMddManager(network), cmdFlagTable, vis_stdout); if (showAfter) { bdd_print_stats(Ntk_NetworkReadMddManager(network), vis_stdout); } return 0; /* Everything okay */ usage: (void) fprintf(vis_stderr, "usage: set_bdd_parameters [-h] [-s]\n"); (void) fprintf(vis_stderr, " -h print the command usage\n"); (void) fprintf(vis_stderr, " -s print also the bdd statistics\n"); return 1; } /**Function******************************************************************** Synopsis [Implements the _memory_profile command.] CommandName [_memory_profile] CommandSynopsis [It shows the amount of memory used by every pacakge.] CommandArguments [\[-f <filename>\] \[-h\] \[-p\] \[-u <units>\]] CommandDescription [This command intregrates the output from purify with a function map generated by a perlscript plus another perlscript to generate a memory profile of vis.

This command relies on the output of purify to a file to call the script "memoryaccount" and produce a summary of how much memory has been allocated by each package. Although this command may appear simple it requires the interaction of two scripts and three files, so special care should be taken when attempting to modify it.

Here is the way it works. The code in this command is conditionally compiled depending on the definition of the symbol PURIFY. If the symbol is not defined, the program prints a message notifying that the command is not operative in this executable. If PURIFY has been defined, there are certain things that are assumed. The executable has been linked with purify. The output of purify is being redirected to a file with name purify.log. The perl script memoryaccount is in $VIS/common/share and it is executable. There exists a file mapping function names to packages in the same place whose name is .fmap.

The command then calls purify_all_inuse() to force purify to dump to the file purify.log the information about the memory that is currently visible to the program. This memory is not the total memory allocated by the program since there may be leaked memory that is no longer accessible. A temporary file is created and the script memoryaccount is called to analyze the file purify.log and write in the temporary file the memory profile obtained from it. Once the script is done, the temporary file is dumped to vis_stdout and deleted.

Since most of the computation in this command is done by the pearlscript memoryaccount, for more information please refer to the message printed when the script is invoked with the option -h. Command options:

-f <filename>
File to read the dump from. The default is purify.log. This option should be used if and only if the option -log-file has been used at the linking stage when building the executable.
-h
Print the command usage.
-p
Print also the packages that did not allocated any visible memory
-u <units>
Units to print the memory usage in. It may be "b" for bytes, "k" for kilobytes, "m" for megabytes and "g" for gigabytes. The default is bytes.
] SideEffects [] ******************************************************************************/ static int CommandMemoryProfile( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int c; char options[128]; #ifdef PURIFY char tmpFileName[128]; FILE *fp; char command[256]; char *visDirectoryName; int systemStatus; #endif /* * Parse command line options. */ options[0] = 0; util_getopt_reset(); while ((c = util_getopt(argc, argv, "f:hpu:")) != EOF) { switch(c) { case 'f': strcat(options, " -f "); strcat(options, util_optarg); break; case 'h': goto usage; case 'p': strcat(options, " -p "); break; case 'u': strcat(options, " -u "); strcat(options, util_optarg); break; default: goto usage; } } #ifdef PURIFY /* Flag to remember that a file has been created by purify */ fileCreated = TRUE; /* Obtain the name of a temporary file */ tmpnam(tmpFileName); /* Kick purify to dump the data in the file */ purify_all_inuse(); /* Obtain the path to the perl script */ visDirectoryName = Vm_VisObtainLibrary(); /* Prepare the string to be sent to a shell */ (void)sprintf(command, "%s/memoryaccount %s %s/.fmap ./.fmap >%s", visDirectoryName, options, visDirectoryName, tmpFileName); /* Effectively execute the perlscript */ systemStatus = system(command); if (systemStatus != 0) { return 1; } fp = Cmd_FileOpen(tmpFileName, "r", NIL(char *), 1); /* Check if the open has been successful */ if (fp == NIL(FILE)) { (void) fprintf(vis_stderr, "** cmd error: File %s was not found\n", tmpFileName); return 1; } /* Dump the contents of the result file in vis_stdout */ while(fgets(command, 128, fp) != NIL(char)) { (void) fprintf(vis_stdout, "%s", command); } fclose(fp); /* Remove the temporary file */ #if HAVE_UNLINK unlink(tmpFileName); #endif #else (void) fprintf(vis_stderr, "** cmd error: Command not available: Vis has not been "); (void) fprintf(vis_stderr, "compiled with purify.\n"); #endif return 0; /* normal exit */ usage: (void) fprintf(vis_stderr, "usage: _memory_profile [-f ] [-h] "); (void) fprintf(vis_stderr, "[-p] [-u ] \n"); (void) fprintf(vis_stderr, " -f \tFile to read the purify dump"); (void) fprintf(vis_stderr, " from. The default is purify.log\n"); (void) fprintf(vis_stderr, " -h\t\tprint the command usage\n"); (void) fprintf(vis_stderr, " -p\t\tPrint also the packages that do not "); (void) fprintf(vis_stderr, " allocate any memory\n"); (void) fprintf(vis_stderr, " -u \tUnits to print the memory usage"); (void) fprintf(vis_stderr, " in. It may be b for bytes\n"); (void) fprintf(vis_stderr, " \t\tk for kilobytes, m for megabytes and "); (void) fprintf(vis_stderr, "g for gigabutes.\n"); return 1; /* error exit */ } /**Function******************************************************************** Synopsis [Implements the quit command.] Description [A return value of -1 indicates a quick quit, -2 return frees the memory.] CommandName [quit] CommandSynopsis [exit VIS] CommandArguments [\[-h\] \[-s\]] CommandDescription [Stops the program. Does not save the current network before exiting.

Command options:

-h
Print the command usage.
-s
Free all the memory before quitting. This is slower, and is used for finding memory leaks.
] SideEffects [] ******************************************************************************/ static int CommandQuit( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int c; util_getopt_reset(); while ((c = util_getopt(argc,argv,"hs")) != EOF){ switch(c){ case 'h': goto usage; case 's': return -2; default: goto usage; } } if ( argc != util_optind){ goto usage; } return -1; usage: (void)fprintf(vis_stderr, "usage: quit [-h] [-s]\n"); (void)fprintf(vis_stderr, " -h print the command usage\n"); (void)fprintf(vis_stderr, " -s frees all the memory before quitting\n"); return 1; } /**Function******************************************************************** Synopsis [Implements the usage command.] CommandName [usage] CommandSynopsis [provide a dump of process statistics] CommandArguments [\[-h\]] CommandDescription [Prints a formatted dump of processor-specific usage statistics. For Berkeley Unix, this includes all of the information in the getrusage() structure.

Command options:

-h
Print the command usage.
] SideEffects [] ******************************************************************************/ static int CommandUsage( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int c; util_getopt_reset(); while ((c = util_getopt(argc,argv,"h")) != EOF){ switch(c){ case 'h': goto usage; default: goto usage; } } if (argc != util_optind){ goto usage; } util_print_cpu_stats(vis_stdout); return 0; usage: (void) fprintf(vis_stderr, "usage: usage [-h]\n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [Implements the which command.] CommandName [which] CommandSynopsis [look for a file called name] CommandArguments [\[-h\] <file_name>] CommandDescription [Looks for a file in a set of directories which includes the current directory as well as those in the VIS path. If it finds it, it reports the path. The path is specified through the "set open_path" command in the .visrc.

Command options:

-h
Print the command usage.
<file_name>
File to be searched
] SideEffects [] SeeAlso [set] ******************************************************************************/ static int CommandWhich( Hrc_Manager_t ** hmgr, int argc, char ** argv) { FILE *fp; char *filename; int c; util_getopt_reset(); while ((c = util_getopt(argc,argv,"h")) != EOF){ switch(c){ case 'h': goto usage; default: goto usage; } } if (argc-1 != util_optind){ goto usage; } fp = Cmd_FileOpen(argv[1], "r", &filename, 0); if (fp != 0) { (void) fprintf(vis_stdout, "%s\n", filename); (void) fclose(fp); } FREE(filename); return 0; usage: (void)fprintf(vis_stderr,"usage: which [-h] file_name\n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [Implements the history command.] CommandName [history] CommandSynopsis [list previous commands and their event numbers] CommandArguments [\[-h\] \[<num>\]] CommandDescription [Lists previous commands and their event numbers. This is a UNIX-like history mechanism inside the VIS shell.

Command options:

-h
Print the command usage.
<num>
Lists the last <num> events. Lists the last 30 events if <num> is not specified.

History Substitution:

The history substitution mechanism is a simpler version of the csh history substitution mechanism. It enables you to reuse words from previously typed commands.

The default history substitution character is the `%' (`!' is default for shell escapes, and `#' marks the beginning of a comment). This can be changed using the "set" command. In this description '%' is used as the history_char. The `%' can appear anywhere in a line. A line containing a history substitution is echoed to the screen after the substitution takes place. `%' can be preceded by a `\\' in order to escape the substitution, for example, to enter a `%' into an alias or to set the prompt.

Each valid line typed at the prompt is saved. If the "history" variable is set (see help page for "set"), each line is also echoed to the history file. You can use the "history" command to list the previously typed commands.

Substitutions:

At any point in a line these history substitutions are available.

%:0
Initial word of last command.
%:n
n-th argument of last command.
%$
Last argument of last command.
%*
All but initial word of last command.
%%
Last command.
%stuf
Last command beginning with "stuf".
%n
Repeat the n-th command.
%-n
Repeat the n-th previous command.
^old^new
Replace "old" with "new" in previous command. Trailing spaces are significant during substitution. Initial spaces are not significant.
] SideEffects [] SeeAlso [set] ******************************************************************************/ static int CommandHistory( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int i, num, lineno; int size; int c; util_getopt_reset(); while ((c = util_getopt(argc, argv, "h")) != EOF) { switch(c) { case 'h': goto usage; default: goto usage; } } if (argc > 3) { goto usage; } num = 30; lineno = 1; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { if (argv[i][1] == 'h') { lineno = 0; } else { goto usage; } } else { num = atoi(argv[i]); if (num <= 0) { goto usage; } } } size = array_n(vm_commandHistoryArray); num = (num < size) ? num : size; for (i = size - num; i < size; i++) { if (lineno != 0) { (void) fprintf(vis_stdout, "%d\t", i + 1); } (void) fprintf(vis_stdout, "%s\n", array_fetch(char *, vm_commandHistoryArray, i)); } return(0); usage: (void) fprintf(vis_stderr, "usage: history [-h] [num]\n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); (void) fprintf(vis_stderr, " num \t\tprint the last num commands\n"); return(1); } /**Function******************************************************************** Synopsis [Implements the alias command.] CommandName [alias] CommandSynopsis [provide an alias for a command] CommandArguments [\[-h\] \[<name> \[<string>\]\]] CommandDescription [The "alias" command, if given no arguments, will print the definition of all current aliases.

Given a single argument, it will print the definition of that alias (if any). Given two arguments, the keyword "name" becomes an alias for the command string "string", replacing any other alias with the same name.

Command options:

-h
Print the command usage.
<name>
Alias
<string>
Command string
It is possible to create aliases that take arguments by using the history substitution mechanism. To protect the history substitution character `%' from immediate expansion, it must be preceded by a `\\' when entering the alias.

For example:

   vis> alias read read_\\%:1 \\%:2.\\%:1
   vis> read blif lion
  
will create an alias `read', execute "read_blif lion.blif".

And...

  vis> alias echo2 "echo Hi ; echo \\%* !"
  vis> echo2 happy birthday
  
will print:

  Hi
  happy birthday !
  
CAVEAT: Currently there is no check to see if there is a circular dependency in the alias definition. e.g.

  vis> alias foo "print_network_stats; print_network; foo"
  
creates an alias which refers to itself. Executing the command "foo" will result an infinite loop during which the commands "print_network_stats" and "print_network" will be executed.

] SideEffects [] SeeAlso [unalias] ******************************************************************************/ static int CommandAlias( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int i; char *key, *value; CmdAliasDescr_t *alias; avl_generator *gen; int status; int c; util_getopt_reset(); while ((c = util_getopt(argc, argv, "h")) != EOF) { switch(c) { case 'h': goto usage; default: goto usage; } } if (argc == 1) { avl_foreach_item(cmdAliasTable, gen, AVL_FORWARD, &key, &value) { print_alias(value); } return 0; } else if (argc == 2) { if (avl_lookup(cmdAliasTable, argv[1], &value)) { print_alias(value); } return 0; } /* delete any existing alias */ key = argv[1]; if (avl_delete(cmdAliasTable, &key, &value)) { CmdAliasFree(value); } alias = ALLOC(CmdAliasDescr_t, 1); alias->name = util_strsav(argv[1]); alias->argc = argc - 2; alias->argv = ALLOC(char *, alias->argc); for(i = 2; i < argc; i++) { alias->argv[i-2] = util_strsav(argv[i]); } status = avl_insert(cmdAliasTable, alias->name, (char *) alias); assert(!status); /* error here in SIS version, TRS, 8/4/95 */ return 0; usage: (void) fprintf(vis_stderr, "usage: alias [-h] [command [string]]\n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); return (1); } /**Function******************************************************************** Synopsis [Implements the unalias command.] CommandName [unalias] CommandSynopsis [remove the definition of an alias.] CommandArguments [\[-h\] <alias_names>] CommandDescription [Removes the definition of an alias.

Command options:

-h
Print the command usage.
<alias_names>
Aliases to be removed
] SideEffects [] SeeAlso [alias] ******************************************************************************/ static int CommandUnalias( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int i; char *key, *value; int c; util_getopt_reset(); while ((c = util_getopt(argc, argv, "h")) != EOF) { switch(c) { case 'h': goto usage; default: goto usage; } } if (argc < 2) { goto usage; } for(i = 1; i < argc; i++) { key = argv[i]; if (avl_delete(cmdAliasTable, &key, &value)) { CmdAliasFree(value); } } return 0; usage: (void) fprintf(vis_stderr, "usage: unalias [-h] alias_names\n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [Implements the set command.] CommandName [set] CommandSynopsis [set an environment variable] CommandArguments [\[-h\] \[<name>\] \[<value>\]] CommandDescription [ A variable environment is maintained by the command interpreter. The "set" command sets a variable to a particular value, and the "unset" command removes the definition of a variable. If "set" is given no arguments, it prints the current value of all variables.

Command options:

-h
Print the command usage.
<name>
Variable name
<value>
Value to be assigned to the variable.

Interpolation of variables is allowed when using the set command. The variables are referred to with the prefix of '$'. So for example, the following can be done to check the value of a set variable:
vis> set foo bar
vis> echo $foo
bar
The last line "bar" will the output produced by vis.

Variables can be extended by using the character ':' to concatenate values. For example :
vis> set foo bar
vis> set foo $foo:foobar
vis> echo $foo
bar:foobar
The variable foo is extended with the value foobar .

Whitespace characters may be present within quotes. However, variable interpolation lays the restriction that the characters ':' and '/' may not be used within quotes. This is to allow for recursive interpolation. So for example, the following is allowed
vis> set "foo bar" this
vis> echo $"foo bar"
this
The last line will be the output produced by vis.
But in the following, the value of the variable foo/bar will not be interpreted correctly:

vis> set "foo/bar" this
vis> echo $"foo/bar"
foo/bar
If a variable is not set by the "set" command, then the variable is returned unchanged.

Different commands use environment information for different purposes. The command interpreter makes use of the following parameters:

autoexec
Defines a command string to be automatically executed after every command processed by the command interpreter. This is useful for things like timing commands, or tracing the progress of optimization.
open_path
"open_path" (in analogy to the shell-variable PATH) is a list of colon-separated strings giving directories to be searched whenever a file is opened for read. Typically the current directory (.) is first in this list. The standard system library (typically $VIS_LIBRARY_PATH) is always implicitly appended to the current path. This provides a convenient short-hand mechanism for reaching standard library files.
vis_stderr
Standard error (normally stderr) can be re-directed to a file by setting the variable vis_stderr.
vis_stdout
Standard output (normally stdout) can be re-directed to a file by setting the variable vis_stdout.
Building MDDs for the network makes use of following setting:
partition_method
This parameter is used to select the method for creating the partition. The vertices of a partition correspond to the combinational inputs, combinational outputs, and any intermediate nodes used. Each vertex has a multi-valued function (represented by MDDs) expressing the function of the corresponding network node in terms of the partition vertices in its transitive fanin. Hence, the MDDs of the partition represent a partial collapsing of the network. The possible values of partition_method are:
inout
Expresses the combinational outputs in terms of the combinational inputs. This is the default partitioning method.
total
The partition built is isomorphic to the combinational part of the network. The function of each node is expressed in terms of its immediate fanins.
frontier
The partition built contains the combinational part of the network as well as vertices corresponding to some intermediate nodes. These vertices are generated to control the MDD sizes of the combinational outputs. The number of intermediate variables can be controlled by the parameter "partition_threshold". The method "inout" and "total" are special cases of this method (corresponding to a partition_threshold of infinity and 0 respectively).
partition_threshold
This parameter is used in conjuction with the selection of "frontier" as partition method. This determines the threshold at which a new MDD variable is created in the partition.
Image computation makes use of following settings:
image_method
The "image_method" parameter is used to control the image method used in various symbolic analysis techniques. Currently, two image methods are implemented. Use "set image_method <method>" to choose the appropriate method.
monolithic
This is the most naive approach possible. However, this method is not suitable for circuits with more than 20 latches.
tfm
This is the pure transition function method. This method is supposed not to be used in general fixpoint computations. Approximate traversal is an application of this method. Basically this method is made as a part of hybrid method. For more detailed options, see the help of print_tfm_options command.
hybrid
This is a hybrid method combining transition relation and function methods. Transition relation method is based on conjunction of partitioned transition relation, whereas transition function method is based on splitting on an input or output variable recursively. The hybrid method choose either splitting or conjunction at each recursion dynamically using the dependence matrix. For details, refer to the paper "To split or to Conjoin: The Question in Image Computation" by In-Ho Moon, James Kukula, Kavita Ravi, and Fabio Somenzi, DAC'00. Also for more detailed options, see the help of print_hybrid_options command.
iwls95
This technique is based on the early variable quantification and related heuristics of Ranjan, et al. "Efficient BDD Algorithms for FSM Synthesis and Verification", IWLS 1995. First, from the given multivalued functions, bit level relations are created. These relations are then clustered based on the value of threshold value controlled by image_cluster_size parameter. Next the relations are ordered for early variable quantification. This ordering is controlled by the parameters image_W1, image_W2, image_W3, and image_W4.
mlp
This technique is based on minimizing the variable lifetime in the conjunctions of the partitioned transition relation. The method is called MLP (Minimal Lifetime Permutation). For details, refer to the paper "Border-Block Triangular Form and Conjunction Schedule in Image Computation" by In-Ho Moon, Gary Hachtel, and Fabio Somenzi, FMCAD'00. Also for more detailed options, see the help of print_mlp_options command.
image_farside_method
This parameter is used in conjunction with the selection of iwls95, mlp, or linear as the image_method. When the value is 1, the compositional far side image computation approach is enabled; when the value is 0, this feature is disabled (default).
image_cluster_size
This parameter is used in conjunction with the selection of iwls95 as the image_method. The value of this parameter is used as threshold value for creating clusters. The default value of this parameter is 5000 which has been empirically proved to be an optimal value.
image_W1, image_W2, image_W3, image_W4
These parameters are used in conjunction with the selection of iwls95 as the image_method. They control the weights associated with various factors in ordering the clusters. The default values are 6, 1, 1, and 2 respectively. For a detailed description of these parameters, please refer to the paper in IWLS'95 proceedings.
image_verbosity
Sets the verbosity mode (0 minimum to 4 maximum), for the image method iwls95.

image_minimize_method <method>
Sets a minimization method to minimize the transition relation or an image/preimage computaion with a set of dont-care states.

Methods: 0 : restrict (default).

1 : constrain

2 : compact (currently supported by only CUDD)

3 : squeeze (currently supported by only CUDD)

scc_method <method>
Sets the symbolic method to enumerate strongly connected components (SCCs). Symbolic SCC enumeration is the core computation in LTL and fair-CTL model checking.

Methods: lockstep : the O(nlogn) time LockStep algorithm (default).

Methods: linearstep : the linear time symbolic algorithm (default).

] SideEffects [] SeeAlso [unset] ******************************************************************************/ static int CommandSetVariable( Hrc_Manager_t ** hmgr, int argc, char ** argv) { char *flag_value, *key, *value; avl_generator *gen; int c; util_getopt_reset(); while ((c = util_getopt(argc, argv, "h")) != EOF) { switch(c) { case 'h': goto usage; default: goto usage; } } if (argc == 0 || argc > 3) { goto usage ; } else if (argc == 1) { avl_foreach_item(cmdFlagTable, gen, AVL_FORWARD, &key, &value) { (void) fprintf(vis_stdout, "%s\t%s\n", key, value); } return 0; } else { key = argv[1]; if (avl_delete(cmdFlagTable, &key, &value)) { FREE(key); FREE(value); } flag_value = argc == 2 ? util_strsav("") : util_strsav(argv[2]); (void) avl_insert(cmdFlagTable, util_strsav(argv[1]), flag_value); if (strcmp(argv[1], "vis_stdout") == 0) { if (vis_stdout != stdout) { (void) fclose(vis_stdout); } if (strcmp(flag_value, "") == 0) { flag_value = "-"; } vis_stdout = Cmd_FileOpen(flag_value, "w", NIL(char *), 0); if (vis_stdout == NULL) { vis_stdout = stdout; } #if HAVE_SETVBUF setvbuf(vis_stdout, (char *)NULL, _IOLBF, 0); #endif } if (strcmp(argv[1], "vis_stderr") == 0) { if (vis_stderr != stderr) { (void) fclose(vis_stderr); } if (strcmp(flag_value, "") == 0) { flag_value = "-"; } vis_stderr = Cmd_FileOpen(flag_value, "w", NIL(char *), 0); if (vis_stderr == NULL) { vis_stderr = stderr; } #if HAVE_SETVBUF setvbuf(vis_stderr, (char *)NULL, _IOLBF, 0); #endif } if (strcmp(argv[1], "history") == 0) { if (vis_historyFile != NIL(FILE)) { (void) fclose(vis_historyFile); } if (strcmp(flag_value, "") == 0) { vis_historyFile = NIL(FILE); } else { vis_historyFile = Cmd_FileOpen(flag_value, "w", NIL(char *), 0); if (vis_historyFile == NULL) { vis_historyFile = NIL(FILE); } } } return 0; } usage: (void) printf("usage: set [-h] [name] [value]\n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [Implements the unset command.] CommandName [unset] CommandSynopsis [unset an environment variable] CommandArguments [\[-h\] <variables>] CommandDescription [ A variable environment is maintained by the command interpreter. The "set" command sets a variable to a particular value, and the "unset" command removes the definition of a variable.

Command options:

-h
Print the command usage.
<variables>
Variables to be unset
] SideEffects [] SeeAlso [set] ******************************************************************************/ static int CommandUnsetVariable( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int i; char *key, *value; int c; util_getopt_reset(); while ((c = util_getopt(argc, argv, "h")) != EOF) { switch(c) { case 'h': goto usage; default: goto usage; } } if (argc < 2) { goto usage; } for(i = 1; i < argc; i++) { key = argv[i]; if (avl_delete(cmdFlagTable, &key, &value)) { FREE(key); FREE(value); } } return 0; usage: (void) fprintf(vis_stderr, "usage: unset [-h] variables \n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [Implements the help command.] CommandName [help] CommandSynopsis [provide on-line information on commands] CommandArguments [\[-a\] \[-h\] \[<command>\]] CommandDescription [Given no arguments, "help" prints a list of all commands known to the command interpreter. If a command name is given, detailed information for that command will be provided.

Command options:

-a
Provides a list of all internal commands, which by convention begin with an underscore.
-h
Print the command usage.
] SideEffects [] ******************************************************************************/ static int CommandHelp( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int c, i, all; char *key; avl_generator *gen; char buffer[1024]; char *command; char *lib_name; #if HAVE_GETENV char *pager; #endif util_getopt_reset(); all = 0; while ((c = util_getopt(argc, argv, "ah")) != EOF) { switch(c) { case 'a': all = 1; break; case 'h': goto usage; default: goto usage; } } if (argc - util_optind == 0) { fprintf(vis_stderr,"List of commands:\n"); i = 0; avl_foreach_item(cmdCommandTable, gen, AVL_FORWARD, &key, NIL(char *)) { if ((key[0] == '_') == all) { (void) fprintf(vis_stdout, "%-26s", key); if ((++i%3) == 0) { (void) fprintf(vis_stdout, "\n"); } } } if ((i%3) != 0) { (void) fprintf(vis_stdout, "\n"); } } else if (argc - util_optind == 1) { command = command_alias_help(argv[util_optind]); lib_name = Vm_VisObtainLibrary(); #if HAVE_GETENV pager = getenv("PAGER"); if (pager != NULL) { (void) sprintf(buffer, "%s %s/help/%sCmd.txt", pager, lib_name, command); } else { (void) sprintf(buffer, "more %s/help/%sCmd.txt", lib_name, command); } #else (void) sprintf(buffer, "more %s/help/%sCmd.txt", lib_name, command); #endif (void) system(buffer); FREE(lib_name); } else { goto usage; } return 0; usage: (void) fprintf(vis_stderr, "usage: help [-a] [-h] [command]\n"); (void) fprintf(vis_stderr, " -a \t\tprint help for all commands\n"); (void) fprintf(vis_stderr, " -h \t\tprint the command usage\n"); return 1; } #if 0 Change "/*!*Function" to "/**Function" when reactivate command /*!*Function******************************************************************** Synopsis [Implements the undo command.] CommandName [undo] CommandSynopsis [undo the result of the last command which changed the network] CommandDescription [ A simple 1-level undo is supported. It reverts the network to its state before the last command which changed the network. Note that interrupting a command (with ^C) which changes the network uses up the one level of undo.

] SideEffects [] ******************************************************************************/ static int CommandUndo( Hrc_Manager_t ** hmgr, int argc, char ** argv) { if (argc != 1) { (void) fprintf(vis_stderr, "usage: undo\n"); return 1; } (void) fprintf(vis_stderr, "** cmd error: undo: not yet implemented\n"); return 1; #if 0 /* * FIX (Tom): can't enable "undo" until network_dup and hmgr_dup exist. */ if (cmdBackupHmgr == NIL(Hrc_Manager_t)) { (void) fprintf(vis_stderr, "undo: no hmgr currently saved\n"); return 1; } else { /* Swap the current and backup. */ Hrc_Manager_t *temp = *hmgr; *hmgr = cmdBackupHmgr; cmdBackupHmgr = temp; return 0; } #endif } #endif /**Function******************************************************************** Synopsis [Implements the source command.] CommandName [source] CommandSynopsis [execute commands from a file] CommandArguments [\[-h\] \[-p\] \[-s\] \[-x\] <file> \[<args>\]] CommandDescription [Reads and executes commands from a file.

Command options:

-h
Print the command usage.
-p
Print a prompt before reading each command.
-s
Silently ignore an attempt to execute commands from a nonexistent file.
-x
Echo each command before it is executed.
<file>
File name
Arguments on the command line after the filename are remembered but not evaluated. Commands in the script file can then refer to these arguments using the history substitution mechanism.

EXAMPLE:

Contents of test.scr:

  read_blif_mv %:2
  init_verify
  simulate -n 10
  
Typing "source test.scr lion.mv" on the command line will execute the sequence

  read_blif_mv lion.mv
  init_verify
  simulate -n 10
  
(In this case %:0 gets "source", %:1 gets "test.scr", and %:2 gets "lion.mv".) If you type "alias st source test.scr" and then type "st lion.blif bozo", you will execute

  read_blif_mv bozo
  init_verify
  simulate -n 10
  
because "bozo" was the second argument on the last command line typed. In other words, command substitution in a script file depends on how the script file was invoked. Switches passed to a command are also counted as positional parameters. Therefore, if you type "st -x lion.mv bozo", you will execute
  read_blif_mv lion.mv
  init_verify
  simulate -n 10
  
To pass the "-x" switch (or any other switch) to "source" when the script uses positional parameters, you can define an alias. For instance, "alias srcx source -x".

] SideEffects [required] SeeAlso [history] ******************************************************************************/ static int CommandSource( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int c, echo, prompt, silent, interactive, quit_count, lp_count; int status = 0; /* initialize so that lint doesn't complain */ int lp_file_index, did_subst; char *prompt_string, *real_filename, line[MAX_STR], *command; FILE *fp; interactive = silent = prompt = echo = 0; util_getopt_reset(); while ((c = util_getopt(argc, argv, "hipsx")) != EOF) { switch(c) { case 'h': goto usage ; case 'i': /* a hack to distinguish EOF from stdin */ interactive = 1; break; case 'p': prompt = 1; break; case 's': silent = 1; break; case 'x': echo = 1; break; default: goto usage; } } /* added to avoid core-dumping when no script file is specified */ if (argc == util_optind){ goto usage; } lp_file_index = util_optind; lp_count = 0; /* * FIX (Tom, 5/7/95): I'm not sure what the purpose of this outer do loop * is. In particular, lp_file_index is never modified in the loop, so it * looks it would just read the same file over again. Also, SIS had * lp_count initialized to -1, and hence, any file sourced by SIS (if -l or * -t options on "source" were used in SIS) would actually be executed * twice. */ do { lp_count ++; /* increment the loop counter */ fp = Cmd_FileOpen(argv[lp_file_index], "r", &real_filename, silent); if (fp == NULL) { FREE(real_filename); return ! silent; /* error return if not silent */ } quit_count = 0; do { if (prompt) { prompt_string = Cmd_FlagReadByName("prompt"); if (prompt_string == NIL(char)) { prompt_string = "vis> "; } } else { prompt_string = NIL(char); } /* clear errors -- e.g., EOF reached from stdin */ clearerr(fp); /* read another command line */ if (CmdFgetsFilec(line, MAX_STR, fp, prompt_string) == NULL) { if (interactive) { if (quit_count++ < 5) { (void) fprintf(vis_stderr, "\nUse \"quit\" to leave VIS.\n"); continue; } status = -1; /* fake a 'quit' */ } else { status = 0; /* successful end of 'source' ; loop? */ } break; } quit_count = 0; if (echo) { (void) fprintf(vis_stdout, "%s", line); } command = CmdHistorySubstitution(line, &did_subst); if (command == NIL(char)) { status = 1; break; } if (did_subst) { if (interactive) { (void) fprintf(stdout, "%s\n", command); } } if (command != line) { (void) strcpy(line, command); } if (interactive && *line != '\0') { array_insert_last(char *, vm_commandHistoryArray, util_strsav(line)); if (vis_historyFile != NIL(FILE)) { (void) fprintf(vis_historyFile, "%s\n", line); (void) fflush(vis_historyFile); } } status = Cmd_CommandExecute(hmgr, line); } while (status == 0); if (fp != stdin) { if (status > 0) { (void) fprintf(vis_stderr, "** cmd error: aborting 'source %s'\n", real_filename); } (void) fclose(fp); } FREE(real_filename); } while ((status == 0) && (lp_count <= 0)); return status; usage: (void) fprintf(vis_stderr, "source [-h] [-p] [-s] [-x] file_name\n"); (void) fprintf(vis_stderr, "\t-h print the command usage\n"); (void) fprintf(vis_stderr, "\t-p supply prompt before reading each line\n"); (void) fprintf(vis_stderr, "\t-s silently ignore nonexistent file\n"); (void) fprintf(vis_stderr, "\t-x echo each line as it is executed\n"); return 1; } /**Function******************************************************************** Synopsis [required] Description [optional] SideEffects [required] SeeAlso [optional] ******************************************************************************/ static void print_alias( char * value) { int i; CmdAliasDescr_t *alias; alias = (CmdAliasDescr_t *) value; (void) fprintf(vis_stdout, "%s\t", alias->name); for(i = 0; i < alias->argc; i++) { (void) fprintf(vis_stdout, " %s", alias->argv[i]); } (void) fprintf(vis_stdout, "\n"); } /**Function******************************************************************** Synopsis [required] Description [optional] SideEffects [required] SeeAlso [optional] ******************************************************************************/ static char * command_alias_help( char * command) { char *value; CmdAliasDescr_t *alias; if (!avl_lookup(cmdAliasTable, command, &value)) { return command; } alias = (CmdAliasDescr_t *) value; return alias->argv[0]; } /**Function******************************************************************** Synopsis [Function to flush vis_stdout and vis_stderr.] Description [This function is the signal handler for the SIGUSR1 signal. Whenever that signal is received, this function is executed and the output channels of VIS are flushed.] SideEffects [] SeeAlso [Cmd_Init] ******************************************************************************/ static void FlushBuffers( int sigtype) { fflush(vis_stdout); fflush(vis_stderr); /* Reprogram again the handler */ #ifdef SIGUSR1 (void) signal(SIGUSR1, FlushBuffers); #endif } /* End of FlushBuffers */