home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / calc-2.9.0 / part03 < prev    next >
Text File  |  1993-12-07  |  61KB  |  2,856 lines

  1. Newsgroups: comp.sources.unix
  2. From: dbell@canb.auug.org.au (David I. Bell)
  3. Subject: v27i130: calc-2.9.0 - arbitrary precision C-like programmable calculator, Part03/19
  4. References: <1.755316719.21314@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: dbell@canb.auug.org.au (David I. Bell)
  9. Posting-Number: Volume 27, Issue 130
  10. Archive-Name: calc-2.9.0/part03
  11.  
  12. #!/bin/sh
  13. # this is part 3 of a multipart archive
  14. # do not concatenate these parts, unpack them in order with /bin/sh
  15. # file calc2.9.0/codegen.c continued
  16. #
  17. CurArch=3
  18. if test ! -r s2_seq_.tmp
  19. then echo "Please unpack part 1 first!"
  20.      exit 1; fi
  21. ( read Scheck
  22.   if test "$Scheck" != $CurArch
  23.   then echo "Please unpack part $Scheck next!"
  24.        exit 1;
  25.   else exit 0; fi
  26. ) < s2_seq_.tmp || exit 1
  27. echo "x - Continuing file calc2.9.0/codegen.c"
  28. sed 's/^X//' << 'SHAR_EOF' >> calc2.9.0/codegen.c
  29. X            return;
  30. X        }
  31. X        addoplabel(OP_JUMP, contlabel);
  32. X        break;
  33. X
  34. X    case T_BREAK:
  35. X        if (breaklabel == NULL_LABEL) {
  36. X            scanerror(T_SEMICOLON, "BREAK not within FOR, WHILE, or DO");
  37. X            return;
  38. X        }
  39. X        addoplabel(OP_JUMP, breaklabel);
  40. X        break;
  41. X
  42. X    case T_GOTO:
  43. X        if (gettoken() != T_SYMBOL) {
  44. X            scanerror(T_SEMICOLON, "Missing label in goto");
  45. X            return;
  46. X        }
  47. X        addop(OP_JUMP);
  48. X        addlabel(tokenstring());
  49. X        break;
  50. X
  51. X    case T_RETURN:
  52. X        switch (gettoken()) {
  53. X            case T_NEWLINE:
  54. X            case T_SEMICOLON:
  55. X                addop(OP_UNDEF);
  56. X                addop(OP_RETURN);
  57. X                return;
  58. X            default:
  59. X                rescantoken();
  60. X                (void) getexprlist();
  61. X                if (curfunc->f_name[0] == '*')
  62. X                    addop(OP_SAVE);
  63. X                addop(OP_RETURN);
  64. X        }
  65. X        break;
  66. X
  67. X    case T_LEFTBRACE:
  68. X        rescantoken();
  69. X        getbody(contlabel, breaklabel, nextcaselabel, defaultlabel, FALSE);
  70. X        return;
  71. X
  72. X    case T_IF:
  73. X        clearlabel(&label1);
  74. X        clearlabel(&label2);
  75. X        getcondition();
  76. X        addoplabel(OP_JUMPEQ, &label1);
  77. X        getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
  78. X        if (gettoken() != T_ELSE) {
  79. X            setlabel(&label1);
  80. X            rescantoken();
  81. X            return;
  82. X        }
  83. X        addoplabel(OP_JUMP, &label2);
  84. X        setlabel(&label1);
  85. X        getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
  86. X        setlabel(&label2);
  87. X        return;
  88. X
  89. X    case T_FOR:    /* for (a; b; c) x */
  90. X        clearlabel(&label1);
  91. X        clearlabel(&label2);
  92. X        clearlabel(&label3);
  93. X        clearlabel(&label4);
  94. X        contlabel = NULL_LABEL;
  95. X        breaklabel = &label4;
  96. X        if (gettoken() != T_LEFTPAREN) {
  97. X            scanerror(T_SEMICOLON, "Left parenthesis expected");
  98. X            return;
  99. X        }
  100. X        if (gettoken() != T_SEMICOLON) {    /* have 'a' part */
  101. X            rescantoken();
  102. X            (void) getexprlist();
  103. X            addop(OP_POP);
  104. X            if (gettoken() != T_SEMICOLON) {
  105. X                scanerror(T_SEMICOLON, "Missing semicolon");
  106. X                return;
  107. X            }
  108. X        }
  109. X        if (gettoken() != T_SEMICOLON) {    /* have 'b' part */
  110. X            setlabel(&label1);
  111. X            contlabel = &label1;
  112. X            rescantoken();
  113. X            (void) getexprlist();
  114. X            addoplabel(OP_JUMPNE, &label3);
  115. X            addoplabel(OP_JUMP, breaklabel);
  116. X            if (gettoken() != T_SEMICOLON) {
  117. X                scanerror(T_SEMICOLON, "Missing semicolon");
  118. X                return;
  119. X            }
  120. X        }
  121. X        if (gettoken() != T_RIGHTPAREN) {    /* have 'c' part */
  122. X            if (label1.l_offset <= 0)
  123. X                addoplabel(OP_JUMP, &label3);
  124. X            setlabel(&label2);
  125. X            contlabel = &label2;
  126. X            rescantoken();
  127. X            (void) getexprlist();
  128. X            addop(OP_POP);
  129. X            if (label1.l_offset > 0)
  130. X                addoplabel(OP_JUMP, &label1);
  131. X            if (gettoken() != T_RIGHTPAREN) {
  132. X                scanerror(T_SEMICOLON, "Right parenthesis expected");
  133. X                return;
  134. X            }
  135. X        }
  136. X        setlabel(&label3);
  137. X        if (contlabel == NULL_LABEL)
  138. X            contlabel = &label3;
  139. X        getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
  140. X        addoplabel(OP_JUMP, contlabel);
  141. X        setlabel(breaklabel);
  142. X        return;
  143. X
  144. X    case T_WHILE:
  145. X        contlabel = &label1;
  146. X        breaklabel = &label2;
  147. X        clearlabel(contlabel);
  148. X        clearlabel(breaklabel);
  149. X        setlabel(contlabel);
  150. X        getcondition();
  151. X        addoplabel(OP_JUMPEQ, breaklabel);
  152. X        getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
  153. X        addoplabel(OP_JUMP, contlabel);
  154. X        setlabel(breaklabel);
  155. X        return;
  156. X
  157. X    case T_DO:
  158. X        contlabel = &label1;
  159. X        breaklabel = &label2;
  160. X        clearlabel(contlabel);
  161. X        clearlabel(breaklabel);
  162. X        clearlabel(&label3);
  163. X        setlabel(&label3);
  164. X        getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
  165. X        if (gettoken() != T_WHILE) {
  166. X            scanerror(T_SEMICOLON, "WHILE keyword expected for DO statement");
  167. X            return;
  168. X        }
  169. X        setlabel(contlabel);
  170. X        getcondition();
  171. X        addoplabel(OP_JUMPNE, &label3);
  172. X        setlabel(breaklabel);
  173. X        return;
  174. X
  175. X    case T_SWITCH:
  176. X        breaklabel = &label1;
  177. X        nextcaselabel = &label2;
  178. X        defaultlabel = &label3;
  179. X        clearlabel(breaklabel);
  180. X        clearlabel(nextcaselabel);
  181. X        clearlabel(defaultlabel);
  182. X        getcondition();
  183. X        if (gettoken() != T_LEFTBRACE) {
  184. X            scanerror(T_SEMICOLON, "Missing left brace for switch statement");
  185. X            return;
  186. X        }
  187. X        addoplabel(OP_JUMP, nextcaselabel);
  188. X        rescantoken();
  189. X        getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
  190. X        addoplabel(OP_JUMP, breaklabel);
  191. X        setlabel(nextcaselabel);
  192. X        if (defaultlabel->l_offset > 0)
  193. X            addoplabel(OP_JUMP, defaultlabel);
  194. X        else
  195. X            addop(OP_POP);
  196. X        setlabel(breaklabel);
  197. X        return;
  198. X
  199. X    case T_CASE:
  200. X        if (nextcaselabel == NULL_LABEL) {
  201. X            scanerror(T_SEMICOLON, "CASE not within SWITCH statement");
  202. X            return;
  203. X        }
  204. X        clearlabel(&label1);
  205. X        addoplabel(OP_JUMP, &label1);
  206. X        setlabel(nextcaselabel);
  207. X        clearlabel(nextcaselabel);
  208. X        (void) getexprlist();
  209. X        if (gettoken() != T_COLON) {
  210. X            scanerror(T_SEMICOLON, "Colon expected after CASE expression");
  211. X            return;
  212. X        }
  213. X        addoplabel(OP_CASEJUMP, nextcaselabel);
  214. X        setlabel(&label1);
  215. X        getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
  216. X        return;
  217. X
  218. X    case T_DEFAULT:
  219. X        if (gettoken() != T_COLON) {
  220. X            scanerror(T_SEMICOLON, "Colon expected after DEFAULT keyword");
  221. X            return;
  222. X        }
  223. X        if (defaultlabel == NULL_LABEL) {
  224. X            scanerror(T_SEMICOLON, "DEFAULT not within SWITCH statement");
  225. X            return;
  226. X        }
  227. X        if (defaultlabel->l_offset > 0) {
  228. X            scanerror(T_SEMICOLON, "Multiple DEFAULT clauses in SWITCH");
  229. X            return;
  230. X        }
  231. X        clearlabel(&label1);
  232. X        addoplabel(OP_JUMP, &label1);
  233. X        setlabel(defaultlabel);
  234. X        addop(OP_POP);
  235. X        setlabel(&label1);
  236. X        getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
  237. X        return;
  238. X
  239. X    case T_ELSE:
  240. X        scanerror(T_SEMICOLON, "ELSE without preceeding IF");
  241. X        return;
  242. X
  243. X    case T_MAT:
  244. X        getmatdeclaration(SYM_UNDEFINED);
  245. X        break;
  246. X
  247. X    case T_OBJ:
  248. X        getobjdeclaration(SYM_UNDEFINED);
  249. X        break;
  250. X
  251. X    case T_PRINT:
  252. X        printeol = TRUE;
  253. X        for (;;) {
  254. X            switch (gettoken()) {
  255. X                case T_RIGHTBRACE:
  256. X                case T_NEWLINE:
  257. X                    rescantoken();
  258. X                    /*FALLTHRU*/
  259. X                case T_SEMICOLON:
  260. X                    if (printeol)
  261. X                        addop(OP_PRINTEOL);
  262. X                    return;
  263. X                case T_COLON:
  264. X                    printeol = FALSE;
  265. X                    break;
  266. X                case T_COMMA:
  267. X                    printeol = TRUE;
  268. X                    addop(OP_PRINTSPACE);
  269. X                    break;
  270. X                case T_STRING:
  271. X                    printeol = TRUE;
  272. X                    addopptr(OP_PRINTSTRING, tokenstring());
  273. X                    break;
  274. X                default:
  275. X                    printeol = TRUE;
  276. X                    rescantoken();
  277. X                    (void) getassignment();
  278. X                    addopone(OP_PRINT, (long) PRINT_NORMAL);
  279. X            }
  280. X        }
  281. X        break;
  282. X
  283. X    case T_QUIT:
  284. X        switch (gettoken()) {
  285. X            case T_STRING:
  286. X                addopptr(OP_QUIT, tokenstring());
  287. X                break;
  288. X            default:
  289. X                addopptr(OP_QUIT, NULL);
  290. X                rescantoken();
  291. X        }
  292. X        break;
  293. X
  294. X    case T_SYMBOL:
  295. X        if (nextchar() == ':') {    /****HACK HACK ****/
  296. X            definelabel(tokenstring());
  297. X            getstatement(contlabel, breaklabel, 
  298. X                NULL_LABEL, NULL_LABEL);
  299. X            return;
  300. X        }
  301. X        reread();
  302. X        /* fall into default case */
  303. X
  304. X    default:
  305. X        rescantoken();
  306. X        type = getexprlist();
  307. X        if (contlabel || breaklabel || (curfunc->f_name[0] != '*')) {
  308. X            addop(OP_POP);
  309. X            break;
  310. X        }
  311. X        addop(OP_SAVE);
  312. X        if (isassign(type) || (curfunc->f_name[1] != '\0')) {
  313. X            addop(OP_POP);
  314. X            break;
  315. X        }
  316. X        addop(OP_PRINTRESULT);
  317. X        break;
  318. X    }
  319. X    switch (gettoken()) {
  320. X        case T_RIGHTBRACE:
  321. X        case T_NEWLINE:
  322. X        case T_EOF:
  323. X            rescantoken();
  324. X            break;
  325. X        case T_SEMICOLON:
  326. X            break;
  327. X        default:
  328. X            scanerror(T_SEMICOLON, "Semicolon expected");
  329. X            break;
  330. X    }
  331. X}
  332. X
  333. X
  334. X/*
  335. X * Read in an object declaration.
  336. X * This is of the following form:
  337. X *    OBJ type [ '{' id [ ',' id ] ... '}' ]  [ objlist ].
  338. X * The OBJ keyword has already been read.  Symtype is SYM_UNDEFINED if this
  339. X * is an OBJ statement, otherwise this is part of a declaration which will
  340. X * define new symbols with the specified type.
  341. X */
  342. Xstatic void
  343. Xgetobjdeclaration(symtype)
  344. X{
  345. X    char *name;            /* name of object type */
  346. X    int count;            /* number of elements */
  347. X    int index;            /* current index */
  348. X    int i;                /* loop counter */
  349. X    BOOL err;            /* error flag */
  350. X    int indices[MAXINDICES];    /* indices for elements */
  351. X
  352. X    err = FALSE;
  353. X    if (gettoken() != T_SYMBOL) {
  354. X        scanerror(T_SEMICOLON, "Object type name missing");
  355. X        return;
  356. X    }
  357. X    name = addliteral(tokenstring());
  358. X    if (gettoken() != T_LEFTBRACE) {
  359. X        rescantoken();
  360. X        getobjvars(name, symtype);
  361. X        return;
  362. X    }
  363. X    /*
  364. X     * Read in the definition of the elements of the object.
  365. X     */
  366. X    count = 0;
  367. X    for (;;) {
  368. X        if (gettoken() != T_SYMBOL) {
  369. X            scanerror(T_SEMICOLON, "Missing element name in OBJ statement");
  370. X            return;
  371. X        }
  372. X        index = addelement(tokenstring());
  373. X        for (i = 0; i < count; i++) {
  374. X            if (indices[i] == index) {
  375. X                scanerror(T_NULL, "Duplicate element name \"%s\"", tokenstring());
  376. X                err = TRUE;
  377. X                break;
  378. X            }
  379. X        }
  380. X        indices[count++] = index;
  381. X        switch (gettoken()) {
  382. X            case T_RIGHTBRACE:
  383. X                if (!err)
  384. X                    (void) defineobject(name, indices, count);
  385. X                switch (gettoken()) {
  386. X                    case T_SEMICOLON:
  387. X                    case T_NEWLINE:
  388. X                        rescantoken();
  389. X                        return;
  390. X                }
  391. X                rescantoken();
  392. X                getobjvars(name, symtype);
  393. X                return;
  394. X            case T_COMMA:
  395. X            case T_SEMICOLON:
  396. X            case T_NEWLINE:
  397. X                break;
  398. X            default:
  399. X                scanerror(T_SEMICOLON, "Bad object element definition");
  400. X                return;
  401. X        }
  402. X    }
  403. X}
  404. X
  405. X
  406. X/*
  407. X * Routine to collect a set of variables for the specified object type
  408. X * and initialize them as being that type of object.
  409. X * Here
  410. X *    objlist = name initlist [ ',' name initlist ] ... ';'.
  411. X * If symtype is SYM_UNDEFINED, then this is an OBJ statement where the
  412. X * values can be any variable expression, and no symbols are to be defined.
  413. X * Otherwise this is part of a declaration, and the variables must be raw
  414. X * symbol names which are defined with the specified symbol type.
  415. X */
  416. Xstatic void
  417. Xgetobjvars(name, symtype)
  418. X    char *name;        /* object name */
  419. X{
  420. X    long index;        /* index for object */
  421. X    char *symname;
  422. X
  423. X    index = checkobject(name);
  424. X    if (index < 0) {
  425. X        scanerror(T_SEMICOLON, "Object %s has not been defined yet", name);
  426. X        return;
  427. X    }
  428. X    for (;;) {
  429. X        if (symtype == SYM_UNDEFINED)
  430. X            (void) getidexpr(TRUE, TRUE);
  431. X        else {
  432. X            if (gettoken() != T_SYMBOL) {
  433. X                scanerror(T_SEMICOLON, "Missing object variable name");
  434. X                return;
  435. X            }
  436. X            symname = tokenstring();
  437. X            definesymbol(symname, symtype);
  438. X            usesymbol(symname, FALSE);
  439. X        }
  440. X        addopone(OP_OBJCREATE, index);
  441. X        (void) getinitlist();
  442. X        switch (gettoken()) {
  443. X            case T_COMMA:
  444. X                break;
  445. X            case T_SEMICOLON:
  446. X            case T_NEWLINE:
  447. X                rescantoken();
  448. X                return;
  449. X            default:
  450. X                scanerror(T_SEMICOLON, "Bad OBJ statement");
  451. X                return;
  452. X        }
  453. X    }
  454. X}
  455. X
  456. X
  457. X/*
  458. X * Read a matrix definition declaration for a one or more dimensional matrix.
  459. X * The MAT keyword has already been read.  This also handles an optional
  460. X * matrix initialization list enclosed in braces.  Symtype is SYM_UNDEFINED
  461. X * if this is part of a MAT statement which handles any variable expression.
  462. X * Otherwise this is part of a declaration and only a symbol name is allowed.
  463. X */
  464. Xstatic void
  465. Xgetmatdeclaration(symtype)
  466. X{
  467. X    long dim;
  468. X    long index;
  469. X    long count;
  470. X    long patchpc;
  471. X    char *name;
  472. X
  473. X    if (symtype == SYM_UNDEFINED)
  474. X        (void) getidexpr(FALSE, TRUE);
  475. X    else {
  476. X        if (gettoken() != T_SYMBOL) {
  477. X            scanerror(T_COMMA, "Missing matrix variable name");
  478. X            return;
  479. X        }
  480. X        name = tokenstring();
  481. X        definesymbol(name, symtype);
  482. X        usesymbol(name, FALSE);
  483. X    }
  484. X
  485. X    if (gettoken() != T_LEFTBRACKET) {
  486. X        scanerror(T_SEMICOLON, "Missing left bracket for MAT");
  487. X        return;
  488. X    }
  489. X    dim = 1;
  490. X
  491. X    /*
  492. X     * If there are no bounds given for the matrix, then they must be
  493. X     * implicitly defined by a list of initialization values.  Put in
  494. X     * a dummy number in the opcode stream for the bounds and remember
  495. X     * its location.  After we know how many values are in the list, we
  496. X     * will patch the correct value back into the opcode.
  497. X     */
  498. X    if (gettoken() == T_RIGHTBRACKET) {
  499. X        clearopt();
  500. X        patchpc = curfunc->f_opcodecount + 1;
  501. X        addopone(OP_NUMBER, (long) -1);
  502. X        clearopt();
  503. X        addop(OP_ZERO);
  504. X        addopone(OP_MATCREATE, dim);
  505. X        count = getinitlist();
  506. X        if (count == 0) {
  507. X            scanerror(T_NULL, "Initialization required for implicit matrix bounds");
  508. X            return;
  509. X        }
  510. X        index = addqconstant(itoq(count - 1));
  511. X        if (index < 0)
  512. X            math_error("Cannot allocate constant");
  513. X        curfunc->f_opcodes[patchpc] = index;
  514. X        return;
  515. X    }
  516. X
  517. X    /*
  518. X     * This isn't implicit, so we expect expressions for the bounds.
  519. X     */
  520. X    rescantoken();
  521. X    while (TRUE) {
  522. X        (void) getassignment();
  523. X        switch (gettoken()) {
  524. X            case T_RIGHTBRACKET:
  525. X            case T_COMMA:
  526. X                rescantoken();
  527. X                addop(OP_ONE);
  528. X                addop(OP_SUB);
  529. X                addop(OP_ZERO);
  530. X                break;
  531. X            case T_COLON:
  532. X                (void) getassignment();
  533. X                break;
  534. X            default:
  535. X                rescantoken();
  536. X        }
  537. X        switch (gettoken()) {
  538. X            case T_RIGHTBRACKET:
  539. X                if (gettoken() != T_LEFTBRACKET) {
  540. X                    rescantoken();
  541. X                    addopone(OP_MATCREATE, dim);
  542. X                    (void) getinitlist();
  543. X                    return;
  544. X                }
  545. X                /* proceed into comma case */
  546. X                /*FALLTHRU*/
  547. X            case T_COMMA:
  548. X                if (++dim <= MAXDIM)
  549. X                    break;
  550. X                scanerror(T_SEMICOLON, "Only %ld dimensions allowed", MAXDIM);
  551. X                return;
  552. X            default:
  553. X                scanerror(T_SEMICOLON, "Illegal matrix definition");
  554. X                return;
  555. X        }
  556. X    }
  557. X}
  558. X
  559. X
  560. X/*
  561. X * Get an optional initialization list for a matrix or object definition.
  562. X * Returns the number of elements that are in the list, or -1 on parse error.
  563. X * This assumes that the address of a matrix or object variable is on the
  564. X * stack, and so this routine will pop it off when complete.
  565. X *    initlist = [ '=' '{' assignment [ ',' assignment ] ... '}' ].
  566. X */
  567. Xstatic long
  568. Xgetinitlist()
  569. X{
  570. X    long index;
  571. X    int oldmode;
  572. X
  573. X    if (gettoken() != T_ASSIGN) {
  574. X        rescantoken();
  575. X        addop(OP_POP);
  576. X        return 0;
  577. X    }
  578. X
  579. X    oldmode = tokenmode(TM_DEFAULT);
  580. X
  581. X    if (gettoken() != T_LEFTBRACE) {
  582. X        scanerror(T_SEMICOLON, "Missing brace for initialization list");
  583. X        (void) tokenmode(oldmode);
  584. X        return -1;
  585. X    }
  586. X
  587. X    for (index = 0; ; index++) {
  588. X        getassignment();
  589. X        addopone(OP_ELEMINIT, index);
  590. X        switch (gettoken()) {
  591. X            case T_COMMA:
  592. X                continue;
  593. X
  594. X            case T_RIGHTBRACE:
  595. X                (void) tokenmode(oldmode);
  596. X                addop(OP_POP);
  597. X                return index + 1;
  598. X
  599. X            default:
  600. X                scanerror(T_SEMICOLON, "Bad initialization list");
  601. X                (void) tokenmode(oldmode);
  602. X                return -1;
  603. X        }
  604. X    }
  605. X}
  606. X
  607. X
  608. X/*
  609. X * Get a condition.
  610. X * condition = '(' assignment ')'.
  611. X */
  612. Xstatic void
  613. Xgetcondition()
  614. X{
  615. X    if (gettoken() != T_LEFTPAREN) {
  616. X        scanerror(T_SEMICOLON, "Missing left parenthesis for condition");
  617. X        return;
  618. X    }
  619. X    (void) getexprlist();
  620. X    if (gettoken() != T_RIGHTPAREN) {
  621. X        scanerror(T_SEMICOLON, "Missing right parenthesis for condition");
  622. X        return;
  623. X    }
  624. X}
  625. X
  626. X
  627. X/*
  628. X * Get an expression list consisting of one or more expressions,
  629. X * separated by commas.  The value of the list is that of the final expression.
  630. X * This is the top level routine for parsing expressions.
  631. X * Returns flags describing the type of assignment or expression found.
  632. X * exprlist = assignment [ ',' assignment ] ...
  633. X */
  634. Xstatic int
  635. Xgetexprlist()
  636. X{
  637. X    int    type;
  638. X
  639. X    type = getassignment();
  640. X    while (gettoken() == T_COMMA) {
  641. X        addop(OP_POP);
  642. X        (void) getassignment();
  643. X        type = EXPR_RVALUE;
  644. X    }
  645. X    rescantoken();
  646. X    return type;
  647. X}
  648. X
  649. X
  650. X/*
  651. X * Get an assignment (or possibly just an expression).
  652. X * Returns flags describing the type of assignment or expression found.
  653. X * assignment = lvalue '=' assignment
  654. X *    | lvalue '+=' assignment
  655. X *    | lvalue '-=' assignment
  656. X *    | lvalue '*=' assignment
  657. X *    | lvalue '/=' assignment
  658. X *    | lvalue '%=' assignment
  659. X *    | lvalue '//=' assignment
  660. X *    | lvalue '&=' assignment
  661. X *    | lvalue '|=' assignment
  662. X *    | lvalue '<<=' assignment
  663. X *    | lvalue '>>=' assignment
  664. X *    | lvalue '^=' assignment
  665. X *    | lvalue '**=' assignment
  666. X *    | orcond.
  667. X */
  668. Xstatic int
  669. Xgetassignment()
  670. X{
  671. X    int type;        /* type of expression */
  672. X    long op;        /* opcode to generate */
  673. X
  674. X    type = getaltcond();
  675. X    switch (gettoken()) {
  676. X        case T_ASSIGN:        op = 0; break;
  677. X        case T_PLUSEQUALS:    op = OP_ADD; break;
  678. X        case T_MINUSEQUALS:    op = OP_SUB; break;
  679. X        case T_MULTEQUALS:    op = OP_MUL; break;
  680. X        case T_DIVEQUALS:    op = OP_DIV; break;
  681. X        case T_SLASHSLASHEQUALS: op = OP_QUO; break;
  682. X        case T_MODEQUALS:    op = OP_MOD; break;
  683. X        case T_ANDEQUALS:    op = OP_AND; break;
  684. X        case T_OREQUALS:    op = OP_OR; break;
  685. X        case T_LSHIFTEQUALS:     op = OP_LEFTSHIFT; break;
  686. X        case T_RSHIFTEQUALS:     op = OP_RIGHTSHIFT; break;
  687. X        case T_POWEREQUALS:    op = OP_POWER; break;
  688. X
  689. X        case T_NUMBER:
  690. X        case T_IMAGINARY:
  691. X        case T_STRING:
  692. X        case T_SYMBOL:
  693. X        case T_OLDVALUE:
  694. X        case T_LEFTPAREN:
  695. X        case T_PLUSPLUS:
  696. X        case T_MINUSMINUS:
  697. X        case T_NOT:
  698. X            scanerror(T_NULL, "Missing operator");
  699. X            return type;
  700. X
  701. X        default:
  702. X            rescantoken();
  703. X            return type;
  704. X    }
  705. X    if (isrvalue(type)) {
  706. X        scanerror(T_NULL, "Illegal assignment");
  707. X        (void) getassignment();
  708. X        return (EXPR_RVALUE | EXPR_ASSIGN);
  709. X    }
  710. X    writeindexop();
  711. X    if (op)
  712. X        addop(OP_DUPLICATE);
  713. X    (void) getassignment();
  714. X    if (op) {
  715. X        addop(op);
  716. X    }
  717. X    addop(OP_ASSIGN);
  718. X    return (EXPR_RVALUE | EXPR_ASSIGN);
  719. X}
  720. X
  721. X
  722. X/*
  723. X * Get a possible conditional result expression (question mark).
  724. X * Flags are returned indicating the type of expression found.
  725. X * altcond = orcond [ '?' orcond ':' altcond ].
  726. X */
  727. Xstatic int
  728. Xgetaltcond()
  729. X{
  730. X    int type;        /* type of expression */
  731. X    LABEL donelab;        /* label for done */
  732. X    LABEL altlab;        /* label for alternate expression */
  733. X
  734. X    type = getorcond();
  735. X    if (gettoken() != T_QUESTIONMARK) {
  736. X        rescantoken();
  737. X        return type;
  738. X    }
  739. X    clearlabel(&donelab);
  740. X    clearlabel(&altlab);
  741. X    addoplabel(OP_JUMPEQ, &altlab);
  742. X    (void) getorcond();
  743. X    if (gettoken() != T_COLON) {
  744. X        scanerror(T_SEMICOLON, "Missing colon for conditional expression");
  745. X        return EXPR_RVALUE;
  746. X    }
  747. X    addoplabel(OP_JUMP, &donelab);
  748. X    setlabel(&altlab);
  749. X    (void) getaltcond();
  750. X    setlabel(&donelab);
  751. X    return EXPR_RVALUE;
  752. X}
  753. X
  754. X
  755. X/*
  756. X * Get a possible conditional or expression.
  757. X * Flags are returned indicating the type of expression found.
  758. X * orcond = andcond [ '||' andcond ] ...
  759. X */
  760. Xstatic int
  761. Xgetorcond()
  762. X{
  763. X    int type;        /* type of expression */
  764. X    LABEL donelab;        /* label for done */
  765. X
  766. X    clearlabel(&donelab);
  767. X    type = getandcond();
  768. X    while (gettoken() == T_OROR) {
  769. X        addoplabel(OP_CONDORJUMP, &donelab);
  770. X        (void) getandcond();
  771. X        type = EXPR_RVALUE;
  772. X    }
  773. X    rescantoken();
  774. X    if (donelab.l_chain > 0)
  775. X        setlabel(&donelab);
  776. X    return type;
  777. X}
  778. X
  779. X
  780. X/*
  781. X * Get a possible conditional and expression.
  782. X * Flags are returned indicating the type of expression found.
  783. X * andcond = relation [ '&&' relation ] ...
  784. X */
  785. Xstatic int
  786. Xgetandcond()
  787. X{
  788. X    int type;        /* type of expression */
  789. X    LABEL donelab;        /* label for done */
  790. X
  791. X    clearlabel(&donelab);
  792. X    type = getrelation();
  793. X    while (gettoken() == T_ANDAND) {
  794. X        addoplabel(OP_CONDANDJUMP, &donelab);
  795. X        (void) getrelation();
  796. X        type = EXPR_RVALUE;
  797. X    }
  798. X    rescantoken();
  799. X    if (donelab.l_chain > 0)
  800. X        setlabel(&donelab);
  801. X    return type;
  802. X}
  803. X
  804. X
  805. X/*
  806. X * Get a possible relation (equality or inequality), or just an expression.
  807. X * Flags are returned indicating the type of relation found.
  808. X * relation = sum '==' sum
  809. X *    | sum '!=' sum
  810. X *    | sum '<=' sum
  811. X *    | sum '>=' sum
  812. X *    | sum '<' sum
  813. X *    | sum '>' sum
  814. X *    | sum.
  815. X */
  816. Xstatic int
  817. Xgetrelation()
  818. X{
  819. X    int type;        /* type of expression */
  820. X    long op;        /* opcode to generate */
  821. X
  822. X    type = getsum();
  823. X    switch (gettoken()) {
  824. X        case T_EQ: op = OP_EQ; break;
  825. X        case T_NE: op = OP_NE; break;
  826. X        case T_LT: op = OP_LT; break;
  827. X        case T_GT: op = OP_GT; break;
  828. X        case T_LE: op = OP_LE; break;
  829. X        case T_GE: op = OP_GE; break;
  830. X        default:
  831. X            rescantoken();
  832. X            return type;
  833. X    }
  834. X    (void) getsum();
  835. X    addop(op);
  836. X    return EXPR_RVALUE;
  837. X}
  838. X
  839. X
  840. X/*
  841. X * Get an expression made up of sums of products.
  842. X * Flags indicating the type of expression found are returned.
  843. X * sum = product [ {'+' | '-'} product ] ...
  844. X */
  845. Xstatic int
  846. Xgetsum()
  847. X{
  848. X    int type;        /* type of expression found */
  849. X    long op;        /* opcode to generate */
  850. X
  851. X    type = getproduct();
  852. X    for (;;) {
  853. X        switch (gettoken()) {
  854. X            case T_PLUS:    op = OP_ADD; break;
  855. X            case T_MINUS:    op = OP_SUB; break;
  856. X            default:
  857. X                rescantoken();
  858. X                return type;
  859. X        }
  860. X        (void) getproduct();
  861. X        addop(op);
  862. X        type = EXPR_RVALUE;
  863. X    }
  864. X}
  865. X
  866. X
  867. X/*
  868. X * Get the product of arithmetic or expressions.
  869. X * Flags indicating the type of expression found are returned.
  870. X * product = orexpr [ {'*' | '/' | '//' | '%'} orexpr ] ...
  871. X */
  872. Xstatic int
  873. Xgetproduct()
  874. X{
  875. X    int type;        /* type of value found */
  876. X    long op;        /* opcode to generate */
  877. X
  878. X    type = getorexpr();
  879. X    for (;;) {
  880. X        switch (gettoken()) {
  881. X            case T_MULT:    op = OP_MUL; break;
  882. X            case T_DIV:    op = OP_DIV; break;
  883. X            case T_MOD:    op = OP_MOD; break;
  884. X            case T_SLASHSLASH: op = OP_QUO; break;
  885. X            default:
  886. X                rescantoken();
  887. X                return type;
  888. X        }
  889. X        (void) getorexpr();
  890. X        addop(op);
  891. X        type = EXPR_RVALUE;
  892. X    }
  893. X}
  894. X
  895. X
  896. X/*
  897. X * Get an expression made up of arithmetic or operators.
  898. X * Flags indicating the type of expression found are returned.
  899. X * orexpr = andexpr [ '|' andexpr ] ...
  900. X */
  901. Xstatic int
  902. Xgetorexpr()
  903. X{
  904. X    int type;        /* type of value found */
  905. X
  906. X    type = getandexpr();
  907. X    while (gettoken() == T_OR) {
  908. X        (void) getandexpr();
  909. X        addop(OP_OR);
  910. X        type = EXPR_RVALUE;
  911. X    }
  912. X    rescantoken();
  913. X    return type;
  914. X}
  915. X
  916. X
  917. X/*
  918. X * Get an expression made up of arithmetic and operators.
  919. X * Flags indicating the type of expression found are returned.
  920. X * andexpr = shiftexpr [ '&' shiftexpr ] ...
  921. X */
  922. Xstatic int
  923. Xgetandexpr()
  924. X{
  925. X    int type;        /* type of value found */
  926. X
  927. X    type = getshiftexpr();
  928. X    while (gettoken() == T_AND) {
  929. X        (void) getshiftexpr();
  930. X        addop(OP_AND);
  931. X        type = EXPR_RVALUE;
  932. X    }
  933. X    rescantoken();
  934. X    return type;
  935. X}
  936. X
  937. X
  938. X/*
  939. X * Get a shift or power expression.
  940. X * Flags indicating the type of expression found are returned.
  941. X * shift = term '^' shiftexpr
  942. X *     | term '<<' shiftexpr
  943. X *     | term '>>' shiftexpr
  944. X *     | term.
  945. X */
  946. Xstatic int
  947. Xgetshiftexpr()
  948. X{
  949. X    int type;        /* type of value found */
  950. X    long op;        /* opcode to generate */
  951. X
  952. X    type = getterm();
  953. X    switch (gettoken()) {
  954. X        case T_POWER:        op = OP_POWER; break;
  955. X        case T_LEFTSHIFT:    op = OP_LEFTSHIFT; break;
  956. X        case T_RIGHTSHIFT:     op = OP_RIGHTSHIFT; break;
  957. X        default:
  958. X            rescantoken();
  959. X            return type;
  960. X    }
  961. X    (void) getshiftexpr();
  962. X    addop(op);
  963. X    return EXPR_RVALUE;
  964. X}
  965. X
  966. X
  967. X/*
  968. X * Get a single term.
  969. X * Flags indicating the type of value found are returned.
  970. X * term = lvalue
  971. X *    | lvalue '[' assignment ']'
  972. X *    | lvalue '++'
  973. X *    | lvalue '--'
  974. X *    | '++' lvalue
  975. X *    | '--' lvalue
  976. X *    | real_number
  977. X *    | imaginary_number
  978. X *    | '.'
  979. X *    | string
  980. X *    | '(' assignment ')'
  981. X *    | function [ '(' [assignment  [',' assignment] ] ')' ]
  982. X *    | '!' term
  983. X *    | '+' term
  984. X *    | '-' term.
  985. X */
  986. Xstatic int
  987. Xgetterm()
  988. X{
  989. X    int type;        /* type of term found */
  990. X
  991. X    type = gettoken();
  992. X    switch (type) {
  993. X        case T_NUMBER:
  994. X            addopone(OP_NUMBER, tokennumber());
  995. X            type = (EXPR_RVALUE | EXPR_CONST);
  996. X            break;
  997. X
  998. X        case T_IMAGINARY:
  999. X            addopone(OP_IMAGINARY, tokennumber());
  1000. X            type = (EXPR_RVALUE | EXPR_CONST);
  1001. X            break;
  1002. X
  1003. X        case T_OLDVALUE:
  1004. X            addop(OP_OLDVALUE);
  1005. X            type = 0;
  1006. X            break;
  1007. X
  1008. X        case T_STRING:
  1009. X            addopptr(OP_STRING, tokenstring());
  1010. X            type = (EXPR_RVALUE | EXPR_CONST);
  1011. X            break;
  1012. X
  1013. X        case T_PLUSPLUS:
  1014. X            if (isrvalue(getterm()))
  1015. X                scanerror(T_NULL, "Bad ++ usage");
  1016. X            writeindexop();
  1017. X            addop(OP_PREINC);
  1018. X            type = (EXPR_RVALUE | EXPR_ASSIGN);
  1019. X            break;
  1020. X
  1021. X        case T_MINUSMINUS:
  1022. X            if (isrvalue(getterm()))
  1023. X                scanerror(T_NULL, "Bad -- usage");
  1024. X            writeindexop();
  1025. X            addop(OP_PREDEC);
  1026. X            type = (EXPR_RVALUE | EXPR_ASSIGN);
  1027. X            break;
  1028. X
  1029. X        case T_NOT:
  1030. X            (void) getterm();
  1031. X            addop(OP_NOT);
  1032. X            type = EXPR_RVALUE;
  1033. X            break;
  1034. X
  1035. X        case T_MINUS:
  1036. X            (void) getterm();
  1037. X            addop(OP_NEGATE);
  1038. X            type = EXPR_RVALUE;
  1039. X            break;
  1040. X
  1041. X        case T_PLUS:
  1042. X            (void) getterm();
  1043. X            type = EXPR_RVALUE;
  1044. X            break;
  1045. X
  1046. X        case T_LEFTPAREN:
  1047. X            type = getexprlist();
  1048. X            if (gettoken() != T_RIGHTPAREN)
  1049. X                scanerror(T_SEMICOLON, "Missing right parenthesis");
  1050. X            break;
  1051. X
  1052. X        case T_SYMBOL:
  1053. X            rescantoken();
  1054. X            type = getidexpr(TRUE, FALSE);
  1055. X            break;
  1056. X
  1057. X        case T_LEFTBRACKET:
  1058. X            scanerror(T_NULL, "Bad index usage");
  1059. X            type = 0;
  1060. X            break;
  1061. X
  1062. X        case T_PERIOD:
  1063. X            scanerror(T_NULL, "Bad element reference");
  1064. X            type = 0;
  1065. X            break;
  1066. X
  1067. X        default:
  1068. X            if (iskeyword(type)) {
  1069. X                scanerror(T_NULL, "Expression contains reserved keyword");
  1070. X                type = 0;
  1071. X                break;
  1072. X            }
  1073. X            rescantoken();
  1074. X            scanerror(T_NULL, "Missing expression");
  1075. X            type = 0;
  1076. X    }
  1077. X    switch (gettoken()) {
  1078. X        case T_PLUSPLUS:
  1079. X            if (isrvalue(type))
  1080. X                scanerror(T_NULL, "Bad ++ usage");
  1081. X            writeindexop();
  1082. X            addop(OP_POSTINC);
  1083. X            return (EXPR_RVALUE | EXPR_ASSIGN);
  1084. X        case T_MINUSMINUS:
  1085. X            if (isrvalue(type))
  1086. X                scanerror(T_NULL, "Bad -- usage");
  1087. X            writeindexop();
  1088. X            addop(OP_POSTDEC);
  1089. X            return (EXPR_RVALUE | EXPR_ASSIGN);
  1090. X        default:
  1091. X            rescantoken();
  1092. X            return type;
  1093. X    }
  1094. X}
  1095. X
  1096. X
  1097. X/*
  1098. X * Read in an identifier expressions.
  1099. X * This is a symbol name followed by parenthesis, or by square brackets or
  1100. X * element refernces.  The symbol can be a global or a local variable name.
  1101. X * Returns the type of expression found.
  1102. X */
  1103. Xstatic int
  1104. Xgetidexpr(okmat, autodef)
  1105. X    BOOL okmat, autodef;
  1106. X{
  1107. X    int type;
  1108. X    char name[SYMBOLSIZE+1];    /* symbol name */
  1109. X
  1110. X    type = 0;
  1111. X    if (!getid(name))
  1112. X        return type;
  1113. X    switch (gettoken()) {
  1114. X        case T_LEFTPAREN:
  1115. X            getcallargs(name);
  1116. X            type = EXPR_RVALUE;
  1117. X            break;
  1118. X        case T_ASSIGN:
  1119. X            autodef = TRUE;
  1120. X            /* fall into default case */
  1121. X        default:
  1122. X            rescantoken();
  1123. X            usesymbol(name, autodef);
  1124. X    }
  1125. X    /*
  1126. X     * Now collect as many element references and matrix index operations
  1127. X     * as there are following the id.
  1128. X     */
  1129. X    for (;;) {
  1130. X        switch (gettoken()) {
  1131. X            case T_LEFTBRACKET:
  1132. X                rescantoken();
  1133. X                if (!okmat)
  1134. X                    return type;
  1135. X                getmatargs();
  1136. X                type = 0;
  1137. X                break;
  1138. X            case T_PERIOD:
  1139. X                getelement();
  1140. X                type = 0;
  1141. X                break;
  1142. X            case T_LEFTPAREN:
  1143. X                scanerror(T_NULL, "Function calls not allowed as expressions");
  1144. X            default:
  1145. X                rescantoken();
  1146. X                return type;
  1147. X        }
  1148. X    }
  1149. X}
  1150. X
  1151. X
  1152. X/*
  1153. X * Read in a filename for a read or write command.
  1154. X * Both quoted and unquoted filenames are handled here.
  1155. X * The name must be terminated by an end of line or semicolon.
  1156. X * Returns TRUE if the filename was successfully parsed.
  1157. X */
  1158. Xstatic BOOL
  1159. Xgetfilename(name, msg_ok)
  1160. X    char name[PATHSIZE+1];
  1161. X    BOOL msg_ok;        /* TRUE => ok to print error messages */
  1162. X{
  1163. X    (void) tokenmode(TM_NEWLINES | TM_ALLSYMS);
  1164. X    switch (gettoken()) {
  1165. X        case T_STRING:
  1166. X        case T_SYMBOL:
  1167. X            break;
  1168. X        default:
  1169. X            if (msg_ok)
  1170. X                scanerror(T_SEMICOLON, "Filename expected");
  1171. X            return FALSE;
  1172. X    }
  1173. X    strcpy(name, tokenstring());
  1174. X    switch (gettoken()) {
  1175. X        case T_SEMICOLON:
  1176. X        case T_NEWLINE:
  1177. X        case T_EOF:
  1178. X            break;
  1179. X        default:
  1180. X            if (msg_ok)
  1181. X                scanerror(T_SEMICOLON, 
  1182. X                    "Missing semicolon after filename");
  1183. X            return FALSE;
  1184. X    }
  1185. X    return TRUE;
  1186. X}
  1187. X
  1188. X
  1189. X/*
  1190. X * Read the show command and display useful information.
  1191. X */
  1192. Xstatic void
  1193. Xgetshowcommand()
  1194. X{
  1195. X    char name[SYMBOLSIZE+1];
  1196. X
  1197. X    if ((gettoken() != T_SHOW) || (gettoken() != T_SYMBOL)) {
  1198. X        scanerror(T_SEMICOLON, "Bad syntax for SHOW command");
  1199. X        return;
  1200. X    }
  1201. X    strcpy(name, tokenstring());
  1202. X    switch (gettoken()) {
  1203. X        case T_NEWLINE:
  1204. X        case T_SEMICOLON:
  1205. X            break;
  1206. X        default:
  1207. X            scanerror(T_SEMICOLON, "Bad syntax for SHOW command");
  1208. X    }
  1209. X    switch ((int) stringindex("builtins\0globals\0functions\0objfuncs\0memory\0", name)) {
  1210. X        case 1:
  1211. X            showbuiltins();
  1212. X            break;
  1213. X        case 2:
  1214. X            showglobals();
  1215. X            break;
  1216. X        case 3:
  1217. X            showfunctions();
  1218. X            break;
  1219. X        case 4:
  1220. X            showobjfuncs();
  1221. X            break;
  1222. X        case 5:
  1223. X            mem_stats("");
  1224. X            break;
  1225. X        default:
  1226. X            scanerror(T_NULL, "Unknown SHOW parameter \"%s\"", name);
  1227. X    }
  1228. X}
  1229. X
  1230. X
  1231. X/*
  1232. X * Read in a set of matrix index arguments, surrounded with square brackets.
  1233. X * This also handles double square brackets for 'fast indexing'.
  1234. X */
  1235. Xstatic void
  1236. Xgetmatargs()
  1237. X{
  1238. X    int dim;
  1239. X
  1240. X    if (gettoken() != T_LEFTBRACKET) {
  1241. X        scanerror(T_NULL, "Matrix indexing expected");
  1242. X        return;
  1243. X    }
  1244. X    /*
  1245. X     * Parse all levels of the array reference
  1246. X     * Look for the 'fast index' first.
  1247. X     */
  1248. X    if (gettoken() == T_LEFTBRACKET) {
  1249. X        (void) getassignment();
  1250. X        if ((gettoken() != T_RIGHTBRACKET) ||
  1251. X            (gettoken() != T_RIGHTBRACKET)) {
  1252. X                scanerror(T_NULL, "Bad fast index usage");
  1253. X                return;
  1254. X        }
  1255. X        addop(OP_FIADDR);
  1256. X        return;
  1257. X    }
  1258. X    rescantoken();
  1259. X    /*
  1260. X     * Normal indexing with the indexes separated by commas.
  1261. X     * Initialize the flag in the opcode to assume that the array
  1262. X     * element will only be referenced for reading.  If the parser
  1263. X     * finds that the element will be referenced for writing, then
  1264. X     * it will call writeindexop to change the flag in the opcode.
  1265. X     */
  1266. X    dim = 1;
  1267. X    for (;;) {
  1268. X        (void) getassignment();
  1269. X        switch (gettoken()) {
  1270. X            case T_RIGHTBRACKET:
  1271. X                if (gettoken() != T_LEFTBRACKET) {
  1272. X                    rescantoken();
  1273. X                    addoptwo(OP_INDEXADDR, (long) dim,
  1274. X                        (long) FALSE);
  1275. X                    return;
  1276. X                }
  1277. X                /* proceed into comma case */
  1278. X                /*FALLTHRU*/
  1279. X            case T_COMMA:
  1280. X                if (++dim > MAXDIM)
  1281. X                    scanerror(T_NULL, "Too many dimensions for array reference");
  1282. X                break;
  1283. X            default:
  1284. X                rescantoken();
  1285. X                scanerror(T_NULL, "Missing right bracket in array reference");
  1286. X                return;
  1287. X        }
  1288. X    }
  1289. X}
  1290. X
  1291. X
  1292. X/*
  1293. X * Get an element of an object reference.
  1294. X * The leading period which introduces the element has already been read.
  1295. X */
  1296. Xstatic void
  1297. Xgetelement()
  1298. X{
  1299. X    long index;
  1300. X    char name[SYMBOLSIZE+1];
  1301. X
  1302. X    if (!getid(name))
  1303. X        return;
  1304. X    index = findelement(name);
  1305. X    if (index < 0) {
  1306. X        scanerror(T_NULL, "Element \"%s\" is undefined", name);
  1307. X        return;
  1308. X    }
  1309. X    addopone(OP_ELEMADDR, index);
  1310. X}
  1311. X
  1312. X
  1313. X/*
  1314. X * Read in a single symbol name and copy its value into the given buffer.
  1315. X * Returns TRUE if a valid symbol id was found.
  1316. X */
  1317. Xstatic BOOL
  1318. Xgetid(buf)
  1319. X    char buf[SYMBOLSIZE+1];
  1320. X{
  1321. X    int type;
  1322. X
  1323. X    type = gettoken();
  1324. X    if (iskeyword(type)) {
  1325. X        scanerror(T_NULL, "Reserved keyword used as symbol name");
  1326. X        type = T_SYMBOL;
  1327. X    }
  1328. X    if (type != T_SYMBOL) {
  1329. X        rescantoken();
  1330. X        scanerror(T_NULL, "Symbol name expected");
  1331. X        *buf = '\0';
  1332. X        return FALSE;
  1333. X    }
  1334. X    strncpy(buf, tokenstring(), SYMBOLSIZE);
  1335. X    buf[SYMBOLSIZE] = '\0';
  1336. X    return TRUE;
  1337. X}
  1338. X
  1339. X
  1340. X/*
  1341. X * Define a symbol name to be of the specified symbol type.  This also checks
  1342. X * to see if the symbol was already defined in an incompatible manner.
  1343. X */
  1344. Xstatic void
  1345. Xdefinesymbol(name, symtype)
  1346. X    char *name;
  1347. X{
  1348. X    switch (symboltype(name)) {
  1349. X        case SYM_UNDEFINED:
  1350. X        case SYM_GLOBAL:
  1351. X        case SYM_STATIC:
  1352. X            if (symtype == SYM_LOCAL)
  1353. X                (void) addlocal(name);
  1354. X            else
  1355. X                (void) addglobal(name, (symtype == SYM_STATIC));
  1356. X            break;
  1357. X
  1358. X        case SYM_PARAM:
  1359. X        case SYM_LOCAL:
  1360. X            scanerror(T_COMMA, "Variable \"%s\" is already defined", name);
  1361. X            return;
  1362. X    }
  1363. X
  1364. X}
  1365. X
  1366. X
  1367. X/*
  1368. X * Check a symbol name to see if it is known and generate code to reference it.
  1369. X * The symbol can be either a parameter name, a local name, or a global name.
  1370. X * If autodef is true, we automatically define the name as a global symbol
  1371. X * if it is not yet known.
  1372. X */
  1373. Xstatic void
  1374. Xusesymbol(name, autodef)
  1375. X    char *name;        /* symbol name to be checked */
  1376. X    BOOL autodef;
  1377. X{
  1378. X    switch (symboltype(name)) {
  1379. X        case SYM_LOCAL:
  1380. X            addopone(OP_LOCALADDR, (long) findlocal(name));
  1381. X            return;
  1382. X        case SYM_PARAM:
  1383. X            addopone(OP_PARAMADDR, (long) findparam(name));
  1384. X            return;
  1385. X        case SYM_GLOBAL:
  1386. X        case SYM_STATIC:
  1387. X            addopptr(OP_GLOBALADDR, (char *) findglobal(name));
  1388. X            return;
  1389. X    }
  1390. X    /*
  1391. X     * The symbol is not yet defined.
  1392. X     * If we are at the top level and we are allowed to, then define it.
  1393. X     */
  1394. X    if ((curfunc->f_name[0] != '*') || !autodef) {
  1395. X        scanerror(T_NULL, "\"%s\" is undefined", name);
  1396. X        return;
  1397. X    }
  1398. X    (void) addglobal(name, FALSE);
  1399. X    addopptr(OP_GLOBALADDR, (char *) findglobal(name));
  1400. X}
  1401. X
  1402. X
  1403. X/*
  1404. X * Get arguments for a function call.
  1405. X * The name and beginning parenthesis has already been seen.
  1406. X * callargs = [ [ '&' ] assignment  [',' [ '&' ] assignment] ] ')'.
  1407. X */
  1408. Xstatic void
  1409. Xgetcallargs(name)
  1410. X    char *name;        /* name of function */
  1411. X{
  1412. X    long index;        /* function index */
  1413. X    long op;        /* opcode to add */
  1414. X    int argcount;        /* number of arguments */
  1415. X    int type;
  1416. X    BOOL addrflag;
  1417. X
  1418. X    op = OP_CALL;
  1419. X    index = getbuiltinfunc(name);
  1420. X    if (index < 0) {
  1421. X        op = OP_USERCALL;
  1422. X        index = adduserfunc(name);
  1423. X    }
  1424. X    if (gettoken() == T_RIGHTPAREN) {
  1425. X        if (op == OP_CALL)
  1426. X            builtincheck(index, 0);
  1427. X        addopfunction(op, index, 0);
  1428. X        return;
  1429. X    }
  1430. X    rescantoken();
  1431. X    argcount = 0;
  1432. X    for (;;) {
  1433. X        argcount++;
  1434. X        addrflag = (gettoken() == T_AND);
  1435. X        if (!addrflag)
  1436. X            rescantoken();
  1437. X        type = getassignment();
  1438. X        if (addrflag) {
  1439. X            if (isrvalue(type))
  1440. X                scanerror(T_NULL, "Taking address of non-variable");
  1441. X            writeindexop();
  1442. X        }
  1443. X        if (!addrflag && (op != OP_CALL))
  1444. X            addop(OP_GETVALUE);
  1445. X        switch (gettoken()) {
  1446. X            case T_RIGHTPAREN:
  1447. X                if (op == OP_CALL)
  1448. X                    builtincheck(index, argcount);
  1449. X                addopfunction(op, index, argcount);
  1450. X                return;
  1451. X            case T_COMMA:
  1452. X                break;
  1453. X            default:
  1454. X                scanerror(T_SEMICOLON, "Missing right parenthesis in function call");
  1455. X                return;
  1456. X        }
  1457. X    }
  1458. X}
  1459. X
  1460. X/* END CODE */
  1461. SHAR_EOF
  1462. echo "File calc2.9.0/codegen.c is complete"
  1463. chmod 0644 calc2.9.0/codegen.c || echo "restore of calc2.9.0/codegen.c fails"
  1464. set `wc -c calc2.9.0/codegen.c`;Sum=$1
  1465. if test "$Sum" != "41674"
  1466. then echo original size 41674, current size $Sum;fi
  1467. echo "x - extracting calc2.9.0/comfunc.c (Text)"
  1468. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/comfunc.c &&
  1469. X/*
  1470. X * Copyright (c) 1993 David I. Bell
  1471. X * Permission is granted to use, distribute, or modify this source,
  1472. X * provided that this copyright notice remains intact.
  1473. X *
  1474. X * Extended precision complex arithmetic non-primitive routines
  1475. X */
  1476. X
  1477. X#include "cmath.h"
  1478. X
  1479. X
  1480. X/*
  1481. X * Round a complex number to the specified number of decimal places.
  1482. X * This simply means to round each of the components of the number.
  1483. X * Zero decimal places means round to the nearest complex integer.
  1484. X */
  1485. XCOMPLEX *
  1486. Xcround(c, places)
  1487. X    COMPLEX *c;
  1488. X    long places;
  1489. X{
  1490. X    COMPLEX *res;        /* result */
  1491. X
  1492. X    res = comalloc();
  1493. X    res->real = qround(c->real, places);
  1494. X    res->imag = qround(c->imag, places);
  1495. X    return res;
  1496. X}
  1497. X
  1498. X
  1499. X/*
  1500. X * Round a complex number to the specified number of binary decimal places.
  1501. X * This simply means to round each of the components of the number.
  1502. X * Zero binary places means round to the nearest complex integer.
  1503. X */
  1504. XCOMPLEX *
  1505. Xcbround(c, places)
  1506. X    COMPLEX *c;
  1507. X    long places;
  1508. X{
  1509. X    COMPLEX *res;        /* result */
  1510. X
  1511. X    res = comalloc();
  1512. X    res->real = qbround(c->real, places);
  1513. X    res->imag = qbround(c->imag, places);
  1514. X    return res;
  1515. X}
  1516. X
  1517. X
  1518. X/*
  1519. X * Compute the result of raising a complex number to an integer power.
  1520. X */
  1521. XCOMPLEX *
  1522. Xcpowi(c, q)
  1523. X    COMPLEX *c;        /* complex number to be raised */
  1524. X    NUMBER *q;        /* power to raise it to */
  1525. X{
  1526. X    COMPLEX *tmp, *res;    /* temporary values */
  1527. X    long power;        /* power to raise to */
  1528. X    unsigned long bit;    /* current bit value */
  1529. X    int sign;
  1530. X
  1531. X    if (qisfrac(q))
  1532. X        math_error("Raising number to non-integral power");
  1533. X    if (zisbig(q->num))
  1534. X        math_error("Raising number to very large power");
  1535. X    power = (zistiny(q->num) ? z1tol(q->num) : z2tol(q->num));
  1536. X    if (ciszero(c) && (power == 0))
  1537. X        math_error("Raising zero to zeroth power");
  1538. X    sign = 1;
  1539. X    if (qisneg(q))
  1540. X        sign = -1;
  1541. X    /*
  1542. X     * Handle some low powers specially
  1543. X     */
  1544. X    if (power <= 4) {
  1545. X        switch ((int) (power * sign)) {
  1546. X            case 0:
  1547. X                return clink(&_cone_);
  1548. X            case 1:
  1549. X                return clink(c);
  1550. X            case -1:
  1551. X                return cinv(c);
  1552. X            case 2:
  1553. X                return csquare(c);
  1554. X            case -2:
  1555. X                tmp = csquare(c);
  1556. X                res = cinv(tmp);
  1557. X                comfree(tmp);
  1558. X                return res;
  1559. X            case 3:
  1560. X                tmp = csquare(c);
  1561. X                res = cmul(c, tmp);
  1562. X                comfree(tmp);
  1563. X                return res;
  1564. X            case 4:
  1565. X                tmp = csquare(c);
  1566. X                res = csquare(tmp);
  1567. X                comfree(tmp);
  1568. X                return res;
  1569. X        }
  1570. X    }
  1571. X    /*
  1572. X     * Compute the power by squaring and multiplying.
  1573. X     * This uses the left to right method of power raising.
  1574. X     */
  1575. X    bit = TOPFULL;
  1576. X    while ((bit & power) == 0)
  1577. X        bit >>= 1L;
  1578. X    bit >>= 1L;
  1579. X    res = csquare(c);
  1580. X    if (bit & power) {
  1581. X        tmp = cmul(res, c);
  1582. X        comfree(res);
  1583. X        res = tmp;
  1584. X    }
  1585. X    bit >>= 1L;
  1586. X    while (bit) {
  1587. X        tmp = csquare(res);
  1588. X        comfree(res);
  1589. X        res = tmp;
  1590. X        if (bit & power) {
  1591. X            tmp = cmul(res, c);
  1592. X            comfree(res);
  1593. X            res = tmp;
  1594. X        }
  1595. X        bit >>= 1L;
  1596. X    }
  1597. X    if (sign < 0) {
  1598. X        tmp = cinv(res);
  1599. X        comfree(res);
  1600. X        res = tmp;
  1601. X    }
  1602. X    return res;
  1603. X}
  1604. X
  1605. X
  1606. X/*
  1607. X * Calculate the square root of a complex number, with each component
  1608. X * within the specified error.  If the number is a square, then the error
  1609. X * is zero.  For sqrt(a + bi), this calculates:
  1610. X *    R = sqrt(a^2 + b^2)
  1611. X *    U = sqrt((R + abs(a))/2)
  1612. X *    V = b/(2 * U)
  1613. X *    then sqrt(a + bi) = U + Vi if a >= 0,
  1614. X *    or abs(V) + sgn(b) * U  if a < 0
  1615. X */
  1616. XCOMPLEX *
  1617. Xcsqrt(c, epsilon)
  1618. X    COMPLEX *c;
  1619. X    NUMBER *epsilon;
  1620. X{
  1621. X    COMPLEX *r;
  1622. X    NUMBER *A, *B, *R, *U, *V, *tmp1, *tmp2, *epsilon2;
  1623. X    long m, n;
  1624. X
  1625. X    if (ciszero(c) || cisone(c))
  1626. X        return clink(c);
  1627. X    if (cisreal(c)) {
  1628. X        r = comalloc();
  1629. X        if (!qisneg(c->real)) {
  1630. X            r->real = qsqrt(c->real, epsilon);
  1631. X            return r;
  1632. X        }
  1633. X        tmp1 = qneg(c->real);
  1634. X        r->imag = qsqrt(tmp1, epsilon);
  1635. X        qfree(tmp1);
  1636. X        return r;
  1637. X    }
  1638. X
  1639. X    A = qlink(c->real);
  1640. X    B = qlink(c->imag);
  1641. X    n = zhighbit(B->num) - zhighbit(B->den);
  1642. X    if (!qiszero(A)) {
  1643. X        m = zhighbit(A->num) - zhighbit(A->den);
  1644. X        if (m > n)
  1645. X            n = m;
  1646. X    }
  1647. X    epsilon2 = qscale(epsilon, n/2);
  1648. X    R = qhypot(A, B, epsilon2);
  1649. X    qfree(epsilon2);
  1650. X    if (qisneg(A))
  1651. X        tmp1 = qsub(R, A);
  1652. X    else
  1653. X        tmp1 = qadd(R, A);
  1654. X    qfree(A);
  1655. X    tmp2 = qscale(tmp1, -1L);
  1656. X    qfree(tmp1);
  1657. X    U = qsqrt(tmp2, epsilon);
  1658. X    qfree(tmp2);
  1659. X    qfree(R);
  1660. X    if (qiszero(U)) {
  1661. X        qfree(B);
  1662. X        qfree(U);
  1663. X        return clink(&_czero_);
  1664. X    }
  1665. X    tmp1 = qdiv(B, U);
  1666. X    V = qscale(tmp1, -1L);
  1667. X    qfree(tmp1);
  1668. X    r = comalloc();
  1669. X    if (qisneg(c->real)) {
  1670. X        if (qisneg(B)) {    
  1671. X            tmp1 = qneg(U);
  1672. X            qfree(U);
  1673. X            U = tmp1;
  1674. X            tmp2 = qabs(V);
  1675. X            qfree(V);
  1676. X            V = tmp2;
  1677. X        }
  1678. X        r->real = V;
  1679. X        r->imag = U;
  1680. X    } else {
  1681. X        r->real = U;
  1682. X        r->imag = V;
  1683. X    }
  1684. X    qfree(B);
  1685. X    return r;
  1686. X}
  1687. X
  1688. X
  1689. X/*
  1690. X * Take the Nth root of a complex number, where N is a positive integer.
  1691. X * Each component of the result is within the specified error.
  1692. X */
  1693. XCOMPLEX *
  1694. Xcroot(c, q, epsilon)
  1695. X    COMPLEX *c;
  1696. X    NUMBER *q, *epsilon;
  1697. X{
  1698. X    COMPLEX *r;
  1699. X    NUMBER *a2pb2, *root, *tmp1, *tmp2, *epsilon2;
  1700. X
  1701. X    if (qisneg(q) || qiszero(q) || qisfrac(q))
  1702. X        math_error("Taking bad root of complex number");
  1703. X    if (cisone(c) || qisone(q))
  1704. X        return clink(c);
  1705. X    if (qistwo(q))
  1706. X        return csqrt(c, epsilon);
  1707. X    r = comalloc();
  1708. X    if (cisreal(c) && !qisneg(c->real)) {
  1709. X        r->real = qroot(c->real, q, epsilon);
  1710. X        return r;
  1711. X    }
  1712. X    /*
  1713. X     * Calculate the root using the formula:
  1714. X     *    croot(a + bi, n) =
  1715. X     *        cpolar(qroot(a^2 + b^2, 2 * n), qatan2(b, a) / n).
  1716. X     */
  1717. X    epsilon2 = qscale(epsilon, -8L);
  1718. X    tmp1 = qsquare(c->real);
  1719. X    tmp2 = qsquare(c->imag);
  1720. X    a2pb2 = qadd(tmp1, tmp2);
  1721. X    qfree(tmp1);
  1722. X    qfree(tmp2);
  1723. X    tmp1 = qscale(q, 1L);
  1724. X    root = qroot(a2pb2, tmp1, epsilon2);
  1725. X    qfree(a2pb2);
  1726. X    qfree(tmp1);
  1727. X    tmp1 = qatan2(c->imag, c->real, epsilon2);
  1728. X    qfree(epsilon2);
  1729. X    tmp2 = qdiv(tmp1, q);
  1730. X    qfree(tmp1);
  1731. X    r = cpolar(root, tmp2, epsilon);
  1732. X    qfree(root);
  1733. X    qfree(tmp2);
  1734. X    return r;
  1735. X}
  1736. X
  1737. X
  1738. X/*
  1739. X * Calculate the complex exponential function to the desired accuracy.
  1740. X * We use the formula:
  1741. X *    exp(a + bi) = exp(a) * (cos(b) + i * sin(b)).
  1742. X */
  1743. XCOMPLEX *
  1744. Xcexp(c, epsilon)
  1745. X    COMPLEX *c;
  1746. X    NUMBER *epsilon;
  1747. X{
  1748. X    COMPLEX *r;
  1749. X    NUMBER *tmp1, *tmp2, *epsilon2;
  1750. X
  1751. X    if (ciszero(c))
  1752. X        return clink(&_cone_);
  1753. X    r = comalloc();
  1754. X    if (cisreal(c)) {
  1755. X        r->real = qexp(c->real, epsilon);
  1756. X        return r;
  1757. X    }
  1758. X    epsilon2 = qscale(epsilon, -2L);
  1759. X    r->real = qcos(c->imag, epsilon2);
  1760. X    r->imag = qlegtoleg(r->real, epsilon2, _sinisneg_);
  1761. X    if (qiszero(c->real)) {
  1762. X        qfree(epsilon2);
  1763. X        return r;
  1764. X    }
  1765. X    tmp1 = qexp(c->real, epsilon2);
  1766. X    qfree(epsilon2);
  1767. X    tmp2 = qmul(r->real, tmp1);
  1768. X    qfree(r->real);
  1769. X    r->real = tmp2;
  1770. X    tmp2 = qmul(r->imag, tmp1);
  1771. X    qfree(r->imag);
  1772. X    qfree(tmp1);
  1773. X    r->imag = tmp2;
  1774. X    return r;
  1775. X}
  1776. X
  1777. X
  1778. X/*
  1779. X * Calculate the natural logarithm of a complex number within the specified
  1780. X * error.  We use the formula:
  1781. X *    ln(a + bi) = ln(a^2 + b^2) / 2 + i * atan2(b, a).
  1782. X */
  1783. XCOMPLEX *
  1784. Xcln(c, epsilon)
  1785. X    COMPLEX *c;
  1786. X    NUMBER *epsilon;
  1787. X{
  1788. X    COMPLEX *r;
  1789. X    NUMBER *a2b2, *tmp1, *tmp2;
  1790. X
  1791. X    if (ciszero(c))
  1792. X        math_error("Logarithm of zero");
  1793. X    if (cisone(c))
  1794. X        return clink(&_czero_);
  1795. X    r = comalloc();
  1796. X    if (cisreal(c) && !qisneg(c->real)) {
  1797. X        r->real = qln(c->real, epsilon);
  1798. X        return r;
  1799. X    }
  1800. X    tmp1 = qsquare(c->real);
  1801. X    tmp2 = qsquare(c->imag);
  1802. X    a2b2 = qadd(tmp1, tmp2);
  1803. X    qfree(tmp1);
  1804. X    qfree(tmp2);
  1805. X    tmp1 = qln(a2b2, epsilon);
  1806. X    qfree(a2b2);
  1807. X    r->real = qscale(tmp1, -1L);
  1808. X    qfree(tmp1);
  1809. X    r->imag = qatan2(c->imag, c->real, epsilon);
  1810. X    return r;
  1811. X}
  1812. X
  1813. X
  1814. X/*
  1815. X * Calculate the complex cosine within the specified accuracy.
  1816. X * This uses the formula:
  1817. X *    cos(a + bi) = cos(a) * cosh(b) - sin(a) * sinh(b) * i.
  1818. X */
  1819. XCOMPLEX *
  1820. Xccos(c, epsilon)
  1821. X    COMPLEX *c;
  1822. X    NUMBER *epsilon;
  1823. X{
  1824. X    COMPLEX *r;
  1825. X    NUMBER *cosval, *coshval, *tmp1, *tmp2, *tmp3, *epsilon2;
  1826. X    int negimag;
  1827. X
  1828. X    if (ciszero(c))
  1829. X        return clink(&_cone_);
  1830. X    r = comalloc();
  1831. X    if (cisreal(c)) {
  1832. X        r->real = qcos(c->real, epsilon);
  1833. X        return r;
  1834. X    }
  1835. X    if (qiszero(c->real)) {
  1836. X        r->real = qcosh(c->imag, epsilon);
  1837. X        return r;
  1838. X    }
  1839. X    epsilon2 = qscale(epsilon, -2L);
  1840. X    coshval = qcosh(c->imag, epsilon2);
  1841. X    cosval = qcos(c->real, epsilon2);
  1842. X    negimag = !_sinisneg_;
  1843. X    if (qisneg(c->imag))
  1844. X        negimag = !negimag;
  1845. X    r->real = qmul(cosval, coshval);
  1846. X    /*
  1847. X     * Calculate the imaginary part using the formula:
  1848. X     *    sin(a) * sinh(b) = sqrt((1 - a^2) * (b^2 - 1)).
  1849. X     */
  1850. X    tmp1 = qsquare(cosval);
  1851. X    qfree(cosval);
  1852. X    tmp2 = qdec(tmp1);
  1853. X    qfree(tmp1);
  1854. X    tmp1 = qneg(tmp2);
  1855. X    qfree(tmp2);
  1856. X    tmp2 = qsquare(coshval);
  1857. X    qfree(coshval);
  1858. X    tmp3 = qdec(tmp2);
  1859. X    qfree(tmp2);
  1860. X    tmp2 = qmul(tmp1, tmp3);
  1861. X    qfree(tmp1);
  1862. X    qfree(tmp3);
  1863. X    r->imag = qsqrt(tmp2, epsilon2);
  1864. X    qfree(tmp2);
  1865. X    qfree(epsilon2);
  1866. X    if (negimag) {
  1867. X        tmp1 = qneg(r->imag);
  1868. X        qfree(r->imag);
  1869. X        r->imag = tmp1;
  1870. X    }
  1871. X    return r;
  1872. X}
  1873. X
  1874. X
  1875. X/*
  1876. X * Calculate the complex sine within the specified accuracy.
  1877. X * This uses the formula:
  1878. X *    sin(a + bi) = sin(a) * cosh(b) + cos(a) * sinh(b) * i.
  1879. X */
  1880. XCOMPLEX *
  1881. Xcsin(c, epsilon)
  1882. X    COMPLEX *c;
  1883. X    NUMBER *epsilon;
  1884. X{
  1885. X    COMPLEX *r;
  1886. X
  1887. X    NUMBER *cosval, *coshval, *tmp1, *tmp2, *epsilon2;
  1888. X
  1889. X    if (ciszero(c))
  1890. X        return clink(&_czero_);
  1891. X    r = comalloc();
  1892. X    if (cisreal(c)) {
  1893. X        r->real = qsin(c->real, epsilon);
  1894. X        return r;
  1895. X    }
  1896. X    if (qiszero(c->real)) {
  1897. X        r->imag = qsinh(c->imag, epsilon);
  1898. X        return r;
  1899. X    }
  1900. X    epsilon2 = qscale(epsilon, -2L);
  1901. X    coshval = qcosh(c->imag, epsilon2);
  1902. X    cosval = qcos(c->real, epsilon2);
  1903. X    tmp1 = qlegtoleg(cosval, epsilon2, _sinisneg_);
  1904. X    r->real = qmul(tmp1, coshval);
  1905. X    qfree(tmp1);
  1906. X    tmp1 = qsquare(coshval);
  1907. X    qfree(coshval);
  1908. X    tmp2 = qdec(tmp1);
  1909. X    qfree(tmp1);
  1910. X    tmp1 = qsqrt(tmp2, epsilon2);
  1911. X    qfree(tmp2);
  1912. X    r->imag = qmul(tmp1, cosval);
  1913. X    qfree(tmp1);
  1914. X    qfree(cosval);
  1915. X    if (qisneg(c->imag)) {
  1916. X        tmp1 = qneg(r->imag);
  1917. X        qfree(r->imag);
  1918. X        r->imag = tmp1;
  1919. X    }
  1920. X    return r;
  1921. X}
  1922. X
  1923. X
  1924. X/*
  1925. X * Convert a number from polar coordinates to normal complex number form
  1926. X * within the specified accuracy.  This produces the value:
  1927. X *    q1 * cos(q2) + q1 * sin(q2) * i.
  1928. X */
  1929. XCOMPLEX *
  1930. Xcpolar(q1, q2, epsilon)
  1931. X    NUMBER *q1, *q2, *epsilon;
  1932. X{
  1933. X    COMPLEX *r;
  1934. X    NUMBER *tmp, *epsilon2;
  1935. X    long scale;
  1936. X
  1937. X    r = comalloc();
  1938. X    if (qiszero(q1) || qiszero(q2)) {
  1939. X        r->real = qlink(q1);
  1940. X        return r;
  1941. X    }
  1942. X    epsilon2 = epsilon;
  1943. X    if (!qisunit(q1)) {
  1944. X        scale = zhighbit(q1->num) - zhighbit(q1->den) + 1;
  1945. X        if (scale > 0)
  1946. X            epsilon2 = qscale(epsilon, -scale);
  1947. X    }
  1948. X    r->real = qcos(q2, epsilon2);
  1949. X    r->imag = qlegtoleg(r->real, epsilon2, _sinisneg_);
  1950. X    if (epsilon2 != epsilon)
  1951. X        qfree(epsilon2);
  1952. X    if (qisone(q1))
  1953. X        return r;
  1954. X    tmp = qmul(r->real, q1);
  1955. X    qfree(r->real);
  1956. X    r->real = tmp;
  1957. X    tmp = qmul(r->imag, q1);
  1958. X    qfree(r->imag);
  1959. X    r->imag = tmp;
  1960. X    return r;
  1961. X}
  1962. X
  1963. X
  1964. X/*
  1965. X * Raise one complex number to the power of another one to within the
  1966. X * specified error.
  1967. X */
  1968. XCOMPLEX *
  1969. Xcpower(c1, c2, epsilon)
  1970. X    COMPLEX *c1, *c2;
  1971. X    NUMBER *epsilon;
  1972. X{
  1973. X    COMPLEX *tmp1, *tmp2;
  1974. X    NUMBER *epsilon2;
  1975. X
  1976. X    if (cisreal(c2) && qisint(c2->real))
  1977. X        return cpowi(c1, c2->real);
  1978. X    if (cisone(c1) || ciszero(c1))
  1979. X        return clink(c1);
  1980. X    epsilon2 = qscale(epsilon, -4L);
  1981. X    tmp1 = cln(c1, epsilon2);
  1982. X    tmp2 = cmul(tmp1, c2);
  1983. X    comfree(tmp1);
  1984. X    tmp1 = cexp(tmp2, epsilon);
  1985. X    comfree(tmp2);
  1986. X    qfree(epsilon2);
  1987. X    return tmp1;
  1988. X}
  1989. X
  1990. X
  1991. X/*
  1992. X * Return a trivial hash value for a complex number.
  1993. X */
  1994. XHASH
  1995. Xchash(c)
  1996. X    COMPLEX *c;
  1997. X{
  1998. X    HASH hash;
  1999. X
  2000. X    hash = qhash(c->real);
  2001. X    if (!cisreal(c))
  2002. X        hash += qhash(c->imag) * 2000029;
  2003. X    return hash;
  2004. X}
  2005. X
  2006. X
  2007. X/*
  2008. X * Print a complex number in the current output mode.
  2009. X */
  2010. Xvoid
  2011. Xcomprint(c)
  2012. X    COMPLEX *c;
  2013. X{
  2014. X    NUMBER qtmp;
  2015. X
  2016. X    if (_outmode_ == MODE_FRAC) {
  2017. X        cprintfr(c);
  2018. X        return;
  2019. X    }
  2020. X    if (!qiszero(c->real) || qiszero(c->imag))
  2021. X        qprintnum(c->real, MODE_DEFAULT);
  2022. X    qtmp = c->imag[0];
  2023. X    if (qiszero(&qtmp))
  2024. X        return;
  2025. X    if (!qiszero(c->real) && !qisneg(&qtmp))
  2026. X        math_chr('+');
  2027. X    if (qisneg(&qtmp)) {
  2028. X        math_chr('-');
  2029. X        qtmp.num.sign = 0;
  2030. X    }
  2031. X    qprintnum(&qtmp, MODE_DEFAULT);
  2032. X    math_chr('i');
  2033. X}
  2034. X
  2035. X
  2036. X/*
  2037. X * Print a complex number in rational representation.
  2038. X * Example:  2/3-4i/5
  2039. X */
  2040. Xvoid
  2041. Xcprintfr(c)
  2042. X    COMPLEX *c;
  2043. X{
  2044. X    NUMBER *r;
  2045. X    NUMBER *i;
  2046. X
  2047. X    r = c->real;
  2048. X    i = c->imag;
  2049. X    if (!qiszero(r) || qiszero(i))
  2050. X        qprintfr(r, 0L, FALSE);
  2051. X    if (qiszero(i))
  2052. X        return;
  2053. X    if (!qiszero(r) && !qisneg(i))
  2054. X        math_chr('+');
  2055. X    zprintval(i->num, 0L, 0L);
  2056. X    math_chr('i');
  2057. X    if (qisfrac(i)) {
  2058. X        math_chr('/');
  2059. X        zprintval(i->den, 0L, 0L);
  2060. X    }
  2061. X}
  2062. X
  2063. X/* END CODE */
  2064. SHAR_EOF
  2065. chmod 0644 calc2.9.0/comfunc.c || echo "restore of calc2.9.0/comfunc.c fails"
  2066. set `wc -c calc2.9.0/comfunc.c`;Sum=$1
  2067. if test "$Sum" != "11584"
  2068. then echo original size 11584, current size $Sum;fi
  2069. echo "x - extracting calc2.9.0/commath.c (Text)"
  2070. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/commath.c &&
  2071. X/*
  2072. X * Copyright (c) 1993 David I. Bell
  2073. X * Permission is granted to use, distribute, or modify this source,
  2074. X * provided that this copyright notice remains intact.
  2075. X *
  2076. X * Extended precision complex arithmetic primitive routines
  2077. X */
  2078. X
  2079. X#include "cmath.h"
  2080. X
  2081. X
  2082. XCOMPLEX _czero_ =        { &_qzero_, &_qzero_, 1 };
  2083. XCOMPLEX _cone_ =        { &_qone_, &_qzero_, 1 };
  2084. XCOMPLEX _conei_ =        { &_qzero_, &_qone_, 1 };
  2085. X
  2086. Xstatic COMPLEX _cnegone_ =    { &_qnegone_, &_qzero_, 1 };
  2087. X
  2088. X
  2089. X/*
  2090. X * Free list for complex numbers.
  2091. X */
  2092. Xstatic FREELIST freelist = {
  2093. X    sizeof(COMPLEX),    /* size of an item */
  2094. X    100            /* number of free items to keep */
  2095. X};
  2096. X
  2097. X
  2098. X/*
  2099. X * Add two complex numbers.
  2100. X */
  2101. XCOMPLEX *
  2102. Xcadd(c1, c2)
  2103. X    COMPLEX *c1, *c2;
  2104. X{
  2105. X    COMPLEX *r;
  2106. X
  2107. X    if (ciszero(c1))
  2108. X        return clink(c2);
  2109. X    if (ciszero(c2))
  2110. X        return clink(c1);
  2111. X    r = comalloc();
  2112. X    if (!qiszero(c1->real) || !qiszero(c2->real))
  2113. X        r->real = qadd(c1->real, c2->real);
  2114. X    if (!qiszero(c1->imag) || !qiszero(c2->imag))
  2115. X        r->imag = qadd(c1->imag, c2->imag);
  2116. X    return r;
  2117. X}
  2118. X
  2119. X
  2120. X/*
  2121. X * Subtract two complex numbers.
  2122. X */
  2123. XCOMPLEX *
  2124. Xcsub(c1, c2)
  2125. X    COMPLEX *c1, *c2;
  2126. X{
  2127. X    COMPLEX *r;
  2128. X
  2129. X    if ((c1->real == c2->real) && (c1->imag == c2->imag))
  2130. X        return clink(&_czero_);
  2131. X    if (ciszero(c2))
  2132. X        return clink(c1);
  2133. X    r = comalloc();
  2134. X    if (!qiszero(c1->real) || !qiszero(c2->real))
  2135. X        r->real = qsub(c1->real, c2->real);
  2136. X    if (!qiszero(c1->imag) || !qiszero(c2->imag))
  2137. X        r->imag = qsub(c1->imag, c2->imag);
  2138. X    return r;
  2139. X}
  2140. X
  2141. X
  2142. X/*
  2143. X * Multiply two complex numbers.
  2144. X * This saves one multiplication over the obvious algorithm by
  2145. X * trading it for several extra additions, as follows.  Let
  2146. X *    q1 = (a + b) * (c + d)
  2147. X *    q2 = a * c
  2148. X *    q3 = b * d
  2149. X * Then (a+bi) * (c+di) = (q2 - q3) + (q1 - q2 - q3)i.
  2150. X */
  2151. XCOMPLEX *
  2152. Xcmul(c1, c2)
  2153. X    COMPLEX *c1, *c2;
  2154. X{
  2155. X    COMPLEX *r;
  2156. X    NUMBER *q1, *q2, *q3, *q4;
  2157. X
  2158. X    if (ciszero(c1) || ciszero(c2))
  2159. X        return clink(&_czero_);
  2160. X    if (cisone(c1))
  2161. X        return clink(c2);
  2162. X    if (cisone(c2))
  2163. X        return clink(c1);
  2164. X    if (cisreal(c2))
  2165. X        return cmulq(c1, c2->real);
  2166. X    if (cisreal(c1))
  2167. X        return cmulq(c2, c1->real);
  2168. X    /*
  2169. X     * Need to do the full calculation.
  2170. X     */
  2171. X    r = comalloc();
  2172. X    q2 = qadd(c1->real, c1->imag);
  2173. X    q3 = qadd(c2->real, c2->imag);
  2174. X    q1 = qmul(q2, q3);
  2175. X    qfree(q2);
  2176. X    qfree(q3);
  2177. X    q2 = qmul(c1->real, c2->real);
  2178. X    q3 = qmul(c1->imag, c2->imag);
  2179. X    q4 = qadd(q2, q3);
  2180. X    r->real = qsub(q2, q3);
  2181. X    r->imag = qsub(q1, q4);
  2182. X    qfree(q1);
  2183. X    qfree(q2);
  2184. X    qfree(q3);
  2185. X    qfree(q4);
  2186. X    return r;
  2187. X}
  2188. X
  2189. X
  2190. X/*
  2191. X * Square a complex number.
  2192. X */
  2193. XCOMPLEX *
  2194. Xcsquare(c)
  2195. X    COMPLEX *c;
  2196. X{
  2197. X    COMPLEX *r;
  2198. X    NUMBER *q1, *q2;
  2199. X
  2200. X    if (ciszero(c))
  2201. X        return clink(&_czero_);
  2202. X    if (cisrunit(c))
  2203. X        return clink(&_cone_);
  2204. X    if (cisiunit(c))
  2205. X        return clink(&_cnegone_);
  2206. X    r = comalloc();
  2207. X    if (cisreal(c)) {
  2208. X        r->real = qsquare(c->real);
  2209. X        return r;
  2210. X    }
  2211. X    if (cisimag(c)) {
  2212. X        q1 = qsquare(c->imag);
  2213. X        r->real = qneg(q1);
  2214. X        qfree(q1);
  2215. X        return r;
  2216. X    }
  2217. X    q1 = qsquare(c->real);
  2218. X    q2 = qsquare(c->imag);
  2219. X    r->real = qsub(q1, q2);
  2220. X    qfree(q1);
  2221. X    qfree(q2);
  2222. X    q1 = qmul(c->real, c->imag);
  2223. X    r->imag = qscale(q1, 1L);
  2224. X    qfree(q1);
  2225. X    return r;
  2226. X}
  2227. X
  2228. X
  2229. X/*
  2230. X * Divide two complex numbers.
  2231. X */
  2232. XCOMPLEX *
  2233. Xcdiv(c1, c2)
  2234. X    COMPLEX *c1, *c2;
  2235. X{
  2236. X    COMPLEX *r;
  2237. X    NUMBER *q1, *q2, *q3, *den;
  2238. X
  2239. X    if (ciszero(c2))
  2240. X        math_error("Division by zero");
  2241. X    if ((c1->real == c2->real) && (c1->imag == c2->imag))
  2242. X        return clink(&_cone_);
  2243. X    r = comalloc();
  2244. X    if (cisreal(c1) && cisreal(c2)) {
  2245. X        r->real = qdiv(c1->real, c2->real);
  2246. X        return r;
  2247. X    }
  2248. X    if (cisimag(c1) && cisimag(c2)) {
  2249. X        r->real = qdiv(c1->imag, c2->imag);
  2250. X        return r;
  2251. X    }
  2252. X    if (cisimag(c1) && cisreal(c2)) {
  2253. X        r->imag = qdiv(c1->imag, c2->real);
  2254. X        return r;
  2255. X    }
  2256. X    if (cisreal(c1) && cisimag(c2)) {
  2257. X        q1 = qdiv(c1->real, c2->imag);
  2258. X        r->imag = qneg(q1);
  2259. X        qfree(q1);
  2260. X        return r;
  2261. X    }
  2262. X    if (cisreal(c2)) {
  2263. X        r->real = qdiv(c1->real, c2->real);
  2264. X        r->imag = qdiv(c1->imag, c2->real);
  2265. X        return r;
  2266. X    }
  2267. X    q1 = qsquare(c2->real);
  2268. X    q2 = qsquare(c2->imag);
  2269. X    den = qadd(q1, q2);
  2270. X    qfree(q1);
  2271. X    qfree(q2);
  2272. X    q1 = qmul(c1->real, c2->real);
  2273. X    q2 = qmul(c1->imag, c2->imag);
  2274. X    q3 = qadd(q1, q2);
  2275. X    qfree(q1);
  2276. X    qfree(q2);
  2277. X    r->real = qdiv(q3, den);
  2278. X    qfree(q3);
  2279. X    q1 = qmul(c1->real, c2->imag);
  2280. X    q2 = qmul(c1->imag, c2->real);
  2281. X    q3 = qsub(q2, q1);
  2282. X    qfree(q1);
  2283. X    qfree(q2);
  2284. X    r->imag = qdiv(q3, den);
  2285. X    qfree(q3);
  2286. X    qfree(den);
  2287. X    return r;
  2288. X}
  2289. X
  2290. X
  2291. X/*
  2292. X * Invert a complex number.
  2293. X */
  2294. XCOMPLEX *
  2295. Xcinv(c)
  2296. X    COMPLEX *c;
  2297. X{
  2298. X    COMPLEX *r;
  2299. X    NUMBER *q1, *q2, *den;
  2300. X
  2301. X    if (ciszero(c))
  2302. X        math_error("Inverting zero");
  2303. X    r = comalloc();
  2304. X    if (cisreal(c)) {
  2305. X        r->real = qinv(c->real);
  2306. X        return r;
  2307. X    }
  2308. X    if (cisimag(c)) {
  2309. X        q1 = qinv(c->imag);
  2310. X        r->imag = qneg(q1);
  2311. X        qfree(q1);
  2312. X        return r;
  2313. X    }
  2314. X    q1 = qsquare(c->real);
  2315. X    q2 = qsquare(c->imag);
  2316. X    den = qadd(q1, q2);
  2317. X    qfree(q1);
  2318. X    qfree(q2);
  2319. X    r->real = qdiv(c->real, den);
  2320. X    q1 = qdiv(c->imag, den);
  2321. X    r->imag = qneg(q1);
  2322. X    qfree(q1);
  2323. X    qfree(den);
  2324. X    return r;
  2325. X}
  2326. X
  2327. X
  2328. X/*
  2329. X * Negate a complex number.
  2330. X */
  2331. XCOMPLEX *
  2332. Xcneg(c)
  2333. X    COMPLEX *c;
  2334. X{
  2335. X    COMPLEX *r;
  2336. X
  2337. X    if (ciszero(c))
  2338. X        return clink(&_czero_);
  2339. X    r = comalloc();
  2340. X    if (!qiszero(c->real))
  2341. X        r->real = qneg(c->real);
  2342. X    if (!qiszero(c->imag))
  2343. X        r->imag = qneg(c->imag);
  2344. X    return r;
  2345. X}
  2346. X
  2347. X
  2348. X/*
  2349. X * Take the integer part of a complex number.
  2350. X * This means take the integer part of both components.
  2351. X */
  2352. XCOMPLEX *
  2353. Xcint(c)
  2354. X    COMPLEX *c;
  2355. X{
  2356. X    COMPLEX *r;
  2357. X
  2358. X    if (cisint(c))
  2359. X        return clink(c);
  2360. X    r = comalloc();
  2361. X    r->real = qint(c->real);
  2362. X    r->imag = qint(c->imag);
  2363. X    return r;
  2364. X}
  2365. X
  2366. X
  2367. X/*
  2368. X * Take the fractional part of a complex number.
  2369. X * This means take the fractional part of both components.
  2370. X */
  2371. XCOMPLEX *
  2372. Xcfrac(c)
  2373. X    COMPLEX *c;
  2374. X{
  2375. X    COMPLEX *r;
  2376. X
  2377. X    if (cisint(c))
  2378. X        return clink(&_czero_);
  2379. X    r = comalloc();
  2380. X    r->real = qfrac(c->real);
  2381. X    r->imag = qfrac(c->imag);
  2382. X    return r;
  2383. X}
  2384. X
  2385. X
  2386. X/*
  2387. X * Take the conjugate of a complex number.
  2388. X * This negates the complex part.
  2389. X */
  2390. XCOMPLEX *
  2391. Xcconj(c)
  2392. X    COMPLEX *c;
  2393. X{
  2394. X    COMPLEX *r;
  2395. X
  2396. X    if (cisreal(c))
  2397. X        return clink(c);
  2398. X    r = comalloc();
  2399. X    if (!qiszero(c->real))
  2400. X        r->real = qlink(c->real);
  2401. X    r->imag = qneg(c->imag);
  2402. X    return r;
  2403. X}
  2404. X
  2405. X
  2406. X/*
  2407. X * Return the real part of a complex number.
  2408. X */
  2409. XCOMPLEX *
  2410. Xcreal(c)
  2411. X    COMPLEX *c;
  2412. X{
  2413. X    COMPLEX *r;
  2414. X
  2415. X    if (cisreal(c))
  2416. X        return clink(c);
  2417. X    r = comalloc();
  2418. X    if (!qiszero(c->real))
  2419. X        r->real = qlink(c->real);
  2420. X    return r;
  2421. X}
  2422. X
  2423. X
  2424. X/*
  2425. X * Return the imaginary part of a complex number as a real.
  2426. X */
  2427. XCOMPLEX *
  2428. Xcimag(c)
  2429. X    COMPLEX *c;
  2430. X{
  2431. X    COMPLEX *r;
  2432. X
  2433. X    if (cisreal(c))
  2434. X        return clink(&_czero_);
  2435. X    r = comalloc();
  2436. X    r->real = qlink(c->imag);
  2437. X    return r;
  2438. X}
  2439. X
  2440. X
  2441. X/*
  2442. X * Add a real number to a complex number.
  2443. X */
  2444. XCOMPLEX *
  2445. Xcaddq(c, q)
  2446. X    COMPLEX *c;
  2447. X    NUMBER *q;
  2448. X{
  2449. X    COMPLEX *r;
  2450. X
  2451. X    if (qiszero(q))
  2452. X        return clink(c);
  2453. X    r = comalloc();
  2454. X    r->real = qadd(c->real, q);
  2455. X    r->imag = qlink(c->imag);
  2456. X    return r;
  2457. X}
  2458. X
  2459. X
  2460. X/*
  2461. X * Subtract a real number from a complex number.
  2462. X */
  2463. XCOMPLEX *
  2464. Xcsubq(c, q)
  2465. X    COMPLEX *c;
  2466. X    NUMBER *q;
  2467. X{
  2468. X    COMPLEX *r;
  2469. X
  2470. X    if (qiszero(q))
  2471. X        return clink(c);
  2472. X    r = comalloc();
  2473. X    r->real = qsub(c->real, q);
  2474. X    r->imag = qlink(c->imag);
  2475. X    return r;
  2476. X}
  2477. X
  2478. X
  2479. X/*
  2480. X * Shift the components of a complex number left by the specified
  2481. X * number of bits.  Negative values shift to the right.
  2482. X */
  2483. XCOMPLEX *
  2484. Xcshift(c, n)
  2485. X    COMPLEX *c;
  2486. X    long n;
  2487. X{
  2488. X    COMPLEX *r;
  2489. X
  2490. X    if (ciszero(c) || (n == 0))
  2491. X        return clink(c);
  2492. X    r = comalloc();
  2493. X    r->real = qshift(c->real, n);
  2494. X    r->imag = qshift(c->imag, n);
  2495. X    return r;
  2496. X}
  2497. X
  2498. X
  2499. X/*
  2500. X * Scale a complex number by a power of two.
  2501. X */
  2502. XCOMPLEX *
  2503. Xcscale(c, n)
  2504. X    COMPLEX *c;
  2505. X    long n;
  2506. X{
  2507. X    COMPLEX *r;
  2508. X
  2509. X    if (ciszero(c) || (n == 0))
  2510. X        return clink(c);
  2511. X    r = comalloc();
  2512. X    r->real = qscale(c->real, n);
  2513. X    r->imag = qscale(c->imag, n);
  2514. X    return r;
  2515. X}
  2516. X
  2517. X
  2518. X/*
  2519. X * Multiply a complex number by a real number.
  2520. X */
  2521. XCOMPLEX *
  2522. Xcmulq(c, q)
  2523. X    COMPLEX *c;
  2524. X    NUMBER *q;
  2525. X{
  2526. X    COMPLEX *r;
  2527. X
  2528. X    if (qiszero(q))
  2529. X        return clink(&_czero_);
  2530. X    if (qisone(q))
  2531. X        return clink(c);
  2532. X    if (qisnegone(q))
  2533. X        return cneg(c);
  2534. X    r = comalloc();
  2535. X    r->real = qmul(c->real, q);
  2536. X    r->imag = qmul(c->imag, q);
  2537. X    return r;
  2538. X}
  2539. X
  2540. X
  2541. X/*
  2542. X * Divide a complex number by a real number.
  2543. X */
  2544. XCOMPLEX *
  2545. Xcdivq(c, q)
  2546. X    COMPLEX *c;
  2547. X    NUMBER *q;
  2548. X{
  2549. X    COMPLEX *r;
  2550. X
  2551. X    if (qiszero(q))
  2552. X        math_error("Division by zero");
  2553. X    if (qisone(q))
  2554. X        return clink(c);
  2555. X    if (qisnegone(q))
  2556. X        return cneg(c);
  2557. X    r = comalloc();
  2558. X    r->real = qdiv(c->real, q);
  2559. X    r->imag = qdiv(c->imag, q);
  2560. X    return r;
  2561. X}
  2562. X
  2563. X
  2564. X/*
  2565. X * Take the integer quotient of a complex number by a real number.
  2566. X * This is defined to be the result of doing the quotient for each component.
  2567. X */
  2568. XCOMPLEX *
  2569. Xcquoq(c, q)
  2570. X    COMPLEX *c;
  2571. X    NUMBER *q;
  2572. X{
  2573. X    COMPLEX *r;
  2574. X
  2575. X    if (qiszero(q))
  2576. X        math_error("Division by zero");
  2577. X    r = comalloc();
  2578. X    r->real = qquo(c->real, q);
  2579. X    r->imag = qquo(c->imag, q);
  2580. X    return r;
  2581. X}
  2582. X
  2583. X
  2584. X/*
  2585. X * Take the modulus of a complex number by a real number.
  2586. X * This is defined to be the result of doing the modulo for each component.
  2587. X */
  2588. XCOMPLEX *
  2589. Xcmodq(c, q)
  2590. X    COMPLEX *c;
  2591. X    NUMBER *q;
  2592. X{
  2593. X    COMPLEX *r;
  2594. X
  2595. X    if (qiszero(q))
  2596. X        math_error("Division by zero");
  2597. X    r = comalloc();
  2598. X    r->real = qmod(c->real, q);
  2599. X    r->imag = qmod(c->imag, q);
  2600. X    return r;
  2601. X}
  2602. X
  2603. X
  2604. X/*
  2605. X * Construct a complex number given the real and imaginary components.
  2606. X */
  2607. XCOMPLEX *
  2608. Xqqtoc(q1, q2)
  2609. X    NUMBER *q1, *q2;
  2610. X{
  2611. X    COMPLEX *r;
  2612. X
  2613. X    if (qiszero(q1) && qiszero(q2))
  2614. X        return clink(&_czero_);
  2615. X    r = comalloc();
  2616. X    if (!qiszero(q1))
  2617. X        r->real = qlink(q1);
  2618. X    if (!qiszero(q2))
  2619. X        r->imag = qlink(q2);
  2620. X    return r;
  2621. X}
  2622. X
  2623. X
  2624. X/*
  2625. X * Compare two complex numbers for equality, returning FALSE if they are equal,
  2626. X * and TRUE if they differ.
  2627. X */
  2628. XBOOL
  2629. Xccmp(c1, c2)
  2630. X    COMPLEX *c1, *c2;
  2631. X{
  2632. X    BOOL i;
  2633. X
  2634. X    i = qcmp(c1->real, c2->real);
  2635. X    if (!i)
  2636. X        i = qcmp(c1->imag, c2->imag);
  2637. X    return i;
  2638. X}
  2639. X
  2640. X
  2641. X/*
  2642. X * Allocate a new complex number.
  2643. X */
  2644. XCOMPLEX *
  2645. Xcomalloc()
  2646. X{
  2647. X    COMPLEX *r;
  2648. X
  2649. X    r = (COMPLEX *) allocitem(&freelist);
  2650. X    if (r == NULL)
  2651. X        math_error("Cannot allocate complex number");
  2652. X    r->links = 1;
  2653. X    r->real = qlink(&_qzero_);
  2654. X    r->imag = qlink(&_qzero_);
  2655. X    return r;
  2656. X}
  2657. X
  2658. X
  2659. X/*
  2660. X * Free a complex number.
  2661. X */
  2662. Xvoid
  2663. Xcomfree(c)
  2664. X    COMPLEX *c;
  2665. X{
  2666. X    if (--(c->links) > 0)
  2667. X        return;
  2668. X    qfree(c->real);
  2669. X    qfree(c->imag);
  2670. X    freeitem(&freelist, (FREEITEM *) c);
  2671. X}
  2672. X
  2673. X/* END CODE */
  2674. SHAR_EOF
  2675. chmod 0644 calc2.9.0/commath.c || echo "restore of calc2.9.0/commath.c fails"
  2676. set `wc -c calc2.9.0/commath.c`;Sum=$1
  2677. if test "$Sum" != "9628"
  2678. then echo original size 9628, current size $Sum;fi
  2679. echo "x - extracting calc2.9.0/config.c (Text)"
  2680. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/config.c &&
  2681. X/*
  2682. X * Copyright (c) 1993 David I. Bell
  2683. X * Permission is granted to use, distribute, or modify this source,
  2684. X * provided that this copyright notice remains intact.
  2685. X *
  2686. X * Configuration routines.
  2687. X */
  2688. X
  2689. X#include "calc.h"
  2690. X
  2691. X
  2692. X/*
  2693. X * Configuration parameter name and type.
  2694. X */
  2695. Xtypedef struct {
  2696. X    char *name;    /* name of configuration string */
  2697. X    int type;    /* type for configuration */
  2698. X} CONFIG;
  2699. X
  2700. X
  2701. X/*
  2702. X * Table of configuration types that can be set or read.
  2703. X */
  2704. Xstatic CONFIG configs[] = {
  2705. X    "trace",    CONFIG_TRACE,
  2706. X    "display",    CONFIG_DISPLAY,
  2707. X    "epsilon",    CONFIG_EPSILON,
  2708. X    "mode",        CONFIG_MODE,
  2709. X    "maxprint",    CONFIG_MAXPRINT,
  2710. X    "mul2",        CONFIG_MUL2,
  2711. X    "sq2",        CONFIG_SQ2,
  2712. X    "pow2",        CONFIG_POW2,
  2713. X    "redc2",    CONFIG_REDC2,
  2714. X    NULL,        0
  2715. X};
  2716. X
  2717. X
  2718. X/*
  2719. X * Possible output modes.
  2720. X */
  2721. Xstatic CONFIG modes[] = {
  2722. X    "frac",        MODE_FRAC,
  2723. X    "decimal",    MODE_FRAC,
  2724. X    "dec",        MODE_FRAC,
  2725. X    "int",        MODE_INT,
  2726. X    "real",        MODE_REAL,
  2727. X    "exp",        MODE_EXP,
  2728. X    "hexadecimal",    MODE_HEX,
  2729. X    "hex",        MODE_HEX,
  2730. X    "octal",    MODE_OCTAL,
  2731. X    "oct",        MODE_OCTAL,
  2732. X    "binary",    MODE_BINARY,
  2733. X    "bin",        MODE_BINARY,
  2734. X    NULL,        0
  2735. X};
  2736. X
  2737. X
  2738. X/*
  2739. X * Given a string value which represents a configuration name, return
  2740. X * the configuration type for that string.  Returns negative type if
  2741. X * the string is unknown.
  2742. X */
  2743. Xint
  2744. Xconfigtype(name)
  2745. X    char *name;        /* configuration name */
  2746. X{
  2747. X    CONFIG *cp;        /* current config pointer */
  2748. X
  2749. X    for (cp = configs; cp->name; cp++) {
  2750. X        if (strcmp(cp->name, name) == 0)
  2751. X            return cp->type;
  2752. X    }
  2753. X    return -1;
  2754. X}
  2755. X
  2756. X
  2757. X/*
  2758. X * Given the name of a mode, convert it to the internal format.
  2759. X * Returns -1 if the string is unknown.
  2760. X */
  2761. Xstatic int
  2762. Xmodetype(name)
  2763. X    char *name;        /* mode name */
  2764. X{
  2765. X    CONFIG *cp;        /* current config pointer */
  2766. X
  2767. X    for (cp = modes; cp->name; cp++) {
  2768. X        if (strcmp(cp->name, name) == 0)
  2769. X            return cp->type;
  2770. X    }
  2771. X    return -1;
  2772. X}
  2773. X
  2774. X
  2775. X/*
  2776. X * Given the mode type, convert it to a string representing that mode.
  2777. X * Where there are multiple strings representing the same mode, the first
  2778. X * one in the table is used.  Returns NULL if the node type is unknown.
  2779. X * The returned string cannot be modified.
  2780. X */
  2781. Xstatic char *
  2782. Xmodename(type)
  2783. X{
  2784. X    CONFIG *cp;        /* current config pointer */
  2785. X
  2786. X    for (cp = modes; cp->name; cp++) {
  2787. X        if (type == cp->type)
  2788. X            return cp->name;
  2789. X    }
  2790. X    return NULL;
  2791. X}
  2792. X
  2793. X
  2794. X/*
  2795. X * Set the specified configuration type to the specified value.
  2796. X * An error is generated if the type number or value is illegal.
  2797. X */
  2798. Xvoid
  2799. Xsetconfig(type, vp)
  2800. X    VALUE *vp;
  2801. X{
  2802. X    NUMBER *q;
  2803. X    long temp;
  2804. X
  2805. X    switch (type) {
  2806. X        case CONFIG_TRACE:
  2807. X            if (vp->v_type != V_NUM)
  2808. X                math_error("Non-numeric for trace");
  2809. X            q = vp->v_num;
  2810. X            temp = qtoi(q);
  2811. X            if (qisfrac(q) || !zistiny(q->num) ||
  2812. X                ((unsigned long) temp > TRACE_MAX))
  2813. X                    math_error("Bad trace value");
  2814. X            traceflags = (FLAG)temp;
  2815. X            break;
  2816. X
  2817. X        case CONFIG_DISPLAY:
  2818. X            if (vp->v_type != V_NUM)
  2819. X                math_error("Non-numeric for display");
  2820. X            q = vp->v_num;
  2821. X            temp = qtoi(q);
  2822. X            if (qisfrac(q) || qisneg(q) || !zistiny(q->num))
  2823. X                temp = -1;
  2824. X            math_setdigits(temp);
  2825. X            break;
  2826. X
  2827. X        case CONFIG_MODE:
  2828. X            if (vp->v_type != V_STR)
  2829. X                math_error("Non-string for mode");
  2830. X            temp = modetype(vp->v_str);
  2831. X            if (temp < 0)
  2832. X                math_error("Unknown mode \"%s\"", vp->v_str);
  2833. X            math_setmode((int) temp);
  2834. X            break;
  2835. X
  2836. X        case CONFIG_EPSILON:
  2837. X            if (vp->v_type != V_NUM)
  2838. X                math_error("Non-numeric for epsilon");
  2839. X            setepsilon(vp->v_num);
  2840. X            break;
  2841. X
  2842. X        case CONFIG_MAXPRINT:
  2843. X            if (vp->v_type != V_NUM)
  2844. X                math_error("Non-numeric for maxprint");
  2845. X            q = vp->v_num;
  2846. X            temp = qtoi(q);
  2847. X            if (qisfrac(q) || qisneg(q) || !zistiny(q->num))
  2848. X                temp = -1;
  2849. X            if (temp < 0)
  2850. X                math_error("Maxprint value is out of range");
  2851. SHAR_EOF
  2852. echo "End of part 3"
  2853. echo "File calc2.9.0/config.c is continued in part 4"
  2854. echo "4" > s2_seq_.tmp
  2855. exit 0
  2856.