1 /* proc.h Copyright (C) 2010 Codemist Ltd */ 2 3 #ifndef header_proc_h 4 #define header_proc_h 1 5 6 7 8 /************************************************************************** 9 * Copyright (C) 2010, Codemist Ltd. A C Norman * 10 * * 11 * Redistribution and use in source and binary forms, with or without * 12 * modification, are permitted provided that the following conditions are * 13 * met: * 14 * * 15 * * Redistributions of source code must retain the relevant * 16 * copyright notice, this list of conditions and the following * 17 * disclaimer. * 18 * * Redistributions in binary form must reproduce the above * 19 * copyright notice, this list of conditions and the following * 20 * disclaimer in the documentation and/or other materials provided * 21 * with the distribution. * 22 * * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * 26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * 27 * COPYRIGHT OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * 30 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * 31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * 32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * 33 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 34 * DAMAGE. * 35 *************************************************************************/ 36 37 /* Signature: 545be01d 22-Aug-2010 */ 38 39 40 /* 41 * Definitions useful for driving the procedural interface to Reduce... 42 */ 43 44 /* 45 * These types are used for callback functions used to send and receive 46 * characters. 47 */ 48 49 typedef int character_reader(void); 50 typedef int character_writer(int); 51 52 /* 53 * When a handle on an expression is returned to the user this is the 54 * type it has. The type should be treated as opaque, please. 55 */ 56 57 typedef void *PROC_handle; 58 59 /* 60 * Before trying to do anything at all you must call cslstart. This will 61 * allocate memory, load an initial heap image etc etc. The argc and argv 62 * passed here are as per normal C startup. The key issue here is how 63 * Reduce will find the file "reduce.img" that it needs to load. There are 64 * two plausible ways you can achieve this. 65 * (a) argv[0] should contain a (for choice) fully rooted path as in 66 * /usr/local/bin/reduce 67 * or c:\my-reduce\binaries\reduce.exe 68 * In that case the name of the supposed execitable has ".img" tagged 69 * onto it, so the image is expected to be at say /usr/local/bin/reduce.img 70 * If the application name is the name of a symbolic link then the 71 * image file is looked for in the dircetory that the link points to. 72 * (b) You can put "-i" "/path/to/reduce.img" in two consecutive entries 73 * in argv to give an explicit indication of where the image file 74 * is to be found. This should override any attempt to look via 75 * argv[0]. 76 * Most users should not need to provide any further options, but options 77 * are decoded just as for the ordinary version of the system. 78 * 79 * Any textual output generated during system-started is sent, character 80 * by character, via the callback function. Eg pass an option "-v" in 81 * argv and see a big banner. 82 */ 83 84 extern void cslstart(int argc, char *argv[], character_writer *wr); 85 86 /* 87 * At the end of a run please call cslfinish to close down everything 88 * in a reasonably orderly manner and release memory. I should cautiously 89 * note that the system will have some memory leaks so cslfinish will 90 * not return EVERYTHING that has been allocated - if this worries you 91 * please search for and correct the defects. Again the callback function 92 * is used to process any output generated during close-down. 93 */ 94 95 extern int cslfinish(character_writer *wr); 96 97 /* 98 * As a general-purpose escape it is possible to get a Lisp function 99 * (with no arguments) called. This function does that re-binding 100 * what would otherwise be terminal input and output to the two 101 * callback functions. By writing your own custom Lisp function and then 102 * calling it this way you get almost ultimate flexibility, if not 103 * convenience! For used of the Reduce algebra system I hope that the 104 * suite of more specialised functions listed later on will prove 105 * easier to use. 106 */ 107 108 extern int execute_lisp_function(char *fname, 109 character_reader *r, 110 character_writer *w); 111 112 113 /* 114 * The next collection of functions provide for interaction with the 115 * Reduce algebra system using a model based on a Reverse Polish 116 * Calculator. You use RPN-style calls to build a fragment of parse 117 * tree and can them as Reduce to "simplify" it. Having simplified it 118 * you can ask for a simple prefix-form of the result to be generated and 119 * returned, and there are functions for traversing that. 120 */ 121 122 /* 123 * Example: 124 * Task: differentiate (x+1)^2 with respect to x 125 * Method: clear_stack(); 126 * push_symbol("x"); 127 * push_small_integer(1); 128 * make_function_call("plus",2); function plus has 2 arguments. 129 * push_small_integer(2); 130 * make_function_call("expt",2); 131 * push_symbol("x"); 132 * make_function_call("df",2); "df" is for differentiate. 133 * To use this you need to learn 134 * the named Reduce uses for all 135 * relevant operations. 136 * simplify(); up until now the form built 137 * has been just the prefix form 138 * (expt (plus x 1) 2). 139 * dup(); because save will pop the stack 140 * save(1); save in "memory number 1". 141 * make_printable(); the simplified form is in 142 * a Reduce internal representation, 143 * so this restores it to simple 144 * prefix form. 145 * p = get_value(); 146 * now p holds a handle on the result, and it can be traversed 147 * using functions atom(), first(), rest() and functions that extract the 148 * name of a symbol or the value of an integer. You should assume that the 149 * handle becomes invalid as soon as you call one of the other functions. 150 * this is because they can all trigger garbage collection and that can 151 * relocate data. 152 * The functions used to build expressions all return zero on success or 153 * an error-code otherwise. In the initial release the error-codes are 154 * not documented other than via reading the source files. Furthermore the 155 * consequence of a calculation seeking input or generating output is not 156 * well sorted. 157 */ 158 159 160 /* 161 * After having called cslstart() you can set the I/O callback functions 162 * using this. If you set one or both to NULL this indicates use of 163 * stdin/stdout as per usual rather than an callback, otherwise whenever 164 * anybody wants to read or write they use these procedures. It is then 165 * your responsibility to cope with whatever text gets exchanged! 166 */ 167 168 extern int PROC_set_callbacks(character_reader *r, 169 character_writer *w); 170 171 /* 172 * Load a Reduce "package". 173 */ 174 175 int PROC_load_package(char *name); 176 177 /* 178 * Set of clear a Reduce switch. As on "on expandlogs;" 179 * which you do via PROC_set_switch("expandlogs", 1); 180 * Use 0 to switch something off and 1 to switch it on. 181 */ 182 183 int PROC_set_switch(char *name, int val); 184 185 /* 186 * Set level of garbage collector noise. This might often be a bit irrelevant, 187 * but 188 * 0 no messages at all 189 * +1 messages whenever garbage collection happens 190 * +2 messages whenever a module of code is loaded 191 * +4 extra details in the garbage collector messages 192 * Note that if an ALWAYS_NOISY option (probably set as a side effect 193 * of the debugging command line option "-g") is in play then any 194 * call here has +1 and +2 forced active. 195 */ 196 197 int PROC_gc_messages(int n); 198 199 /* 200 * stack = nil; 201 */ 202 extern int PROC_clear_stack(); 203 204 /* 205 * stack = name . stack; 206 */ 207 208 extern int PROC_push_symbol(const char *name); 209 210 /* 211 * stack = the-string . stack; 212 */ 213 214 extern int PROC_push_string(const char *data); 215 216 /* 217 * stack = n . stack; 218 * Small integers may be up to 28-bits of (signed) data, while 219 * big integers can be almost any size and are denoted here by strings. 220 * Eg: PROC_push_small_integer(134217727); largest positive small num 221 * PROC_push_small_integer(-134217728); extreme negative case 222 * PROC_push_big_integer("-12345678901234567890"); 223 */ 224 225 extern int PROC_push_small_integer(int32_t n); 226 227 extern int PROC_push_big_integer(const char *n); 228 229 extern int PROC_push_floating(double n); 230 231 /* 232 * Takes n items from the top of the stack and uses them as arguments 233 * for a function as specified by the name. Leaves the result on the 234 * top of the stack. Arguments will have been pushed with arg1 pushed 235 * first and the last argument pushed last. 236 */ 237 238 extern int PROC_make_function_call(const char *name, int n); 239 240 /* 241 * Save whatever is on top of the stack in memory location n. At present 242 * I provide 100 memory locations, whihc ar enumbered 0 to 99. 243 */ 244 245 extern int PROC_save(int n); 246 247 /* 248 * Push the contents of memory location n onto the stack. 249 */ 250 251 extern int PROC_load(int n); 252 253 /* 254 * Duplicate the top stack element. 255 */ 256 257 extern int PROC_dup(); 258 259 /* 260 * Discard the top stack element. 261 */ 262 263 extern int PROC_pop(); 264 265 /* 266 * The top item on the stack is replaced with what happens when Reduce 267 * is asked to "simplify" or "evaluate" it. The result can then be stored 268 * or combined with other items, but it will not in general be in a format 269 * directly convenient for use by humans. 270 */ 271 272 extern int PROC_simplify(); 273 274 /* 275 * Replace the top item on the stack with a version of the same expression 276 * in a reasonably simple prefix notation. 277 * This representation is NOT intended for re-input to any calculation - 278 * it is only intended for inspecial by the client code that is using Reduce 279 * via this interface. To that end it may in the future return big integers 280 * in a form where they have been converted to Lisp strings and may make 281 * other transformations that would hurt attempts to re-use the expression. 282 */ 283 284 extern int PROC_make_printable(); 285 286 /* 287 * Return a handle to the top item on the stack, and pop the stack. This 288 * will normally be called immediately after a call to PROC_make_printable. 289 * the stack is popped because I view the "printable" version as unsuitable 290 * for further use. 291 */ 292 293 extern PROC_handle PROC_get_value(); 294 295 /* 296 * The next few functions are predicates that may be applied to handles. 297 * An "atom" is any non-composite form. A fixnum is a small integer, and 298 * a symbol is a name. 299 */ 300 301 extern int PROC_atom(PROC_handle p); 302 extern int PROC_null(PROC_handle p); 303 extern int PROC_fixnum(PROC_handle p); 304 extern int PROC_floatnum(PROC_handle p); 305 extern int PROC_string(PROC_handle p); 306 extern int PROC_symbol(PROC_handle p); 307 308 /* 309 * If something is not an atom it will be a list, and the following two 310 * functions return the components of it. In general non-atomic items will 311 * be structured as 312 * (fname arg1 arg2 ...) 313 * with "well understood" function names "plus", "difference", "minus", 314 * "times", "quotient", "expt" being used to denote use of the main 315 * arithmetic connectives. A Lisp fanatic would have named the following 316 * two functions PROC_car and PROC_cdr! 317 */ 318 319 extern PROC_handle PROC_first(PROC_handle p); 320 extern PROC_handle PROC_rest(PROC_handle p); 321 322 /* 323 * If something is an atom then these make it possible to extract details 324 * of what it represents. In due course I may support floating point values 325 * and big numbers, but release 1 of those code concentrates on the basics. 326 */ 327 328 extern int32_t PROC_integer_value(PROC_handle p); 329 extern double PROC_floating_value(PROC_handle p); 330 extern const char *PROC_symbol_name(PROC_handle p); 331 extern const char *PROC_string_data(PROC_handle p); 332 333 /* 334 * I also provide some calls that support a sort of ultimate cop-out in 335 * that they maye it possible to call Lisp code directly rather than 336 * just invoking the Reduce simplifier. They also allow one to get back a 337 * raw Lisp result which will have had gensym-names solidified but which 338 * is otherwise unaltered. Note that the way this is achieved means that 339 * things will FAIL if the Lisp result were to be a cyclic structure! 340 */ 341 342 343 /* 344 * Replace the top item on the stack with whatever is obtained by using 345 * the Lisp EVAL operation on it. Note that this is not intended for 346 * casual use - if there is any functionality that you need PLEASE ask 347 * me to put in a cleaner abstraction to support it. 348 */ 349 350 extern int PROC_lisp_eval(); 351 352 /* 353 * Return a handle to the top item on the stack, and pop the stack. 354 * The value here will be a RAW LISP structure and NOT at all necessarily 355 * anything neat. 356 */ 357 358 extern PROC_handle PROC_get_raw_value(); 359 360 361 362 #ifndef __cplusplus 363 #ifdef USE_SIGALTSTACK 364 extern sigjmp_buf my_exit_buffer; 365 #else 366 extern jmp_buf my_exit_buffer; 367 #endif 368 #endif 369 extern volatile int my_return_code; 370 371 #endif /* header_proc_h */ 372 373 /* end of proc.h */ 374 375