/ src / hal / utils / halsh.c
halsh.c
  1  //    Copyright 2007-2013, various authors
  2  //
  3  //    This program is free software; you can redistribute it and/or modify
  4  //    it under the terms of the GNU General Public License as published by
  5  //    the Free Software Foundation; either version 2 of the License, or
  6  //    (at your option) any later version.
  7  //
  8  //    This program is distributed in the hope that it will be useful,
  9  //    but WITHOUT ANY WARRANTY; without even the implied warranty of
 10  //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 11  //    GNU General Public License for more details.
 12  //
 13  //    You should have received a copy of the GNU General Public License
 14  //    along with this program; if not, write to the Free Software
 15  //    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 16  
 17  #include <string.h>
 18  #include <stdlib.h>
 19  #include <stdio.h>
 20  #include <tcl.h>
 21  #include "halcmd.h"
 22  
 23  Tcl_Interp *target_interp = NULL;
 24  static int pending_cr = 0;
 25  
 26  static void halError(Tcl_Interp *interp, int result) {
 27      // Usually, halcmd leaves a good string message via halcmd_error()
 28      // but just in case, fall back to using the result of the halcmd api call as
 29      // a negative errno value...
 30      if(!*Tcl_GetStringResult(interp))
 31  	Tcl_SetResult(interp, strerror(-result), TCL_VOLATILE);
 32  }
 33  
 34  static int refcount = 0;
 35  
 36  static void shutdown(void) {
 37      if(refcount > 0) {
 38          refcount --;
 39          if(refcount == 0) halcmd_shutdown();
 40      }
 41  }
 42  
 43  static int init() {
 44      int result = 0;
 45      if(refcount == 0) {
 46          result = halcmd_startup(0);
 47          atexit(shutdown);
 48      }
 49      if(result == 0) {
 50          refcount ++;
 51      }
 52      return result;
 53  }
 54  static void halExit(ClientData d) {
 55      shutdown();
 56  }
 57  
 58  static int halCmd(ClientData cd, Tcl_Interp *interp, int argc, const char **argv) {
 59      int result;
 60      Tcl_ResetResult(interp);
 61  
 62      if(argc < 2) {
 63          Tcl_AppendResult(interp,
 64                  "wrong # args: should be \"", argv[0], " command ...\"", NULL);
 65          return TCL_ERROR;
 66      }
 67  
 68      if(strcmp(argv[1], "--commands") == 0)
 69      {
 70          int i;
 71          Tcl_ResetResult(interp);
 72          for(i=0; i<halcmd_ncommands; i++)
 73              Tcl_AppendElement(interp, halcmd_commands[i].name);
 74          return TCL_OK;
 75      }
 76  
 77      target_interp = interp;
 78      pending_cr = 0;
 79      result = halcmd_parse_cmd((char **)argv+1);
 80      target_interp = NULL;
 81  
 82      if(result == 0) return TCL_OK;
 83      halError(interp, result);
 84      return TCL_ERROR;
 85  }
 86  
 87  int Hal_Init(Tcl_Interp *interp) {
 88      int result = init();
 89      if(result < 0) {
 90  	Tcl_ResetResult(interp);
 91  	halError(interp, result);
 92  	return TCL_ERROR;
 93      }
 94  
 95      if (Tcl_InitStubs(interp, "8.1", 0) == NULL)
 96      {
 97          return TCL_ERROR;
 98      }
 99  
100      Tcl_CreateCommand(interp, "hal", halCmd, 0, halExit);
101  
102      Tcl_PkgProvide(interp, "Hal", "1.0");
103      return TCL_OK;
104  }
105  
106  #ifndef BUFFERLEN
107  #define BUFFERLEN 1024
108  #endif
109  
110  void halcmd_output(const char *format, ...) {
111      char buf[BUFFERLEN + 1];
112      va_list ap;
113      int len;
114  
115      va_start(ap, format);
116      vsnprintf(buf, BUFFERLEN, format, ap);
117      va_end(ap);
118  
119      if(pending_cr) 
120  	Tcl_AppendResult(target_interp, "\n", NULL);
121      len = strlen(buf);
122      if(buf[len-1] == '\n') {
123  	buf[len-1] = 0;
124  	pending_cr = 1;
125      } else {
126  	pending_cr = 0;
127      }
128      Tcl_AppendResult(target_interp, buf, NULL);
129  }
130  
131  void halcmd_error(const char *format, ...) {
132      char buf[BUFFERLEN + 1];
133      va_list ap;
134      int len;
135  
136      va_start(ap, format);
137      vsnprintf(buf, BUFFERLEN, format, ap);
138      va_end(ap);
139  
140      if(pending_cr) 
141  	Tcl_AppendResult(target_interp, "\n", NULL);
142      len = strlen(buf);
143      if(buf[len-1] == '\n') {
144  	buf[len-1] = 0;
145  	pending_cr = 1;
146      } else {
147  	pending_cr = 0;
148      }
149      Tcl_AppendResult(target_interp, buf, NULL);
150  }
151  
152  void halcmd_warning(const char *format, ...) {
153      char buf[BUFFERLEN + 1];
154      va_list ap;
155      int len;
156  
157      va_start(ap, format);
158      vsnprintf(buf, BUFFERLEN, format, ap);
159      va_end(ap);
160  
161      if(pending_cr) 
162  	Tcl_AppendResult(target_interp, "\n", NULL);
163      len = strlen(buf);
164      if(buf[len-1] == '\n') {
165  	buf[len-1] = 0;
166  	pending_cr = 1;
167      } else {
168  	pending_cr = 0;
169      }
170      Tcl_AppendResult(target_interp, buf, NULL);
171  }
172  
173  void halcmd_info(const char *format, ...) {
174      char buf[BUFFERLEN + 1];
175      va_list ap;
176      int len;
177  
178      va_start(ap, format);
179      vsnprintf(buf, BUFFERLEN, format, ap);
180      va_end(ap);
181  
182      if(pending_cr) 
183  	Tcl_AppendResult(target_interp, "\n", NULL);
184      len = strlen(buf);
185      if(buf[len-1] == '\n') {
186  	buf[len-1] = 0;
187  	pending_cr = 1;
188      } else {
189  	pending_cr = 0;
190      }
191      Tcl_AppendResult(target_interp, buf, NULL);
192  }
193