r7061: initial property settings
[ctsim.git] / tools / ctsimtext.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          ctsimtext.cpp
5 **   Purpose:       Text mode shell for CTSim
6 **   Programmer:    Kevin Rosenberg
7 **   Date Started:  Jan 2001
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2000 Kevin Rosenberg
11 **
12 **  $Id$
13 **
14 **  This program is free software; you can redistribute it and/or modify
15 **  it under the terms of the GNU General Public License (version 2) as
16 **  published by the Free Software Foundation.
17 **
18 **  This program is distributed in the hope that it will be useful,
19 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 **  GNU General Public License for more details.
22 **
23 **  You should have received a copy of the GNU General Public License
24 **  along with this program; if not, write to the Free Software
25 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 ******************************************************************************/
27
28 #include "ct.h"
29
30 #ifdef HAVE_READLINE_H
31 extern "C" {
32 #include <readline.h>
33 #include <history.h>
34 };
35 #elif defined(HAVE_READLINE_READLINE_H)
36 extern "C" {
37 #include <readline/readline.h>
38 #include <readline/history.h>
39 };
40 #endif
41 #include <exception>
42
43 // Master shell for all command-line tools
44 // If called as ctsimtext, program will look to next token on command-line as the function name
45 // If linked to ctsimtext, but executed as another name, eg pjrec, then program will use that
46 // linked name as name of function.
47
48 static const char* const g_szIdStr = "$Id$";
49 static const char* const s_szProgramName = "ctsimtext";
50 static const char* const s_szProgramName2 = "ctsimtext.exe";
51 static const char* const s_szProgramName3 = "ctsimtext-lam";
52
53 extern int if1_main (int argc, char* const argv[]);
54 extern int if2_main (int argc, char* const argv[]);
55 extern int ifexport_main (int argc, char* const argv[]);
56 extern int ifinfo_main (int argc, char* const argv[]);
57 extern int phm2if_main (int argc, char* const argv[]);
58 extern int phm2pj_main (int argc, char* const argv[]);
59 extern int phm2helix_main (int argc, char* const argv[]);
60 extern int pjHinterp_main (int argc, char* const argv[]);
61 extern int pj2if_main (int argc, char* const argv[]);
62 extern int pjinfo_main (int argc, char* const argv[]);
63 extern int pjrec_main (int argc, char* const argv[]);
64 extern int linogram_main (int argc, char* const argv[]);
65
66 static int processCommand (int argc, char* const argv[]);
67 static void convertStringToArgcv (char* szLine, int* piArgc, char*** pppArgv);
68
69
70 void 
71 ctsimtext_usage (const char *program)
72 {
73   std::cout << "usage: " << fileBasename(program) << " ctsim-function-name ctstim-function-parameters...\n";
74   std::cout << "CTSim text shell";
75 #ifdef VERSION
76   std::cout << ", Version " <<VERSION;
77 #endif
78   std::cout << "\n\n";
79   std::cout << "  if1           Single image file conversion\n";
80   std::cout << "  if2           Dual image file conversions\n";
81   std::cout << "  ifexport      Export an imagefile to a graphics file\n";
82   std::cout << "  ifinfo        Image file information\n";
83   std::cout << "  pj2if         Convert an projection file into an imagefile\n";
84   std::cout << "  pjinfo        Projection file information\n";
85   std::cout << "  pjrec         Projection reconstruction\n";
86   std::cout << "  phm2if        Convert a geometric phantom into an imagefile\n";
87   std::cout << "  phm2pj        Take projections of a phantom object\n";
88   std::cout << "  phm2helix     Take projections of a phantom object\n";
89   std::cout << "  pjHinterp     Interpolate helical projections of a phantom object\n";
90   std::cout << "  linogram      Print linogram sampling\n";
91 }
92
93 void 
94 interactive_usage ()
95 {
96   std::cout << "usage: function-name parameters...\n";
97   std::cout << "Available functions:\n";
98   std::cout << "  ifexport      Export an imagefile to a graphics file\n";
99   std::cout << "  ifinfo        Image file information\n";
100   std::cout << "  if1           Single image file conversion\n";
101   std::cout << "  if2           Dual image file conversions\n";
102   std::cout << "  phm2if        Convert a geometric phantom into an imagefile\n";
103   std::cout << "  phm2pj        Take projections of a phantom object\n";
104   std::cout << "  phm2helix     Take projections of a phantom object\n";
105   std::cout << "  pjinfo        Projection file information\n";
106   std::cout << "  pj2if         Convert an projection file into an imagefile\n";
107   std::cout << "  pjHinterp     Interpolate helical projections of a phantom object\n";
108   std::cout << "  pjrec         Projection reconstruction\n";
109   std::cout << "  quit          Quits shell\n";
110   std::cout << "  linogram      Display linogram sampling\n";
111   std::cout << "All functions accept --help as parameter for online help\n\n";
112 }
113
114 static bool s_bInteractive = false;
115
116 int 
117 ctsimtext_main (int argc, char * argv[])
118 {
119   int iReturn = 0;  
120   
121   if (argc > 1 && (strcmp(s_szProgramName, fileBasename (argv[0])) == 0 || strcmp(s_szProgramName2, fileBasename (argv[0])) == 0 || strcmp(s_szProgramName3, fileBasename (argv[0])) == 0)) {
122     argv++;
123     argc--;
124     iReturn = processCommand (argc, argv);
125   } else if (argc >= 1 && ! (strcmp(s_szProgramName, fileBasename (argv[0])) == 0 || strcmp(s_szProgramName2, fileBasename (argv[0])) == 0 || strcmp(s_szProgramName3, fileBasename (argv[0])) == 0)) {
126     iReturn = processCommand (argc, argv);
127   } else {
128     s_bInteractive = true;
129     char szPrompt[] = "CTSim> ";
130     std::cout << "CTSim Text Shell";
131 #ifdef VERSION
132     std::cout << ", Version " << VERSION;
133 #endif
134     std::cout << " (Type \"quit\" to end)\n\n";
135     
136     while (1) {
137 #ifdef HAVE_READLINE
138       char* pszInputLine = readline (szPrompt);
139       if (! pszInputLine)
140         break;
141       if (*pszInputLine != EOS)
142         add_history (pszInputLine);
143       
144 #else  // DONT_HAVE_READLINE
145       
146       static const int s_MaxLineLength = 1024;
147       char* pszInputLine = new char [s_MaxLineLength+1];
148       std::cout << szPrompt;
149       std::cin.getline (pszInputLine, s_MaxLineLength);
150       
151 #ifdef DEBUG
152       std::cout << "#" << pszInputLine << "#\n";
153 #endif
154       
155       std::cout << std::flush;
156       std::cout << "\n";
157 #endif  // DONT_HAVE_READLINE
158       
159       if (strncasecmp (pszInputLine, "quit", 4) == 0) 
160         break;
161       
162       convertStringToArgcv (pszInputLine, &argc, &argv);
163 #ifdef DEBUG
164       for (int i = 0; i < argc; i++)
165         std::cout << "Token " << i << ": " << argv[i] << "\n";
166 #endif
167       iReturn = processCommand (argc, argv);
168       
169       delete pszInputLine;
170     }
171   }
172   
173   return iReturn;
174 }
175
176 static void
177 convertStringToArgcv (char* pszLine, int* piArgc, char*** pppArgv)
178 {
179   char* pCurrentPos = pszLine;
180   int nTokens = 0;
181   std::vector<char*> vecpszToken;
182   
183   // Process line
184   bool bInDoubleQuote = false;
185   bool bInSingleQuote = false;
186   bool bInToken = false;
187   
188   while (*pCurrentPos) {
189     if (isspace (*pCurrentPos)) {
190       if (! bInToken)
191         *pCurrentPos = 0;
192       else if (bInSingleQuote || bInDoubleQuote)
193         ;
194       else { // in non-quote token
195         *pCurrentPos = 0;
196         bInToken = false;
197       }
198     }
199     else if (*pCurrentPos == '\"') {
200       if (bInSingleQuote) {
201         bInSingleQuote = false;
202         *pCurrentPos = 0;
203       } else {
204         bInSingleQuote = true;
205         if (! bInToken) {
206           bInToken = true;
207           nTokens++;
208           vecpszToken.push_back (pCurrentPos+1);
209         }
210       }
211     } else if (*pCurrentPos == '\'') {
212       if (bInDoubleQuote) {
213         bInDoubleQuote = false;
214         *pCurrentPos = 0;
215       } else {
216         bInDoubleQuote = true;
217         if (! bInToken) {
218           bInToken = true;
219           nTokens++;
220           vecpszToken.push_back (pCurrentPos+1);
221         }
222       }
223     } else if (! bInToken) {   // nonwhite, non-quote character
224       bInToken = true;
225       nTokens++;
226       vecpszToken.push_back (pCurrentPos);
227     }
228     
229     pCurrentPos++;
230   }
231   
232   *piArgc = nTokens;
233   if (nTokens > 0) {
234     *pppArgv = new char* [nTokens];
235     for (unsigned int iToken = 0; iToken < vecpszToken.size(); iToken++)
236       (*pppArgv)[iToken] = vecpszToken[iToken];
237   } else
238     *pppArgv = NULL;
239 }
240
241 static int 
242 processCommand (int argc, char* const argv[])
243 {
244   if (argc < 1)
245     return 1;
246   
247   const char* const pszFunction = fileBasename (argv[0]);
248
249   try {  
250     if (strcasecmp (pszFunction, "if1") == 0)
251       return if1_main (argc, argv);
252     else if (strcasecmp (pszFunction, "if2") == 0)
253       return if2_main (argc, argv);
254     else if (strcasecmp (pszFunction, "ifexport") == 0)
255       return ifexport_main (argc, argv);
256     else if (strcasecmp (pszFunction, "ifinfo") == 0)
257       return ifinfo_main (argc, argv);
258     else if (strcasecmp (pszFunction, "phm2if") == 0)
259       return phm2if_main (argc, argv);
260     else if (strcasecmp (pszFunction, "phm2pj") == 0)
261       return phm2pj_main (argc, argv);
262     else if (strcasecmp (pszFunction, "phm2helix") == 0)
263       return phm2helix_main (argc, argv);
264     else if (strcasecmp (pszFunction, "pjHinterp") == 0)
265       return pjHinterp_main (argc, argv);
266     else if (strcasecmp (pszFunction, "pj2if") == 0)
267       return pj2if_main (argc, argv);
268     else if (strcasecmp (pszFunction, "pjinfo") == 0)
269       return pjinfo_main (argc, argv);
270     else if (strcasecmp (pszFunction, "pjrec") == 0)
271       return pjrec_main (argc, argv);
272     else if (strcasecmp (pszFunction, "linogram") == 0)
273       return linogram_main (argc, argv);
274     else {
275       std::cout << "Unknown function name: " << pszFunction << "\n";
276       if (s_bInteractive)
277         interactive_usage();
278       else
279         ctsimtext_usage (s_szProgramName);
280       return 1;
281     }
282   } catch (std::exception e) {
283     std::cerr << "Exception: " << e.what() << std::endl;
284   } catch (...) {
285     std::cerr << "Unknown exception caught\n";
286   }  
287
288   return 1;
289 }
290
291 int 
292 main (int argc, char* argv[])
293 {
294   int retval = 1;
295   
296   retval = ctsimtext_main(argc, argv);
297   
298   return retval;
299 }