00001
00009 #include <string.h>
00010 #include <time.h>
00011 #include <stdio.h>
00012
00013 #include "ipc.h"
00014 #include "cmdparam.h"
00015 #include "binarysave.h"
00016 #include "inputs.h"
00017 #include "globals.h"
00018
00019
00020
00021 #ifdef USE_READLINE_LIBRARY
00022
00027 typedef char *CPFunction (char *, int);
00028 typedef char **CPPFunction (char *, int);
00029 extern CPPFunction *rl_attempted_completion_function;
00030 EXTERNAL_C_LINKAGE char *readline ( char *prompt);
00031 EXTERNAL_C_LINKAGE void add_history (char *string);
00032 EXTERNAL_C_LINKAGE char **completion_matches (char *text, CPFunction *entry_function);
00033 #endif
00034
00035
00036
00037
00038
00039
00040 #define MAX_PROMPT_CHARS 1024
00041
00042
00043
00044
00045
00046
00047
00048 #define RCFILENAME ".lissomrc"
00049
00050 bool has_command_file=false;
00051
00052 const char lissom_version[]="4.0";
00053
00054
00128 const char title_string[]=
00129 " RF-LISSOM SOFTWARE\n"
00130 "\n"
00131 " James A. Bednar\n"
00132 " Department of Computer Sciences\n"
00133 " The University of Texas at Austin\n"
00134 "\n"
00135 " Version: %s\n"
00136 " Compiled on %s at %s.\n";
00137
00138
00139 const char intro_string[]=
00140 "`lissom' is a Receptive-Field LISSOM implementation that currently\n"
00141 "runs on single-processor UNIX machines. Since `lissom' is a living\n"
00142 "program used for research, all documentation in this file and others\n"
00143 "should be considered preliminary, incomplete, outdated, and otherwise\n"
00144 "inaccurate. Then again, it is hopefully better than nothing ;^).\n\n"
00145
00146 "This program is free software; you can redistribute it and/or modify it\n"
00147 "under the terms of the GNU General Public License version 2 as published\n"
00148 "by the Free Software Foundation. This program is distributed in the hope\n"
00149 "that it will be useful, but without any warranty; without even the\n"
00150 "implied warranty of merchantability or fitness for a particular purpose.\n"
00151 "See the GNU General Public License for more details.\n\n"
00152
00153 "Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003 James A. Bednar\n";
00154
00155
00156 const char usage[]=
00157 "Usage: %s [<options>]*\n\n"
00158
00159 " where <options> may be any of the following:\n\n"
00160
00161 " --no-init-file Do not process any " RCFILENAME " file(s).\n"
00162 " If present must be the first option given.\n\n"
00163
00164 " <param>=<value> Set the given parameter to the given value\n\n"
00165
00166 " --help Print this message\n\n"
00167
00168 " [--file] <command file> Execute commands in the given file\n\n"
00169 " --train Train network until tend\n"
00170 " --test Test network (without learning) until tend\n\n"
00171
00172 " --batch Suppress interactive prompt & image viewing\n"
00173 " --interactive Force interactive prompt\n"
00174 " --remote Use ppm_remote_viewer, not ppm_image_viewer\n\n"
00175 " --display Call the plot cmd for every presentation\n\n"
00176
00177 " --filebase <basename> Basename to use for generated files\n\n"
00178
00179 " --verbose Increase level of messages printed\n\n"
00180 " --quiet Reduce level of messages printed\n\n"
00181
00182 " --command '<command> [<arg>]*' Execute the given command with given args\n"
00183 " -c '<command> [<arg>]*' Shortcut for --command\n\n"
00184
00185
00186 "Each option is processed strictly in the order given on the command line,\n"
00187 "repeatedly if given more than once. This means that you can e.g. set\n"
00188 "a parameter to have one value when processing one command file, and another\n"
00189 "when processing the next, or else override a value set in one before going\n"
00190 "on to the next. After the options have all been processed, interactive\n"
00191 "command-prompt mode is entered if requested explicitly or if no command\n"
00192 "has yet been executed that caused the network to be initialized. Type\n"
00193 "`help' in interactive mode for more information on commands and parameters.\n";
00194
00195
00196 const char param_help_string[]=
00197 "Parameters are given values using the command `set', which takes\n"
00198 "any number of pairs of parameter names and values in the form \n"
00199 "[[[::]<path>::]<name>=<value>], up to the maximum number of\n"
00200 "command arguments defined in cmdparam.h. See `help set' for\n"
00201 "information about valid parameter values, such as numeric\n"
00202 "expressions. See `help parameters list' to find out what\n"
00203 "parameters are available. See `help constants list' to find\n"
00204 "out available symbolic constants, which are like parameters\n"
00205 "except they cannot be set.\n\n"
00206
00207 "Type `help <name>' for more information about a particular\n"
00208 "parameter, and for even more information search the source code\n"
00209 "to see where that parameter is used. Be careful not to assume\n"
00210 "that a given parameter is supported in all cases where it might\n"
00211 "conceptually apply, since the code is continually under\n"
00212 "development; if in doubt check the code or run an experiment.\n\n"
00213
00214 "Nearly all parameters have default values, but the default will often\n"
00215 "need to be overridden for a particular case. Many parameters also\n"
00216 "have hard-coded limits, and `set' will (in most cases) refuse\n"
00217 "to set the value if the limits are violated. Legal ranges for\n"
00218 "parameters often begin at Uninitialized, which is currently -1.\n"
00219 "Uninitialized generally means that the program will try to\n"
00220 "dynamically determine an appropriate default; see the help for a\n"
00221 "particular parameter for more information. The help lists the\n"
00222 "current parameter value and the current limits on its value, but\n"
00223 "remember that these differ at different times and for different\n"
00224 "compilation constant definitions. An asterisk in a range (`*')\n"
00225 "indicates that there is no limit of the indicated type, e.g.\n"
00226 "`[0,*]' denotes a parameter which may take any positive value.\n\n"
00227
00228 "Note that, at this time, dynamic restructuring of the network connections\n"
00229 "is supported only for the special case of decreasing exc_rad. Changes to\n"
00230 "other network architecture parameters will be refused after a network is\n"
00231 "initialized.\n\n";
00232
00233
00234 const char cmd_help_string[]=
00235 "Commands may be specified through any of the following means, listed\n"
00236 "in order of processing (and thus in reverse order of precedence):\n\n"
00237
00238 " ${HOME}/" RCFILENAME " (if present)\n"
00239 " ./" RCFILENAME " (if present)\n"
00240 " file(s) specified on the command-line (if any, in order)\n"
00241 " command-prompt command(s) (if any, as entered)\n\n"
00242
00243 "Arguments to the set command (e.g. 'x=y') can be entered in lieu of a\n"
00244 "command; see the documentation for set for more details. In all other\n"
00245 "cases a command consists of a command name followed by its arguments,\n"
00246 "separated by spaces, all on a single line except that multiple\n"
00247 "command-file lines ending in a backslash (`\\') are concatenated. Single\n"
00248 "or double quotes may be used to ensure that an argument containing spaces\n"
00249 "is interpreted as a single argument. At the command prompt or in a command\n"
00250 "file, blank lines and comment lines (lines whose first non-blank character\n"
00251 "is `#') are ignored. Comments are also allowed after commands if they are\n"
00252 "preceded by `#'.\n\n"
00253
00254 "Type `help command <name>' for more information about a particular\n"
00255 "command, and for more information than that search the source code for\n"
00256 "cmd_<name> see where that command is defined. Each command may take\n"
00257 "a certain fixed minimum number of arguments, followed by an arbitrary\n"
00258 "number of optional arguments. Some commands accept named arguments\n"
00259 "of the form x=y following the command name; if so they will list which\n"
00260 "arguments are accepted. Almost all commands accept the same\n"
00261 "form of expressions for all numeric and string arguments as the\n"
00262 "`set' command does; see `help set' for more details.\n\n"
00263
00264 "In practice, the first command file specified on the command line, if\n"
00265 "any, will usually be used to set the starting values of training\n"
00266 "parameters. It will often also set up automatic changes to some of\n"
00267 "these parameters at predetermined times during training (see help\n"
00268 "for the command `hook'). For instance, the excitatory radius is\n"
00269 "generally decreased as training progresses, and this is usually done\n"
00270 "using `hook' with `set'.\n\n"
00271
00272 "The actual training and/or testing of the network can be performed by\n"
00273 "adding more commands (e.g. `training' or `testing') to the end of\n"
00274 "first command file. However, to keep that file general often you will\n"
00275 "want to put such commands into a second file, so that it can be\n"
00276 "omitted when working with the network interactively. If just simple\n"
00277 "training until `tend' is desired, the second file isn't needed; just\n"
00278 "specify the appropriate command on the command line, e.g. `--train',\n"
00279 "`--test' or `--command ...', or type it at the interactive prompt.\n\n"
00280
00281 "The global and per-directory options files (named " RCFILENAME ") are\n"
00282 "useful for setting host-specific parameters, such as running_remotely,\n"
00283 "or e.g. default network parameter sizes.\n";
00284
00285
00286 const char file_types_string[]=
00287 "%s can create many files over the course of a run. Depending\n"
00288 "on the commands used, different files will be created, but most will\n"
00289 "be of one of the formats below. All of the filenames should start\n"
00290 "with the value of the filebase parameter. This parameter defaults to\n"
00291 "`lissom' for runs with no command file, the name of the first command\n"
00292 "file (minus `.param' extension, if any). The extensions may be any of\n"
00293 "the following:\n\n"
00294
00295
00296 ".<t>.params Command file with parameter values as defined\n"
00297 " when init_network was called; can be used to\n"
00298 " recreate a starting state later.\n\n"
00299
00300 ".log Generic logging output from commands, if any\n\n"
00301
00302 ".<t>.<angle>.p<pres>.ppm Input and activity image in PPM format.\n\n"
00303
00304
00305
00306
00307
00308
00309
00310 ".aff_map.ppm PPM plot of afferent weights to each neuron.\n\n"
00311
00312 ".<t>.or.ppm Orientation map in PPM format.\n\n"
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 ".<t>.wts ASCII or binary weight state file.\n\n"
00323 ".<t>.wts.<ui>_<uj>.ppm Weights for the neuron (ui,uj) in PPM format\n"
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 ;
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 CMD_DECLARE(help);
00354 CMD_DECLARE(make_doc);
00356 char** command_prompt_completion (char *text, int start, int end);
00357 int get_line_from_prompt( void );
00358 void lissom_init_hooks(void);
00359 bool process_command_line_args(int argc, char **argv);
00360 void set_filebase(string commandfilename);
00361 void wrong_usage(const char* filename);
00362 void read_command_file_if_present(string name);
00363
00364
00365
00366
00367
00368
00369
00371 int main(int argc, char **argv)
00372 {
00373 time_t start_time = time(NULL);
00374
00375
00376 lissom_init_hooks();
00377
00378
00379 ipc_notify(IPC_ONE,IPC_SUMMARY,"Execution of %s started %.24s on %s",
00380 argv[0], ctime(&start_time), getenv("HOST") );
00381
00382
00383 const bool is_interactive = process_command_line_args(argc,argv);
00384
00385
00386 if (is_interactive) {
00387 if (!has_command_file)
00388 ipc_init_logfile(filebase.c_str());
00389 cmdparam_changes_verbose=True;
00390 cmddefs_exec_batch(&get_line_from_prompt,"prompt");
00391 }
00392
00393
00394 ipc_exit(IPC_EXIT_NORMAL,"Exited normally");
00395 return 0;
00396 }
00397
00398
00399
00400
00401
00402
00403
00405 void lissom_init_hooks(void)
00406 {
00407
00408 if (check_ind_types(False))
00409 ipc_exit(0,"Need to add definitions to ind_types.c for this architecture.");
00410
00411 ipc_init();
00412
00413
00414 static Msg::LevelHandler<> ipc_message_handler;
00415 ipc_message_handler.register_handler( Msg::Verbose, Msg::ipc_verbose );
00416 ipc_message_handler.register_handler( Msg::Notify, Msg::ipc_notify );
00417 ipc_message_handler.register_handler( Msg::Requested, Msg::ipc_requested );
00418 ipc_message_handler.register_handler( Msg::Warning, Msg::ipc_warning );
00419 ipc_message_handler.register_handler( Msg::Error, Msg::ipc_error );
00420 Msg::LevelHandler<>::set_default_instance(&ipc_message_handler);
00421
00422
00423 blackboard.add_constants();
00424
00425
00426 setvbuf( stdout, NULL, _IONBF , 0);
00427
00428 #ifdef USE_READLINE_LIBRARY
00429 rl_attempted_completion_function = (CPPFunction *)command_prompt_completion;
00430 #endif
00431
00432 CMD_DOC(help,NULL,0,"%s [<options>]",
00433 "Try:\n\n"
00434
00435 " help parameters for general help using parameters and constants\n"
00436 " help parameters list for a concise list of the available parameters\n"
00437 " help parameters doc for help on all parameters\n"
00438 " help constants list for a concise list of the available constants\n"
00439 " help constants doc for help on all constants\n"
00440
00441 " help commands for general help using commands\n"
00442 " help commands list for a concise list of the available commands\n"
00443 " help commands doc for help on all commands\n"
00444
00445 " help usage for help on the command-line options\n"
00446 " help version for the date and number of this version of LISSOM\n"
00447
00448 " help <name> for help with a specific parameter, constant,\n"
00449 " or command");
00450
00451
00452 CMD_DOC(make_doc,NULL,0,"%s [<filename>]",
00453 "Create a file with the specified name containing all the help information\n"
00454 "available. It is currently formatted as an ASCII document.");
00455
00456
00457 globals_init_hook();
00458 kernel_init_hook();
00459 Inputs::global_entry().register_params_and_commands();
00460 LISSOMBinaryStateSaver::init_hook();
00461 cmdparam_init_hook();
00462
00463
00464 cmddefs_define_command_doc
00465 ("hook","%s <hook_location> <iteration_specifier> <command> [<arguments>]",
00466 "This command allows you to specify that any other command should be\n"
00467 "executed at a specified iteration or iterations.\n\n"
00468
00469 "The <command> and its <arguments> may be any valid command and any\n"
00470 "arguments that it accepts. Any command arguments are evaluated when the\n"
00471 "command is run, not when the hook is first defined.\n\n"
00472
00473 "The <iteration_specifier> should be of the (recursive) form:\n\n"
00474
00475 " <start_iteration>[-<end_iteration>[%<step>]][,<iteration_specifier>]\n\n"
00476
00477 "Each of the first three quantities may be a <term> as defined by the command\n"
00478 "`set', which means that any compound expressions must be parenthesized. For\n"
00479 "example, the <iteration_specifier> can be:\n\n"
00480
00481 " a single iteration (e.g. `1000'),\n"
00482 " a range of iterations (e.g. `1-1000'), \n"
00483 " a range with a stepsize (e.g. `1-1000%%10'), or\n"
00484 " a list of any of these (e.g. `1,10,100-200%%100,7,50-52,(tend-2)-tend').\n\n"
00485
00486 "In the first case, the command is executed only once, at iteration 1000,\n"
00487 "in the second it is executed 1000 times, once per iteration, in the third,\n"
00488 "it is executed 100 times, at iterations 10, 20, etc. (all those evenly\n"
00489 "divisible by 10), and in the last one it is executed at iterations 1,7,\n"
00490 "10,50,51,52,100,200,19998,19999, and 20000, assuming tend==20000. Note\n"
00491 "that the <iteration_specifier> must not contain any spaces.\n\n"
00492
00493 "The <hook_location> specifies where in the code the hook is checked\n"
00494 "for (and executed at the appropriate time.) Currently hooks can be\n"
00495 "inserted at the following locations within an iteration of the training\n"
00496 "or testing commands:\n\n"
00497
00498 " before_input: At the start of the training iteration, before input,\n"
00499 " activation, settling, or learning. Useful for setting parameters,\n"
00500 " loading a saved state, etc.\n\n"
00501
00502 " after_learning: At the end of the training iteration, after input,\n"
00503 " activation, settling, and learning. Useful for saving state,\n"
00504 " plotting, analyzing the activity, etc.\n\n"
00505
00506 "At a given hook_location and iteration, all the hooks that apply\n"
00507 "are executed in the order of their start_iteration and (if those\n"
00508 "match) the order in which they were defined.\n\n"
00509
00510 "Hooks can also be defined to execute multiple times within a given\n"
00511 "specified iteration or iterations(s) using the following hooklist:\n\n"
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 "Examples:\n\n"
00523
00524 " hook before_input 501 set exc_rad=9 delta=0.12 beta=0.67\n"
00525 " hook before_input 1001 set exc_rad=6 delta=0.15 beta=0.65\n\n"
00526
00527 "These could be part of a training schedule that gradually reduces the\n"
00528 "excitation radius while increasing the slope of the sigmoid.\n\n"
00529
00530 " hook after_learning 1-100%%2 plot\n"
00531 " hook after_learning 1000 plot\n\n"
00532
00533 " hook after_learning 10000 kill_connections 0.0001\n\n"
00534
00535 "The top two specify 101 iterations at which the input and activity\n"
00536 "should be plotted. The next specifies that inhibitory weights smaller\n"
00537 "than 0.0001 should be pruned at iteration 10000.\n\n"
00538
00539
00540 " hook after_learning 1 for f=0 f<PI f=f+PI/18 input_present_object \"\" Input_Gaussian f\n\n"
00541
00542 "This hook presents a variety of stimuli at iteration 1.");
00543
00544
00545 PARAM_A(blackboard,"command_prompt_format",
00546 string("lissom.t${iteration}.p${presentation}.c${command_num_called}${current_param_set_path}> "),,
00547 "Command prompt for an interactive session. The value of this parameter\n"
00548 "is evaluated as for a string argument to a command, substituting the\n"
00549 "value of any specified parameters at the time the prompt is printed.\n\n"
00550
00551 "As a special case, the string '${param_set_path}' is globally replaced\n"
00552 "by the path to the parameter set currently selected, even though there\n"
00553 "is currently no parameter by that name.\n\n"
00554
00555 "As another special case, the characters '\\033' are replaced by the\n"
00556 "escape character. This allows ANSI color codes to be used in the\n"
00557 "prompt. Example:\n\n"
00558
00559 " command_prompt_format=\"\\033[33;40;1mlissom.t$${iteration}.p$${presentation}.c$${command_num_called}$${current_param_set_path}>\\033[m \"");
00560
00561
00562 cmddefs_exec_str("uninit_network");
00563 }
00564
00565
00566
00567
00568
00569
00570
00572 void wrong_usage(const char* filename)
00573 {
00574 if (AMPARENTPE)
00575 fprintf(stdout,usage,filename);
00576 ipc_exit(IPC_EXIT_WRONG_USAGE,"Wrong usage");
00577 }
00578
00579
00580
00582 void read_command_file_if_present(string name)
00583 {
00584 cmdparam_changes_verbose=network_initialized;
00585 FILE *file=fopen(name.c_str(),"r");
00586 if (file) {
00587 ipc_notify(IPC_ONE,IPC_STD,"Processing command file %s", name.c_str());
00588 fclose(file);
00589 if (cmddefs_exec_file(name.c_str()))
00590 ipc_notify(IPC_ONE,IPC_ERROR,"Problem with command file %s",name.c_str());
00591 }
00592 }
00593
00594
00596 #define nextargis(str) (arglist.nextis(string(str)))
00597
00606 bool process_command_line_args(int argc, char **argv)
00607 {
00608 CMD_ARG_LIST;
00609
00610 Tristate force_interactive=Uninitialized;
00611 const string progname=arglist.next(string("lissom"));
00612
00613
00614
00615
00616 if (arglist.empty() || !arglist.nextis(string("--no-init-file"))) {
00617 read_command_file_if_present(string(getenv("HOME"))+"/" RCFILENAME);
00618 read_command_file_if_present(RCFILENAME);
00619 }
00620
00621
00622 bool has_filebase=false;
00623
00624 while (!arglist.empty()) {
00625
00626 cmdparams_set(blackboard,arglist,true,false,true);
00627
00628 if (nextargis("--help") || nextargis("-h"))
00629 fprintf(stdout,usage,progname.c_str());
00630
00631 else if (nextargis("--batch")) {
00632 cmdparam_set("interactive","False");
00633 force_interactive=False;
00634 }
00635 else if (nextargis("--interactive")) {
00636 cmdparam_set("interactive","True");
00637 force_interactive=True;
00638 }
00639 else if (nextargis("--remote")) cmdparam_set("running_remotely","True");
00640 else if (nextargis("--display")) cmdparam_set("display","1");
00641 else if (nextargis("--verbose")) ipc_msg_level+=2;
00642 else if (nextargis("--quiet")) ipc_msg_level-=2;
00643
00644 else if (nextargis("--filebase")) {
00645 if (arglist.empty())
00646 wrong_usage(progname.c_str());
00647 else {
00648 filebase = arglist.next(string(""));
00649 has_filebase=true;
00650 }
00651 }
00652
00653 else if (nextargis("--command") || nextargis("-c")) {
00654 if (arglist.empty())
00655 wrong_usage(progname.c_str());
00656 else {
00657 ipc_init_logfile(filebase.c_str());
00658 const string cmd=arglist.next(string(""));
00659 cmddefs_exec_str(cmd.c_str());
00660 }
00661 }
00662
00663 else if (nextargis("--set")) {
00664 const string param=arglist.next(string(""));
00665 if (arglist.empty())
00666 wrong_usage(progname.c_str());
00667 else {
00668 const string val=arglist.next(string(""));
00669 cmdparam_set(param,val);
00670 }
00671 }
00672
00673 else if (nextargis("--train")) {
00674 ipc_init_logfile(filebase.c_str());
00675 cmddefs_exec_str("training");
00676 cmdparam_set("interactive","False");
00677 }
00678
00679 else if (nextargis("--test")) {
00680 ipc_init_logfile(filebase.c_str());
00681 cmddefs_exec_str("testing");
00682 cmdparam_set("interactive","False");
00683 }
00684
00685 else if (!arglist.empty()) {
00686 const string filename=arglist.next(string(""));
00687 const string start=string(filename,0,2);
00688
00689 if (start == "--") {
00690 if (nextargis("--file"));
00691 else
00692 wrong_usage(progname.c_str());
00693 }
00694
00695 if (filename=="")
00696 wrong_usage(progname.c_str());
00697 else {
00698 if (!has_command_file) {
00699 has_command_file=true;
00700 if (!has_filebase)
00701 set_filebase(filename.c_str());
00702 ipc_init_logfile(filebase.c_str());
00703 }
00704
00705
00706 cmdparam_changes_verbose=network_initialized;
00707
00708
00709 ipc_notify(IPC_ONE,IPC_STD,"Processing command file %s", filename.c_str());
00710 if (cmddefs_exec_file(filename.c_str()))
00711 ipc_abort(IPC_EXIT_FILE_PROBLEM,"Problem with command file %s",
00712 filename.c_str());
00713 cmdparam_changes_verbose=True;
00714 }
00715 }
00716 }
00717
00718
00719
00720 if (force_interactive == Uninitialized && !network_initialized)
00721 cmdparam_set("interactive","True");
00722
00723 return blackboard.get_with_default("interactive",True);
00724 }
00725 #undef nextargis
00726
00727
00728
00733 void set_filebase(string commandfilename)
00734 {
00735 int extension = commandfilename.rfind(".param");
00736 filebase =
00737 ((extension<0 || extension>=int(commandfilename.length()))?
00738 commandfilename :
00739 commandfilename.replace(extension,commandfilename.length(),""));
00740 }
00741
00742
00743
00745 int get_line_from_prompt( void )
00746 {
00747 const string param_set_name = (blackboard.path_name()=="" ? "" : "::"+blackboard.path_name());
00748 const string promptformat = blackboard.get_with_default("command_prompt_format",string(""));
00749
00750
00751
00752 unsigned pos;
00753 string p = promptformat;
00754 const string param_set_marker="${current_param_set_path}";
00755 const string escape_marker="\\033";
00756 while ((pos=p.find(param_set_marker))<p.length())
00757 p.replace(pos,param_set_marker.length(),param_set_name);
00758 while ((pos=p.find(escape_marker))<p.length())
00759 p.replace(pos,escape_marker.length(),"\033");
00760
00761
00762 const string promptstr = Parse(blackboard,p.c_str()).cmds();
00763
00764
00765 char prompt[MAX_PROMPT_CHARS];
00766 SNPRINTF(prompt, MAX_PROMPT_CHARS, "%s",promptstr.c_str());
00767
00768 char *lineptr=NULL;
00769 #ifdef USE_READLINE_LIBRARY
00770 lineptr= readline(prompt);
00771 if (lineptr) {
00772 if (*lineptr) add_history(lineptr);
00773 strncpy(cmddefs_line_buffer,lineptr,CMD_MAX_LINE_LENGTH+1);
00774 free(lineptr);
00775 lineptr=cmddefs_line_buffer;
00776 }
00777 else
00778 fprintf(stdout,"\n");
00779 #else
00780 fprintf(stdout,prompt);
00781 lineptr = fgets(cmddefs_line_buffer,CMD_MAX_LINE_LENGTH+1,stdin);
00782 #endif
00783
00784 return (lineptr==NULL);
00785 }
00786
00787
00788
00789 #ifdef USE_READLINE_LIBRARY
00790 char ** command_prompt_completion (char *text, int start, int end)
00791 {
00792 (void)end;
00793
00794
00795 return (start==0 ?
00796 completion_matches(text, cmddefs_completion_generator) :
00797 completion_matches(text, params_completion_generator) );
00798 }
00799 #endif
00800
00801
00802
00803 #define COMPAREARG(arg,string) (argc>(arg) && !strcmp(argv[arg],string))
00804 cmdstat cmd_help( CMD_ARGS )
00805 {
00806 if (AMPARENTPE) {
00807
00808
00809 if (COMPAREARG(0,"parameters")) {
00810 if (COMPAREARG(1,"list")) params_print_parameters(stdout);
00811 else if (COMPAREARG(1,"doc")) params_print_parameters_doc(stdout);
00812 else fprintf(stdout,param_help_string);
00813 }
00814
00815
00816 else if (COMPAREARG(0,"constants")) {
00817 if (COMPAREARG(1,"list")) params_print_constants(stdout);
00818 else if (COMPAREARG(1,"doc")) params_print_constants_doc(stdout);
00819 else fprintf(stdout,param_help_string);
00820 }
00821
00822
00823 else if (COMPAREARG(0,"commands")) {
00824 if (COMPAREARG(1,"list")) cmddefs_print_all(stdout);
00825 else if (COMPAREARG(1,"doc")) cmddefs_print_all_doc(stdout);
00826 else fprintf(stdout,cmd_help_string);
00827 }
00828
00829
00830 else if (COMPAREARG(0,"set")) {
00831 cmdparams_print_doc(stdout, "set");
00832 fprintf(stdout,"\nAt present, parameters may be set in any of the following paths:\n(default)\n");
00833 blackboard.print_children(stdout);
00834 }
00835
00836
00837 else if (COMPAREARG(0,"files")) fprintf(stdout,file_types_string,"lissom");
00838 else if (COMPAREARG(0,"usage")) fprintf(stdout,usage,"lissom");
00839 else if (COMPAREARG(0,"version")) {
00840 fprintf(stdout,"This is version %s of LISSOM, compiled on %s at %s.\n",
00841 lissom_version,__DATE__, __TIME__);
00842 }
00843
00844
00845 else if (argc>0 && cmdparams_print_doc(stdout, argv[0]));
00846
00847
00848 else
00849 cmddefs_print_doc(stdout,"help");
00850 }
00851
00852 return CMD_NO_ERROR;
00853 }
00854 #undef COMPARE_ARG
00855
00857 #define NEW_SECTION(name) \
00858 fprintf(file,"\nSECTION: " #name "\n\n")
00859
00861 #define NEW_SUBSECTION(name) \
00862 fprintf(file,"\nSUBSECTION: " #name "\n\n")
00863
00865 cmdstat cmd_make_doc( CMD_ARGS )
00866 {
00867 const char *filename=(argc>0 ? PARSE_C(argv[0]) : "USERDOC");
00868
00869 if (AMPARENTPE) {
00870 FILE *file;
00871 if ((file=fopen(filename,"w+"))==NULL){
00872 ipc_notify(IPC_ALL,IPC_ERROR,"Could not open output file %s", filename);
00873 return CMD_FILE_ERROR;
00874 }
00875
00876 fprintf(file,title_string,lissom_version,__DATE__, __TIME__);
00877
00878 NEW_SECTION(INTRODUCTION);
00879 fprintf(file,intro_string);
00880
00881 NEW_SECTION(USAGE);
00882 fprintf(file,usage,"lissom");
00883
00884 NEW_SECTION(PARAMETERS);
00885 fprintf(file,param_help_string);
00886 fprintf(file,"\nList of valid parameters:\n\n");
00887 params_print_parameters(file);
00888
00889 NEW_SUBSECTION(PARAMETER DOCUMENTATION);
00890 params_print_parameters_doc(file);
00891
00892 NEW_SECTION(CONSTANTS);
00893 fprintf(file,"\nList of valid constants:\n\n");
00894 params_print_constants(file);
00895
00896 NEW_SUBSECTION(CONSTANT DOCUMENTATION);
00897 params_print_constants_doc(file);
00898
00899 NEW_SECTION(COMMANDS);
00900 fprintf(file,cmd_help_string);
00901 fprintf(file,"\nList of valid commands:\n\n");
00902 cmddefs_print_all(file);
00903
00904 NEW_SUBSECTION(COMMAND DOCUMENTATION);
00905 cmddefs_print_all_doc(file);
00906
00907 NEW_SECTION(FILES);
00908 fprintf(file,file_types_string,"lissom");
00909
00910 fclose(file);
00911 }
00912
00913 ipc_notify(IPC_ONE,IPC_STD,"Created documentation file %s",filename);
00914
00915 return CMD_NO_ERROR;
00916 }
00917 #undef NEW_SECTION
00918 #undef NEW_SUBSECTION
00919