cmdhist.c

Go to the documentation of this file.
00001 /*                       C M D H I S T . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1998-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** \addtogroup butcl */
00023 /*@{*/
00024 /** @file cmdhist.c
00025  *
00026  *@brief
00027  * Routines for maintaining a command history
00028  *
00029  * The history routines were borrowed from mged/history.c
00030  * and modified to work with command history objects.
00031  *
00032  *  @author   Robert G. Parker
00033  *
00034  *  @par Authors of mged/history.c
00035  *         Glenn Durfee                                 @n
00036  *         Robert G. Parker
00037  *
00038  *  @par Source -
00039  *      The U. S. Army Research Laboratory                      @n
00040  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00041  *
00042  */
00043 
00044 
00045 #include "common.h"
00046 
00047 
00048 #ifdef HAVE_STRING_H
00049 #include <string.h>
00050 #endif
00051 
00052 #include "tcl.h"
00053 
00054 #include "machine.h"
00055 #include "cmd.h"
00056 
00057 /*
00058  *      H I S T O R Y _ R E C O R D
00059  *
00060  *      Stores the given command with start and finish times in the
00061  *      history vls'es.
00062  */
00063 static void
00064 history_record(struct bu_cmdhist_obj *chop, struct bu_vls *cmdp, struct timeval *start, struct timeval *finish, int status)
00065 
00066 
00067 
00068                    /* Either TCL_OK or TCL_ERROR */
00069 {
00070         struct bu_cmdhist *new_hist;
00071 
00072         if (strcmp(bu_vls_addr(cmdp), "\n") == 0)
00073                 return;
00074 
00075         new_hist = (struct bu_cmdhist *)bu_malloc(sizeof(struct bu_cmdhist),
00076                                                   "mged history");
00077         bu_vls_init(&new_hist->h_command);
00078         bu_vls_vlscat(&new_hist->h_command, cmdp);
00079         new_hist->h_start = *start;
00080         new_hist->h_finish = *finish;
00081         new_hist->h_status = status;
00082         BU_LIST_INSERT(&chop->cho_head.l, &new_hist->l);
00083 
00084         chop->cho_curr = &chop->cho_head;
00085 }
00086 
00087 static int
00088 timediff(struct timeval *tvdiff, struct timeval *start, struct timeval *finish)
00089 {
00090         if (finish->tv_sec == 0 && finish->tv_usec == 0)
00091                 return -1;
00092         if (start->tv_sec == 0 && start->tv_usec == 0)
00093                 return -1;
00094 
00095         tvdiff->tv_sec = finish->tv_sec - start->tv_sec;
00096         tvdiff->tv_usec = finish->tv_usec - start->tv_usec;
00097         if (tvdiff->tv_usec < 0) {
00098                 --tvdiff->tv_sec;
00099                 tvdiff->tv_usec += 1000000L;
00100         }
00101 
00102         return 0;
00103 }
00104 
00105 /**
00106  * @brief
00107  * Prints out the command history.
00108  *
00109  * USAGE:
00110  *        procname history [-delays] [-outfile filename]
00111  */
00112 int
00113 bu_cmdhist_history(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
00114 {
00115         struct bu_cmdhist_obj *chop = (struct  bu_cmdhist_obj *)clientData;
00116         FILE *fp;
00117         int with_delays = 0;
00118         struct bu_cmdhist *hp, *hp_prev;
00119         struct bu_vls str;
00120         struct timeval tvdiff;
00121 
00122         if (argc < 2 || 5 < argc) {
00123                 struct bu_vls vls;
00124 
00125                 bu_vls_init(&vls);
00126                 bu_vls_printf(&vls, "help history");
00127                 Tcl_Eval(interp, bu_vls_addr(&vls));
00128                 bu_vls_free(&vls);
00129                 return TCL_ERROR;
00130         }
00131 
00132         fp = NULL;
00133         while (argc >= 3)  {
00134                 if (strcmp(argv[2], "-delays") == 0)
00135                         with_delays = 1;
00136                 else if( strcmp(argv[2], "-outfile") == 0 ) {
00137                         if (fp != NULL) {
00138                                 fclose(fp);
00139                                 Tcl_AppendResult(interp, "history: -outfile option given more than once\n",
00140                                                  (char *)NULL);
00141                                 return TCL_ERROR;
00142                         } else if (argc < 4 || strcmp(argv[3], "-delays") == 0) {
00143                                 Tcl_AppendResult(interp, "history: I need a file name\n", (char *)NULL);
00144                                 return TCL_ERROR;
00145                         } else {
00146                                 fp = fopen( argv[3], "a+" );
00147                                 if (fp == NULL) {
00148                                         Tcl_AppendResult(interp, "history: error opening file", (char *)NULL);
00149                                         return TCL_ERROR;
00150                                 }
00151                                 --argc;
00152                                 ++argv;
00153                         }
00154                 } else {
00155                         Tcl_AppendResult(interp, "Invalid option ", argv[2], "\n", (char *)NULL);
00156                 }
00157                 --argc;
00158                 ++argv;
00159         }
00160 
00161         bu_vls_init(&str);
00162         for (BU_LIST_FOR(hp, bu_cmdhist, &chop->cho_head.l)) {
00163                 bu_vls_trunc(&str, 0);
00164                 hp_prev = BU_LIST_PREV(bu_cmdhist, &hp->l);
00165                 if (with_delays && BU_LIST_NOT_HEAD(hp_prev, &chop->cho_head.l)) {
00166                         if (timediff(&tvdiff, &(hp_prev->h_finish), &(hp->h_start)) >= 0)
00167                                 bu_vls_printf(&str, "delay %ld %ld\n", (long)tvdiff.tv_sec,
00168                                               (long)tvdiff.tv_usec);
00169 
00170                 }
00171 
00172                 if (hp->h_status == TCL_ERROR)
00173                         bu_vls_printf(&str, "# ");
00174                 bu_vls_vlscat(&str, &(hp->h_command));
00175 
00176                 if (fp != NULL)
00177                         bu_vls_fwrite(fp, &str);
00178                 else
00179                         Tcl_AppendResult(interp, bu_vls_addr(&str), (char *)NULL);
00180         }
00181 
00182         if (fp != NULL)
00183                 fclose(fp);
00184 
00185         return TCL_OK;
00186 }
00187 
00188 /**
00189  * @brief
00190  * Add a command to the history list.
00191  *
00192  * USAGE:
00193  *        procname add cmd
00194  */
00195 int
00196 bu_cmdhist_add(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
00197 {
00198         struct bu_cmdhist_obj *chop = (struct  bu_cmdhist_obj *)clientData;
00199         struct bu_vls vls;
00200         struct timeval zero;
00201 
00202         if(argc != 3){
00203                 bu_vls_init(&vls);
00204                 bu_vls_printf(&vls, "helplib cmdhist_add");
00205                 Tcl_Eval(interp, bu_vls_addr(&vls));
00206                 bu_vls_free(&vls);
00207                 return TCL_ERROR;
00208         }
00209 
00210         if (argv[2][0] == '\n' || argv[2][0] == '\0')
00211                 return TCL_OK;
00212 
00213         bu_vls_init(&vls);
00214         bu_vls_strcpy(&vls, argv[2]);
00215         if (argv[2][strlen(argv[2])-1] != '\n')
00216                 bu_vls_putc(&vls, '\n');
00217 
00218         zero.tv_sec = zero.tv_usec = 0L;
00219         history_record(chop, &vls, &zero, &zero, TCL_OK);
00220 
00221         bu_vls_free(&vls);
00222         return TCL_OK;
00223 }
00224 
00225 /**
00226  * Set the current command to the previous command.
00227  *
00228  * USAGE:
00229  *        procname prev
00230  */
00231 int
00232 bu_cmdhist_prev(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
00233 {
00234         struct bu_cmdhist_obj *chop = (struct  bu_cmdhist_obj *)clientData;
00235         struct bu_cmdhist *hp;
00236 
00237         if (argc != 2) {
00238                 struct bu_vls vls;
00239 
00240                 bu_vls_init(&vls);
00241                 bu_vls_printf(&vls, "helplib cmdhist_prev");
00242                 Tcl_Eval(interp, bu_vls_addr(&vls));
00243                 bu_vls_free(&vls);
00244                 return TCL_ERROR;
00245         }
00246 
00247         hp = BU_LIST_PLAST(bu_cmdhist, chop->cho_curr);
00248         if (BU_LIST_NOT_HEAD(hp, &chop->cho_head.l))
00249                 chop->cho_curr = hp;
00250 
00251         Tcl_AppendResult(interp, bu_vls_addr(&chop->cho_curr->h_command), (char *)NULL);
00252         return TCL_OK;
00253 }
00254 
00255 /**
00256  * Return the current command.
00257  *
00258  * USAGE:
00259  *        procname curr
00260  */
00261 int
00262 bu_cmdhist_curr(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
00263 {
00264         struct bu_cmdhist_obj *chop = (struct  bu_cmdhist_obj *)clientData;
00265 
00266         if (argc != 2) {
00267                 struct bu_vls vls;
00268 
00269                 bu_vls_init(&vls);
00270                 bu_vls_printf(&vls, "helplib cmdhist_curr");
00271                 Tcl_Eval(interp, bu_vls_addr(&vls));
00272                 bu_vls_free(&vls);
00273                 return TCL_ERROR;
00274         }
00275 
00276         if (BU_LIST_NOT_HEAD(chop->cho_curr, &chop->cho_head.l))
00277                 Tcl_AppendResult(interp, bu_vls_addr(&chop->cho_curr->h_command), (char *)NULL);
00278 
00279         return TCL_OK;
00280 }
00281 
00282 /**
00283  * Set the current command to the next command.
00284  *
00285  * USAGE:
00286  *        procname next
00287  */
00288 int
00289 bu_cmdhist_next(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
00290 {
00291         struct bu_cmdhist_obj *chop = (struct  bu_cmdhist_obj *)clientData;
00292 
00293         if (argc != 2) {
00294                 struct bu_vls vls;
00295 
00296                 bu_vls_init(&vls);
00297                 bu_vls_printf(&vls, "helplib cmdhist_next");
00298                 Tcl_Eval(interp, bu_vls_addr(&vls));
00299                 bu_vls_free(&vls);
00300                 return TCL_ERROR;
00301         }
00302 
00303         if (BU_LIST_IS_HEAD(chop->cho_curr, &chop->cho_head.l))
00304                 return TCL_ERROR;
00305 
00306         chop->cho_curr = BU_LIST_PNEXT(bu_cmdhist, chop->cho_curr);
00307         if (BU_LIST_IS_HEAD(chop->cho_curr, &chop->cho_head.l))
00308                 return TCL_ERROR;
00309 
00310         Tcl_AppendResult(interp, bu_vls_addr(&chop->cho_curr->h_command), (char *)NULL);
00311         return TCL_OK;
00312 }
00313 
00314 #if 0
00315 /**
00316  *      F _ D E L A Y
00317  *
00318  *      Uses select to delay for the specified amount of seconds and
00319  *        microseconds.
00320  */
00321 
00322 int
00323 f_delay(clientData, interp, argc, argv)
00324      ClientData clientData;
00325      Tcl_Interp *interp;
00326      int argc;
00327      char **argv;
00328 {
00329         struct timeval tv;
00330 
00331         if(argc < 3 || 3 < argc){
00332                 struct bu_vls vls;
00333 
00334                 bu_vls_init(&vls);
00335                 bu_vls_printf(&vls, "help delay");
00336                 Tcl_Eval(interp, bu_vls_addr(&vls));
00337                 bu_vls_free(&vls);
00338                 return TCL_ERROR;
00339         }
00340 
00341         tv.tv_sec = atoi(argv[1]);
00342         tv.tv_usec = atoi(argv[2]);
00343         select(0, NULL, NULL, NULL, &tv);
00344 
00345         return TCL_OK;
00346 }
00347 #endif
00348 /*@}*/
00349 /*
00350  * Local Variables:
00351  * mode: C
00352  * tab-width: 8
00353  * c-basic-offset: 4
00354  * indent-tabs-mode: t
00355  * End:
00356  * ex: shiftwidth=4 tabstop=8
00357  */

Generated on Mon Sep 18 01:24:47 2006 for BRL-CAD by  doxygen 1.4.6