diff options
| author | Mike Rowan | 1990-09-27 21:17:59 +0000 |
|---|---|---|
| committer | Mike Rowan | 1990-09-27 21:17:59 +0000 |
| commit | b70021f430514d779a4d0cd9577a4425683ad524 (patch) | |
| tree | fe633742eb58693d21f51fafef31237e4c8c01af /src | |
| parent | 24c5e809a90e0da4af29e8ba24946355619f516f (diff) | |
| download | emacs-b70021f430514d779a4d0cd9577a4425683ad524.tar.gz emacs-b70021f430514d779a4d0cd9577a4425683ad524.zip | |
Initial revision
Diffstat (limited to 'src')
| -rw-r--r-- | src/floatfns.c | 558 | ||||
| -rw-r--r-- | src/hftctl.c | 319 |
2 files changed, 877 insertions, 0 deletions
diff --git a/src/floatfns.c b/src/floatfns.c new file mode 100644 index 00000000000..1cf132d5f5c --- /dev/null +++ b/src/floatfns.c | |||
| @@ -0,0 +1,558 @@ | |||
| 1 | /* Primitive operations on floating point for GNU Emacs Lisp interpreter. | ||
| 2 | Copyright (C) 1988 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 1, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 19 | |||
| 20 | |||
| 21 | #include <signal.h> | ||
| 22 | |||
| 23 | #include "config.h" | ||
| 24 | #include "lisp.h" | ||
| 25 | |||
| 26 | Lisp_Object Qarith_error; | ||
| 27 | |||
| 28 | #ifdef LISP_FLOAT_TYPE | ||
| 29 | #include <math.h> | ||
| 30 | |||
| 31 | /* Nonzero while executing in floating point. | ||
| 32 | This tells float_error what to do. */ | ||
| 33 | |||
| 34 | static int in_float; | ||
| 35 | |||
| 36 | /* If an argument is out of range for a mathematical function, | ||
| 37 | that is detected with a signal. Here is the actual argument | ||
| 38 | value to use in the error message. */ | ||
| 39 | |||
| 40 | static Lisp_Object float_error_arg; | ||
| 41 | |||
| 42 | #define IN_FLOAT(d, num) \ | ||
| 43 | (in_float = 1, float_error_arg = num, (d), in_float = 0) | ||
| 44 | |||
| 45 | /* Extract a Lisp number as a `double', or signal an error. */ | ||
| 46 | |||
| 47 | double | ||
| 48 | extract_float (num) | ||
| 49 | Lisp_Object num; | ||
| 50 | { | ||
| 51 | CHECK_NUMBER_OR_FLOAT (num, 0); | ||
| 52 | |||
| 53 | if (XTYPE (num) == Lisp_Float) | ||
| 54 | return XFLOAT (num)->data; | ||
| 55 | return (double) XINT (num); | ||
| 56 | } | ||
| 57 | |||
| 58 | DEFUN ("acos", Facos, Sacos, 1, 1, 0, | ||
| 59 | "Return the inverse cosine of ARG.") | ||
| 60 | (num) | ||
| 61 | register Lisp_Object num; | ||
| 62 | { | ||
| 63 | double d = extract_float (num); | ||
| 64 | IN_FLOAT (d = acos (d), num); | ||
| 65 | return make_float (d); | ||
| 66 | } | ||
| 67 | |||
| 68 | DEFUN ("acosh", Facosh, Sacosh, 1, 1, 0, | ||
| 69 | "Return the inverse hyperbolic cosine of ARG.") | ||
| 70 | (num) | ||
| 71 | register Lisp_Object num; | ||
| 72 | { | ||
| 73 | double d = extract_float (num); | ||
| 74 | IN_FLOAT (d = acosh (d), num); | ||
| 75 | return make_float (d); | ||
| 76 | } | ||
| 77 | |||
| 78 | DEFUN ("asin", Fasin, Sasin, 1, 1, 0, | ||
| 79 | "Return the inverse sine of ARG.") | ||
| 80 | (num) | ||
| 81 | register Lisp_Object num; | ||
| 82 | { | ||
| 83 | double d = extract_float (num); | ||
| 84 | IN_FLOAT (d = asin (d), num); | ||
| 85 | return make_float (d); | ||
| 86 | } | ||
| 87 | |||
| 88 | DEFUN ("asinh", Fasinh, Sasinh, 1, 1, 0, | ||
| 89 | "Return the inverse hyperbolic sine of ARG.") | ||
| 90 | (num) | ||
| 91 | register Lisp_Object num; | ||
| 92 | { | ||
| 93 | double d = extract_float (num); | ||
| 94 | IN_FLOAT (d = asinh (d), num); | ||
| 95 | return make_float (d); | ||
| 96 | } | ||
| 97 | |||
| 98 | DEFUN ("atan", Fatan, Satan, 1, 1, 0, | ||
| 99 | "Return the inverse tangent of ARG.") | ||
| 100 | (num) | ||
| 101 | register Lisp_Object num; | ||
| 102 | { | ||
| 103 | double d = extract_float (num); | ||
| 104 | IN_FLOAT (d = atan (d), num); | ||
| 105 | return make_float (d); | ||
| 106 | } | ||
| 107 | |||
| 108 | DEFUN ("atanh", Fatanh, Satanh, 1, 1, 0, | ||
| 109 | "Return the inverse hyperbolic tangent of ARG.") | ||
| 110 | (num) | ||
| 111 | register Lisp_Object num; | ||
| 112 | { | ||
| 113 | double d = extract_float (num); | ||
| 114 | IN_FLOAT (d = atanh (d), num); | ||
| 115 | return make_float (d); | ||
| 116 | } | ||
| 117 | |||
| 118 | DEFUN ("bessel-j0", Fbessel_j0, Sbessel_j0, 1, 1, 0, | ||
| 119 | "Return the bessel function j0 of ARG.") | ||
| 120 | (num) | ||
| 121 | register Lisp_Object num; | ||
| 122 | { | ||
| 123 | double d = extract_float (num); | ||
| 124 | IN_FLOAT (d = j0 (d), num); | ||
| 125 | return make_float (d); | ||
| 126 | } | ||
| 127 | |||
| 128 | DEFUN ("bessel-j1", Fbessel_j1, Sbessel_j1, 1, 1, 0, | ||
| 129 | "Return the bessel function j1 of ARG.") | ||
| 130 | (num) | ||
| 131 | register Lisp_Object num; | ||
| 132 | { | ||
| 133 | double d = extract_float (num); | ||
| 134 | IN_FLOAT (d = j1 (d), num); | ||
| 135 | return make_float (d); | ||
| 136 | } | ||
| 137 | |||
| 138 | DEFUN ("bessel-jn", Fbessel_jn, Sbessel_jn, 2, 2, 0, | ||
| 139 | "Return the order N bessel function output jn of ARG.\n\ | ||
| 140 | The first arg (the order) is truncated to an integer.") | ||
| 141 | (num1, num2) | ||
| 142 | register Lisp_Object num1, num2; | ||
| 143 | { | ||
| 144 | int i1 = extract_float (num1); | ||
| 145 | double f2 = extract_float (num2); | ||
| 146 | |||
| 147 | IN_FLOAT (f2 = jn (i1, f2), num1); | ||
| 148 | return make_float (f2); | ||
| 149 | } | ||
| 150 | |||
| 151 | DEFUN ("bessel-y0", Fbessel_y0, Sbessel_y0, 1, 1, 0, | ||
| 152 | "Return the bessel function y0 of ARG.") | ||
| 153 | (num) | ||
| 154 | register Lisp_Object num; | ||
| 155 | { | ||
| 156 | double d = extract_float (num); | ||
| 157 | IN_FLOAT (d = y0 (d), num); | ||
| 158 | return make_float (d); | ||
| 159 | } | ||
| 160 | |||
| 161 | DEFUN ("bessel-y1", Fbessel_y1, Sbessel_y1, 1, 1, 0, | ||
| 162 | "Return the bessel function y1 of ARG.") | ||
| 163 | (num) | ||
| 164 | register Lisp_Object num; | ||
| 165 | { | ||
| 166 | double d = extract_float (num); | ||
| 167 | IN_FLOAT (d = y1 (d), num); | ||
| 168 | return make_float (d); | ||
| 169 | } | ||
| 170 | |||
| 171 | DEFUN ("bessel-yn", Fbessel_yn, Sbessel_yn, 2, 2, 0, | ||
| 172 | "Return the order N bessel function output yn of ARG.\n\ | ||
| 173 | The first arg (the order) is truncated to an integer.") | ||
| 174 | (num1, num2) | ||
| 175 | register Lisp_Object num1, num2; | ||
| 176 | { | ||
| 177 | int i1 = extract_float (num1); | ||
| 178 | double f2 = extract_float (num2); | ||
| 179 | |||
| 180 | IN_FLOAT (f2 = yn (i1, f2), num1); | ||
| 181 | return make_float (f2); | ||
| 182 | } | ||
| 183 | |||
| 184 | DEFUN ("cube-root", Fcube_root, Scube_root, 1, 1, 0, | ||
| 185 | "Return the cube root of ARG.") | ||
| 186 | (num) | ||
| 187 | register Lisp_Object num; | ||
| 188 | { | ||
| 189 | double d = extract_float (num); | ||
| 190 | IN_FLOAT (d = cbrt (d), num); | ||
| 191 | return make_float (d); | ||
| 192 | } | ||
| 193 | |||
| 194 | DEFUN ("cos", Fcos, Scos, 1, 1, 0, | ||
| 195 | "Return the cosine of ARG.") | ||
| 196 | (num) | ||
| 197 | register Lisp_Object num; | ||
| 198 | { | ||
| 199 | double d = extract_float (num); | ||
| 200 | IN_FLOAT (d = cos (d), num); | ||
| 201 | return make_float (d); | ||
| 202 | } | ||
| 203 | |||
| 204 | DEFUN ("cosh", Fcosh, Scosh, 1, 1, 0, | ||
| 205 | "Return the hyperbolic cosine of ARG.") | ||
| 206 | (num) | ||
| 207 | register Lisp_Object num; | ||
| 208 | { | ||
| 209 | double d = extract_float (num); | ||
| 210 | IN_FLOAT (d = cosh (d), num); | ||
| 211 | return make_float (d); | ||
| 212 | } | ||
| 213 | |||
| 214 | DEFUN ("erf", Ferf, Serf, 1, 1, 0, | ||
| 215 | "Return the mathematical error function of ARG.") | ||
| 216 | (num) | ||
| 217 | register Lisp_Object num; | ||
| 218 | { | ||
| 219 | double d = extract_float (num); | ||
| 220 | IN_FLOAT (d = erf (d), num); | ||
| 221 | return make_float (d); | ||
| 222 | } | ||
| 223 | |||
| 224 | DEFUN ("erfc", Ferfc, Serfc, 1, 1, 0, | ||
| 225 | "Return the complementary error function of ARG.") | ||
| 226 | (num) | ||
| 227 | register Lisp_Object num; | ||
| 228 | { | ||
| 229 | double d = extract_float (num); | ||
| 230 | IN_FLOAT (d = erfc (d), num); | ||
| 231 | return make_float (d); | ||
| 232 | } | ||
| 233 | |||
| 234 | DEFUN ("exp", Fexp, Sexp, 1, 1, 0, | ||
| 235 | "Return the exponential base e of ARG.") | ||
| 236 | (num) | ||
| 237 | register Lisp_Object num; | ||
| 238 | { | ||
| 239 | double d = extract_float (num); | ||
| 240 | IN_FLOAT (d = exp (d), num); | ||
| 241 | return make_float (d); | ||
| 242 | } | ||
| 243 | |||
| 244 | DEFUN ("expm1", Fexpm1, Sexpm1, 1, 1, 0, | ||
| 245 | "Return the exp (x)-1 of ARG.") | ||
| 246 | (num) | ||
| 247 | register Lisp_Object num; | ||
| 248 | { | ||
| 249 | double d = extract_float (num); | ||
| 250 | IN_FLOAT (d = expm1 (d), num); | ||
| 251 | return make_float (d); | ||
| 252 | } | ||
| 253 | |||
| 254 | DEFUN ("log-gamma", Flog_gamma, Slog_gamma, 1, 1, 0, | ||
| 255 | "Return the log gamma of ARG.") | ||
| 256 | (num) | ||
| 257 | register Lisp_Object num; | ||
| 258 | { | ||
| 259 | double d = extract_float (num); | ||
| 260 | IN_FLOAT (d = lgamma (d), num); | ||
| 261 | return make_float (d); | ||
| 262 | } | ||
| 263 | |||
| 264 | DEFUN ("log", Flog, Slog, 1, 1, 0, | ||
| 265 | "Return the natural logarithm of ARG.") | ||
| 266 | (num) | ||
| 267 | register Lisp_Object num; | ||
| 268 | { | ||
| 269 | double d = extract_float (num); | ||
| 270 | IN_FLOAT (d = log (d), num); | ||
| 271 | return make_float (d); | ||
| 272 | } | ||
| 273 | |||
| 274 | DEFUN ("log10", Flog10, Slog10, 1, 1, 0, | ||
| 275 | "Return the logarithm base 10 of ARG.") | ||
| 276 | (num) | ||
| 277 | register Lisp_Object num; | ||
| 278 | { | ||
| 279 | double d = extract_float (num); | ||
| 280 | IN_FLOAT (d = log10 (d), num); | ||
| 281 | return make_float (d); | ||
| 282 | } | ||
| 283 | |||
| 284 | DEFUN ("log1p", Flog1p, Slog1p, 1, 1, 0, | ||
| 285 | "Return the log (1+x) of ARG.") | ||
| 286 | (num) | ||
| 287 | register Lisp_Object num; | ||
| 288 | { | ||
| 289 | double d = extract_float (num); | ||
| 290 | IN_FLOAT (d = log1p (d), num); | ||
| 291 | return make_float (d); | ||
| 292 | } | ||
| 293 | |||
| 294 | DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, | ||
| 295 | "Return the exponential x ** y.") | ||
| 296 | (num1, num2) | ||
| 297 | register Lisp_Object num1, num2; | ||
| 298 | { | ||
| 299 | double f1, f2; | ||
| 300 | |||
| 301 | CHECK_NUMBER_OR_FLOAT (num1, 0); | ||
| 302 | CHECK_NUMBER_OR_FLOAT (num2, 0); | ||
| 303 | if ((XTYPE (num1) == Lisp_Int) && /* common lisp spec */ | ||
| 304 | (XTYPE (num2) == Lisp_Int)) /* don't promote, if both are ints */ | ||
| 305 | { /* this can be improved by pre-calculating */ | ||
| 306 | int acc, x, y; /* some binary powers of x then acumulating */ | ||
| 307 | /* these, therby saving some time. -wsr */ | ||
| 308 | x = XINT (num1); | ||
| 309 | y = XINT (num2); | ||
| 310 | acc = 1; | ||
| 311 | |||
| 312 | if (y < 0) | ||
| 313 | { | ||
| 314 | for (; y < 0; y++) | ||
| 315 | acc /= x; | ||
| 316 | } | ||
| 317 | else | ||
| 318 | { | ||
| 319 | for (; y > 0; y--) | ||
| 320 | acc *= x; | ||
| 321 | } | ||
| 322 | return XSET (x, Lisp_Int, acc); | ||
| 323 | } | ||
| 324 | f1 = (XTYPE (num1) == Lisp_Float) ? XFLOAT (num1)->data : XINT (num1); | ||
| 325 | f2 = (XTYPE (num2) == Lisp_Float) ? XFLOAT (num2)->data : XINT (num2); | ||
| 326 | IN_FLOAT (f1 = pow (f1, f2), num1); | ||
| 327 | return make_float (f1); | ||
| 328 | } | ||
| 329 | |||
| 330 | DEFUN ("sin", Fsin, Ssin, 1, 1, 0, | ||
| 331 | "Return the sine of ARG.") | ||
| 332 | (num) | ||
| 333 | register Lisp_Object num; | ||
| 334 | { | ||
| 335 | double d = extract_float (num); | ||
| 336 | IN_FLOAT (d = sin (d), num); | ||
| 337 | return make_float (d); | ||
| 338 | } | ||
| 339 | |||
| 340 | DEFUN ("sinh", Fsinh, Ssinh, 1, 1, 0, | ||
| 341 | "Return the hyperbolic sine of ARG.") | ||
| 342 | (num) | ||
| 343 | register Lisp_Object num; | ||
| 344 | { | ||
| 345 | double d = extract_float (num); | ||
| 346 | IN_FLOAT (d = sinh (d), num); | ||
| 347 | return make_float (d); | ||
| 348 | } | ||
| 349 | |||
| 350 | DEFUN ("sqrt", Fsqrt, Ssqrt, 1, 1, 0, | ||
| 351 | "Return the square root of ARG.") | ||
| 352 | (num) | ||
| 353 | register Lisp_Object num; | ||
| 354 | { | ||
| 355 | double d = extract_float (num); | ||
| 356 | IN_FLOAT (d = sqrt (d), num); | ||
| 357 | return make_float (d); | ||
| 358 | } | ||
| 359 | |||
| 360 | DEFUN ("tan", Ftan, Stan, 1, 1, 0, | ||
| 361 | "Return the tangent of ARG.") | ||
| 362 | (num) | ||
| 363 | register Lisp_Object num; | ||
| 364 | { | ||
| 365 | double d = extract_float (num); | ||
| 366 | IN_FLOAT (d = tan (d), num); | ||
| 367 | return make_float (d); | ||
| 368 | } | ||
| 369 | |||
| 370 | DEFUN ("tanh", Ftanh, Stanh, 1, 1, 0, | ||
| 371 | "Return the hyperbolic tangent of ARG.") | ||
| 372 | (num) | ||
| 373 | register Lisp_Object num; | ||
| 374 | { | ||
| 375 | double d = extract_float (num); | ||
| 376 | IN_FLOAT (d = tanh (d), num); | ||
| 377 | return make_float (d); | ||
| 378 | } | ||
| 379 | |||
| 380 | DEFUN ("abs", Fabs, Sabs, 1, 1, 0, | ||
| 381 | "Return the absolute value of ARG.") | ||
| 382 | (num) | ||
| 383 | register Lisp_Object num; | ||
| 384 | { | ||
| 385 | CHECK_NUMBER_OR_FLOAT (num, 0); | ||
| 386 | |||
| 387 | if (XTYPE (num) == Lisp_Float) | ||
| 388 | IN_FLOAT (num = make_float (fabs (XFLOAT (num)->data)), num); | ||
| 389 | else if (XINT (num) < 0) | ||
| 390 | XSETINT (num, - XFASTINT (num)); | ||
| 391 | |||
| 392 | return num; | ||
| 393 | } | ||
| 394 | |||
| 395 | DEFUN ("float", Ffloat, Sfloat, 1, 1, 0, | ||
| 396 | "Return the floating point number equal to ARG.") | ||
| 397 | (num) | ||
| 398 | register Lisp_Object num; | ||
| 399 | { | ||
| 400 | CHECK_NUMBER_OR_FLOAT (num, 0); | ||
| 401 | |||
| 402 | if (XTYPE (num) == Lisp_Int) | ||
| 403 | return make_float ((double) XINT (num)); | ||
| 404 | else /* give 'em the same float back */ | ||
| 405 | return num; | ||
| 406 | } | ||
| 407 | |||
| 408 | DEFUN ("logb", Flogb, Slogb, 1, 1, 0, | ||
| 409 | "Returns the integer that is the base 2 log of ARG.\n\ | ||
| 410 | This is the same as the exponent of a float.") | ||
| 411 | (num) | ||
| 412 | Lisp_Object num; | ||
| 413 | { | ||
| 414 | Lisp_Object val; | ||
| 415 | double f; | ||
| 416 | |||
| 417 | CHECK_NUMBER_OR_FLOAT (num, 0); | ||
| 418 | f = (XTYPE (num) == Lisp_Float) ? XFLOAT (num)->data : XINT (num); | ||
| 419 | IN_FLOAT (val = logb (f), num); | ||
| 420 | XSET (val, Lisp_Int, val); | ||
| 421 | return val; | ||
| 422 | } | ||
| 423 | |||
| 424 | /* the rounding functions */ | ||
| 425 | |||
| 426 | DEFUN ("ceiling", Fceiling, Sceiling, 1, 1, 0, | ||
| 427 | "Return the smallest integer no less than ARG. (Round toward +inf.)") | ||
| 428 | (num) | ||
| 429 | register Lisp_Object num; | ||
| 430 | { | ||
| 431 | CHECK_NUMBER_OR_FLOAT (num, 0); | ||
| 432 | |||
| 433 | if (XTYPE (num) == Lisp_Float) | ||
| 434 | IN_FLOAT (XSET (num, Lisp_Int, ceil (XFLOAT (num)->data)), num); | ||
| 435 | |||
| 436 | return num; | ||
| 437 | } | ||
| 438 | |||
| 439 | DEFUN ("floor", Ffloor, Sfloor, 1, 1, 0, | ||
| 440 | "Return the largest integer no greater than ARG. (Round towards -inf.)") | ||
| 441 | (num) | ||
| 442 | register Lisp_Object num; | ||
| 443 | { | ||
| 444 | CHECK_NUMBER_OR_FLOAT (num, 0); | ||
| 445 | |||
| 446 | if (XTYPE (num) == Lisp_Float) | ||
| 447 | IN_FLOAT (XSET (num, Lisp_Int, floor (XFLOAT (num)->data)), num); | ||
| 448 | |||
| 449 | return num; | ||
| 450 | } | ||
| 451 | |||
| 452 | DEFUN ("round", Fround, Sround, 1, 1, 0, | ||
| 453 | "Return the nearest integer to ARG.") | ||
| 454 | (num) | ||
| 455 | register Lisp_Object num; | ||
| 456 | { | ||
| 457 | CHECK_NUMBER_OR_FLOAT (num, 0); | ||
| 458 | |||
| 459 | if (XTYPE (num) == Lisp_Float) | ||
| 460 | IN_FLOAT (XSET (num, Lisp_Int, rint (XFLOAT (num)->data)), num); | ||
| 461 | |||
| 462 | return num; | ||
| 463 | } | ||
| 464 | |||
| 465 | DEFUN ("truncate", Ftruncate, Struncate, 1, 1, 0, | ||
| 466 | "Truncate a floating point number to an int.\n\ | ||
| 467 | Rounds the value toward zero.") | ||
| 468 | (num) | ||
| 469 | register Lisp_Object num; | ||
| 470 | { | ||
| 471 | CHECK_NUMBER_OR_FLOAT (num, 0); | ||
| 472 | |||
| 473 | if (XTYPE (num) == Lisp_Float) | ||
| 474 | XSET (num, Lisp_Int, (int) XFLOAT (num)->data); | ||
| 475 | |||
| 476 | return num; | ||
| 477 | } | ||
| 478 | |||
| 479 | #ifdef BSD | ||
| 480 | static | ||
| 481 | float_error (signo) | ||
| 482 | int signo; | ||
| 483 | { | ||
| 484 | if (! in_float) | ||
| 485 | fatal_error_signal (signo); | ||
| 486 | |||
| 487 | #ifdef BSD4_1 | ||
| 488 | sigrelse (SIGILL); | ||
| 489 | #else /* not BSD4_1 */ | ||
| 490 | sigsetmask (0); | ||
| 491 | #endif /* not BSD4_1 */ | ||
| 492 | |||
| 493 | in_float = 0; | ||
| 494 | |||
| 495 | Fsignal (Qarith_error, Fcons (float_error_arg, Qnil)); | ||
| 496 | } | ||
| 497 | |||
| 498 | /* Another idea was to replace the library function `infnan' | ||
| 499 | where SIGILL is signaled. */ | ||
| 500 | |||
| 501 | #endif /* BSD */ | ||
| 502 | |||
| 503 | init_floatfns () | ||
| 504 | { | ||
| 505 | signal (SIGILL, float_error); | ||
| 506 | in_float = 0; | ||
| 507 | } | ||
| 508 | |||
| 509 | syms_of_floatfns () | ||
| 510 | { | ||
| 511 | defsubr (&Sacos); | ||
| 512 | defsubr (&Sacosh); | ||
| 513 | defsubr (&Sasin); | ||
| 514 | defsubr (&Sasinh); | ||
| 515 | defsubr (&Satan); | ||
| 516 | defsubr (&Satanh); | ||
| 517 | defsubr (&Sbessel_y0); | ||
| 518 | defsubr (&Sbessel_y1); | ||
| 519 | defsubr (&Sbessel_yn); | ||
| 520 | defsubr (&Sbessel_j0); | ||
| 521 | defsubr (&Sbessel_j1); | ||
| 522 | defsubr (&Sbessel_jn); | ||
| 523 | defsubr (&Scube_root); | ||
| 524 | defsubr (&Scos); | ||
| 525 | defsubr (&Scosh); | ||
| 526 | defsubr (&Serf); | ||
| 527 | defsubr (&Serfc); | ||
| 528 | defsubr (&Sexp); | ||
| 529 | defsubr (&Sexpm1); | ||
| 530 | defsubr (&Slog_gamma); | ||
| 531 | defsubr (&Slog); | ||
| 532 | defsubr (&Slog10); | ||
| 533 | defsubr (&Slog1p); | ||
| 534 | defsubr (&Sexpt); | ||
| 535 | defsubr (&Ssin); | ||
| 536 | defsubr (&Ssinh); | ||
| 537 | defsubr (&Ssqrt); | ||
| 538 | defsubr (&Stan); | ||
| 539 | defsubr (&Stanh); | ||
| 540 | |||
| 541 | defsubr (&Sabs); | ||
| 542 | defsubr (&Sfloat); | ||
| 543 | defsubr (&Slogb); | ||
| 544 | defsubr (&Sceiling); | ||
| 545 | defsubr (&Sfloor); | ||
| 546 | defsubr (&Sround); | ||
| 547 | defsubr (&Struncate); | ||
| 548 | } | ||
| 549 | |||
| 550 | #else /* not LISP_FLOAT_TYPE */ | ||
| 551 | |||
| 552 | init_floatfns () | ||
| 553 | {} | ||
| 554 | |||
| 555 | syms_of_floatfns () | ||
| 556 | {} | ||
| 557 | |||
| 558 | #endif /* not LISP_FLOAT_TYPE */ | ||
diff --git a/src/hftctl.c b/src/hftctl.c new file mode 100644 index 00000000000..3e3788aa709 --- /dev/null +++ b/src/hftctl.c | |||
| @@ -0,0 +1,319 @@ | |||
| 1 | /* IBM has disclaimed copyright on this module. */ | ||
| 2 | |||
| 3 | /***************************************************************/ | ||
| 4 | /* */ | ||
| 5 | /* Function: hftctl */ | ||
| 6 | /* */ | ||
| 7 | /* Syntax: */ | ||
| 8 | /* #include <sys/ioctl.h> */ | ||
| 9 | /* #include <sys/hft.h> */ | ||
| 10 | /* */ | ||
| 11 | /* int hftctl(fildes, request, arg ) */ | ||
| 12 | /* int fildes, request ; */ | ||
| 13 | /* char *arg ; */ | ||
| 14 | /* */ | ||
| 15 | /* Description: */ | ||
| 16 | /* */ | ||
| 17 | /* Does the following: */ | ||
| 18 | /* 1. determines if fildes is pty */ | ||
| 19 | /* does normal ioctl it is not */ | ||
| 20 | /* 2. places fildes into raw mode */ | ||
| 21 | /* 3. converts ioctl arguments to datastream */ | ||
| 22 | /* 4. waits for 2 secs for acknowledgement before */ | ||
| 23 | /* timimg out. */ | ||
| 24 | /* 5. places response in callers buffer ( just like */ | ||
| 25 | /* ioctl. */ | ||
| 26 | /* 6. returns fildes to its original mode */ | ||
| 27 | /* */ | ||
| 28 | /* User of this program should review steps 1,4, and 3. */ | ||
| 29 | /* hftctl makes no check on the request type. It must be */ | ||
| 30 | /* a HFT ioctl that is supported remotely. */ | ||
| 31 | /* This program will use the SIGALRM and alarm(2). Any */ | ||
| 32 | /* Previous alarms are lost. */ | ||
| 33 | /* */ | ||
| 34 | /* Users of this program are free to modify it any way */ | ||
| 35 | /* they want. */ | ||
| 36 | /* */ | ||
| 37 | /* Return Value: */ | ||
| 38 | /* */ | ||
| 39 | /* If ioctl fails, a value of -1 is returned and errno */ | ||
| 40 | /* is set to indicate the error. */ | ||
| 41 | /* */ | ||
| 42 | /***************************************************************/ | ||
| 43 | |||
| 44 | |||
| 45 | #include <stdio.h> | ||
| 46 | #include <fcntl.h> | ||
| 47 | #include <errno.h> | ||
| 48 | #include <setjmp.h> | ||
| 49 | #include <sys/ioctl.h> | ||
| 50 | #include <sys/signal.h> | ||
| 51 | #include <sys/devinfo.h> | ||
| 52 | #include <termio.h> | ||
| 53 | #include <sys/hft.h> | ||
| 54 | #include <termios.h> | ||
| 55 | #include <sys/tty.h> | ||
| 56 | /* #include <sys/pty.h> */ | ||
| 57 | #define REMOTE 0x01 | ||
| 58 | |||
| 59 | #undef ioctl | ||
| 60 | static char SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90" ; | ||
| 61 | |||
| 62 | /*************** LOCAL DEFINES **********************************/ | ||
| 63 | |||
| 64 | typedef int (*FUNC)() ; /* pointer to a function */ | ||
| 65 | |||
| 66 | #define QDEV ((HFQPDEVCH<<8)|HFQPDEVCL) | ||
| 67 | #define QLOC ((HFQLOCCH<<8)|HFQLOCCL) | ||
| 68 | #define QPS ((HFQPRESCH<<8)|HFQPRESCL) | ||
| 69 | |||
| 70 | /*************** EXTERNAL / GLOBAL DATA AREA ********************/ | ||
| 71 | |||
| 72 | int hfqry() ; | ||
| 73 | int hfskbd() ; | ||
| 74 | char *malloc() ; | ||
| 75 | |||
| 76 | extern int errno ; | ||
| 77 | static jmp_buf hftenv ; | ||
| 78 | static int is_ack_vtd ; | ||
| 79 | static FUNC sav_alrm ; | ||
| 80 | static struct hfctlreq req = | ||
| 81 | { 0x1b,'[','x',0,0,0,21,HFCTLREQCH,HFCTLREQCL}; | ||
| 82 | static struct hfctlack ACK = | ||
| 83 | { 0x1b,'[','x',0,0,0,21,HFCTLACKCH,HFCTLACKCL}; | ||
| 84 | |||
| 85 | /* FUNC signal() ; */ | ||
| 86 | |||
| 87 | /*************** LOCAL MACROS ***********************************/ | ||
| 88 | |||
| 89 | #define HFTYPE(p) ((p->hf_typehi<<8)|(p->hf_typelo)) | ||
| 90 | |||
| 91 | #define BYTE4(p) ( (p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3] ) | ||
| 92 | |||
| 93 | /* read a buffer */ | ||
| 94 | #define RD_BUF(f,p,l) \ | ||
| 95 | while ( (l) ) \ | ||
| 96 | if ( ( j = read((f),(p),(l)) ) < 0 ) \ | ||
| 97 | if ( errno != EINTR ) return (-1) ; \ | ||
| 98 | else continue ; \ | ||
| 99 | else { (l)-=j ; (p)+=j ; } | ||
| 100 | |||
| 101 | /*************** HFTCTL FUNCTION *******************************/ | ||
| 102 | |||
| 103 | hftctl( fd, request, arg ) | ||
| 104 | int fd ; | ||
| 105 | int request ; | ||
| 106 | union { | ||
| 107 | struct hfintro *intro ; | ||
| 108 | struct hfquery *query ; | ||
| 109 | char *c ; | ||
| 110 | } arg ; | ||
| 111 | { | ||
| 112 | |||
| 113 | int i ; | ||
| 114 | int fd_flag ; /* fcntl flags */ | ||
| 115 | register union { | ||
| 116 | struct hfintro *cmd ; /* p.cmd - intro des. */ | ||
| 117 | struct hfqphdevc *ph ; /* p.ph - physical dev.*/ | ||
| 118 | char *c ; /* p.c - char ptr */ | ||
| 119 | } p ; /* general pointer */ | ||
| 120 | int pty_new ; /* pty modes */ | ||
| 121 | int pty_old ; | ||
| 122 | int retcode ; | ||
| 123 | struct termios term_new ; /* terminal attributes */ | ||
| 124 | struct termios term_old ; | ||
| 125 | struct devinfo devInfo ; /* defined in sys/devinfo.h */ | ||
| 126 | |||
| 127 | |||
| 128 | if ( ioctl( fd, IOCINFO, &devInfo ) == -1 ) return(-1) ; | ||
| 129 | |||
| 130 | if ( devInfo.devtype != DD_PSEU ) /* is it a pty? */ | ||
| 131 | return (ioctl(fd, request, arg) ) ; /* no, do IOCTL */ | ||
| 132 | |||
| 133 | /******* START PTY **************/ | ||
| 134 | /** Pty found, possible HFT */ | ||
| 135 | /** set new file des as raw */ | ||
| 136 | /** as you can. */ | ||
| 137 | /********************************/ | ||
| 138 | |||
| 139 | /* Get current state of file */ | ||
| 140 | /* descriptor & save */ | ||
| 141 | if ( ( fd_flag = fcntl( fd, F_GETFL, 0 ) ) == -1 ) return (-1) ; | ||
| 142 | if ( ioctl( fd, TCGETS, &term_old ) == -1 ) return (-1) ; | ||
| 143 | /* set terminal attr to raw */ | ||
| 144 | /* and to delay on read */ | ||
| 145 | pty_new = pty_old | REMOTE ; | ||
| 146 | memcpy( &term_new, &term_old, sizeof( term_new ) ) ; | ||
| 147 | term_new.c_iflag = 0 ; | ||
| 148 | term_new.c_oflag = 0 ; | ||
| 149 | term_new.c_lflag = 0 ; | ||
| 150 | /* term_new.c_line = 0 ; */ | ||
| 151 | for ( i = 1 ; i <= 5 ; i++ ) | ||
| 152 | term_new.c_cc[i] = 0 ; | ||
| 153 | term_new.c_cc[0] = -1 ; | ||
| 154 | ioctl( fd, TCSETS, &term_new ) ; | ||
| 155 | if ( fcntl( fd, F_SETFL, fd_flag & ~O_NDELAY ) == -1 ) | ||
| 156 | return(-1) ; | ||
| 157 | /* call spacific function */ | ||
| 158 | if ( request == HFSKBD ) | ||
| 159 | retcode = hfskbd( fd, request, arg.c) ; | ||
| 160 | else /* assume HFQUERY */ | ||
| 161 | retcode = hfqry( fd, request, arg.c) ; | ||
| 162 | |||
| 163 | fcntl( fd, F_SETFL, fd_flag ) ; /* reset terminal to original */ | ||
| 164 | ioctl( fd, TCSETS, &term_old ) ; | ||
| 165 | |||
| 166 | |||
| 167 | return( retcode ) ; /* return error */ | ||
| 168 | } | ||
| 169 | |||
| 170 | /*************** HFSKBD FUNCTION ******************************/ | ||
| 171 | static hfskbd(fd, request, arg ) | ||
| 172 | int fd ; | ||
| 173 | int request ; | ||
| 174 | struct hfbuf *arg ; | ||
| 175 | { | ||
| 176 | WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0) ; | ||
| 177 | return( GT_ACK(fd, request, arg->hf_bufp) ) ; | ||
| 178 | } | ||
| 179 | |||
| 180 | /*************** HFQUERY FUNCTION ******************************/ | ||
| 181 | static hfqry(fd, request, arg ) | ||
| 182 | int fd ; | ||
| 183 | int request ; | ||
| 184 | struct hfquery *arg ; | ||
| 185 | { | ||
| 186 | WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen ) ; | ||
| 187 | return( GT_ACK(fd, request, arg->hf_resp ) ) ; | ||
| 188 | } | ||
| 189 | |||
| 190 | |||
| 191 | /*************** GT_ACK FUNCTION ******************************/ | ||
| 192 | static GT_ACK(fd, req, buf ) | ||
| 193 | int fd ; | ||
| 194 | int req ; | ||
| 195 | char *buf ; | ||
| 196 | { | ||
| 197 | |||
| 198 | struct hfctlack ack ; | ||
| 199 | int i = sizeof( ack ) ; | ||
| 200 | int j = 0 ; | ||
| 201 | union { | ||
| 202 | char *c ; | ||
| 203 | struct hfctlack *ack ; | ||
| 204 | } p ; | ||
| 205 | |||
| 206 | int hft_alrm() ; | ||
| 207 | |||
| 208 | is_ack_vtd = 0 ; /* flag no ACT VTD yet */ | ||
| 209 | |||
| 210 | if ( setjmp( hftenv ) ) /* set environment in case */ | ||
| 211 | { /* of time out */ | ||
| 212 | errno=ENODEV ; /* if time out, set errno */ | ||
| 213 | return( -1 ) ; /* flag error */ | ||
| 214 | } | ||
| 215 | |||
| 216 | alarm(3) ; /* time out in 3 secs */ | ||
| 217 | sav_alrm = signal( SIGALRM, hft_alrm ) ;/* prepare to catch time out */ | ||
| 218 | |||
| 219 | p.ack = &ack ; | ||
| 220 | while ( ! is_ack_vtd ) /* do until valid ACK VTD */ | ||
| 221 | { | ||
| 222 | RD_BUF(fd, p.c, i ) ; /* read until a ACK VTD is fill*/ | ||
| 223 | |||
| 224 | if ( ! memcmp( &ack, &ACK, sizeof( HFINTROSZ ) ) /* the ACK intro & */ | ||
| 225 | && ( ack.hf_request == req ) ) /* is it the response we want ?*/ | ||
| 226 | { /* yes, ACK VTD found */ | ||
| 227 | is_ack_vtd = 1 ; /* quickly, flag it */ | ||
| 228 | break ; /* get the %$%#@ out of here */ | ||
| 229 | } | ||
| 230 | |||
| 231 | p.ack = &ack ; /* no, then skip 1st */ | ||
| 232 | ++p.c ; /* char and start over */ | ||
| 233 | i = sizeof( ack ) - 1 ; /* one less ESC to cry over */ | ||
| 234 | |||
| 235 | while( ( *p.c != 0x1b ) && i ) /* scan for next ESC */ | ||
| 236 | { ++p.c ; --i ; } /* if any */ | ||
| 237 | |||
| 238 | ( i ? memcpy( &ack, p.c, i ) : 0 ) ; /* if any left over, then move */ | ||
| 239 | p.ack = &ack ; /* ESC to front of ack struct */ | ||
| 240 | p.c += i ; /* skip over whats been read */ | ||
| 241 | i = sizeof( ack ) - i ; /* set whats left to be read */ | ||
| 242 | } /***** TRY AGAIN */ | ||
| 243 | |||
| 244 | alarm(0) ; /* ACK VTD received, reset alrm*/ | ||
| 245 | signal( SIGALRM, sav_alrm ) ; /* reset signal */ | ||
| 246 | |||
| 247 | if ( i = ack.hf_arg_len ) /* any data following ? */ | ||
| 248 | { /* yes, */ | ||
| 249 | RD_BUF(fd,buf,i) ; /* read until it is received */ | ||
| 250 | } | ||
| 251 | |||
| 252 | if ( errno = ack.hf_retcode ) /* set errno based on returned */ | ||
| 253 | return (-1) ; /* code, if 0, then no error */ | ||
| 254 | else | ||
| 255 | return (0) ; /* if set, then error returned */ | ||
| 256 | } | ||
| 257 | |||
| 258 | /*************** HFT_ALRM FUNCTION ******************************/ | ||
| 259 | static hft_alrm(sig) /* Function hft_alrm - handle */ | ||
| 260 | int sig ; /* alarm signal */ | ||
| 261 | { | ||
| 262 | signal( SIGALRM, sav_alrm ) ; /* reset to previous */ | ||
| 263 | |||
| 264 | if ( is_ack_vtd ) /* has ack vtd arrived ? */ | ||
| 265 | return(0) ; /* yes, then continue */ | ||
| 266 | else /* no, then return with error */ | ||
| 267 | longjmp( hftenv, -1 ) ; | ||
| 268 | |||
| 269 | } | ||
| 270 | |||
| 271 | /*********************************************************************/ | ||
| 272 | /*** ***/ | ||
| 273 | /*** NOTE: Both the HFCTLREQ and the arg structure should be ***/ | ||
| 274 | /*** sent in one io write operation. If terminal ***/ | ||
| 275 | /*** emulators are in NODELAY mode then multiple writes ***/ | ||
| 276 | /*** may cause bogus information to be read by the emulator ***/ | ||
| 277 | /*** depending on the timing. ***/ | ||
| 278 | /*** ***/ | ||
| 279 | /*********************************************************************/ | ||
| 280 | |||
| 281 | static WR_REQ(fd, request, cmdlen, cmd, resplen ) | ||
| 282 | int fd ; | ||
| 283 | int request ; | ||
| 284 | int cmdlen ; | ||
| 285 | char *cmd ; | ||
| 286 | int resplen ; | ||
| 287 | { | ||
| 288 | struct { | ||
| 289 | char *c ; | ||
| 290 | struct hfctlreq *req ; | ||
| 291 | } p ; | ||
| 292 | int size ; | ||
| 293 | |||
| 294 | req.hf_request = request ; | ||
| 295 | req.hf_arg_len = cmdlen ; | ||
| 296 | req.hf_rsp_len = resplen ; | ||
| 297 | |||
| 298 | if ( cmdlen ) /* if arg structure to pass */ | ||
| 299 | { | ||
| 300 | size = sizeof( struct hfctlreq ) + cmdlen ; | ||
| 301 | if ( ( p.c = malloc(size) ) == NULL ) /* malloc one area */ | ||
| 302 | return( -1 ) ; | ||
| 303 | |||
| 304 | memcpy( p.c, &req, sizeof( req ) ) ; /* copy CTL REQ struct */ | ||
| 305 | memcpy( p.c + sizeof( req ), cmd, cmdlen ) ; /* copy arg struct */ | ||
| 306 | } | ||
| 307 | else | ||
| 308 | { | ||
| 309 | p.req = &req ; /* otherwise use only CTL REQ */ | ||
| 310 | size = sizeof( req ) ; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* write request to terminal */ | ||
| 314 | if ( write(fd,p.c,size) == -1 ) return (-1) ; | ||
| 315 | if ( p.req != &req ) /* free if allocated */ | ||
| 316 | free( p.c ) ; | ||
| 317 | return (0) ; | ||
| 318 | |||
| 319 | } | ||