home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / calc-2.9.0 / part05 < prev    next >
Encoding:
Text File  |  1993-12-07  |  59.7 KB  |  2,990 lines

  1. Newsgroups: comp.sources.unix
  2. From: dbell@canb.auug.org.au (David I. Bell)
  3. Subject: v27i132: calc-2.9.0 - arbitrary precision C-like programmable calculator, Part05/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 132
  10. Archive-Name: calc-2.9.0/part05
  11.  
  12. #!/bin/sh
  13. # this is part 5 of a multipart archive
  14. # do not concatenate these parts, unpack them in order with /bin/sh
  15. # file calc2.9.0/func.c continued
  16. #
  17. CurArch=5
  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/func.c"
  28. sed 's/^X//' << 'SHAR_EOF' >> calc2.9.0/func.c
  29. X        math_error("Non-numeric positions for substr");
  30. X    q1 = v2->v_num;
  31. X    q2 = v3->v_num;
  32. X    if (qisfrac(q1) || qisneg(q1) || qisfrac(q2) || qisneg(q2))
  33. X        math_error("Illegal positions for substr");
  34. X    i1 = qtoi(q1);
  35. X    i2 = qtoi(q2);
  36. X    cp = v1->v_str;
  37. X    len = strlen(cp);
  38. X    result.v_type = V_STR;
  39. X    if (i1 > 0)
  40. X        i1--;
  41. X    if (i1 >= len) {    /* indexing off of end */
  42. X        result.v_subtype = V_STRLITERAL;
  43. X        result.v_str = "";
  44. X        return result;
  45. X    }
  46. X    cp += i1;
  47. X    len -= i1;
  48. X    if ((i2 >= len) && (v1->v_subtype == V_STRLITERAL)) {
  49. X        result.v_subtype = V_STRLITERAL;
  50. X        result.v_str = cp;
  51. X        return result;
  52. X    }
  53. X    if (len > i2)
  54. X        len = i2;
  55. X    if (len == 1) {
  56. X        result.v_subtype = V_STRLITERAL;
  57. X        result.v_str = charstr(*cp);
  58. X        return result;
  59. X    }
  60. X    result.v_subtype = V_STRALLOC;
  61. X    result.v_str = (char *)malloc(len + 1);
  62. X    if (result.v_str == NULL)
  63. X        math_error("No memory for substr");
  64. X    strncpy(result.v_str, cp, len);
  65. X    result.v_str[len] = '\0';
  66. X    return result;
  67. X}
  68. X
  69. X
  70. Xstatic VALUE
  71. Xf_char(vp)
  72. X    VALUE *vp;
  73. X{
  74. X    long num;
  75. X    NUMBER *q;
  76. X    VALUE result;
  77. X
  78. X    if (vp->v_type != V_NUM)
  79. X        math_error("Non-numeric argument for char");
  80. X    q = vp->v_num;
  81. X    num = qtoi(q);
  82. X    if (qisneg(q) || qisfrac(q) || zisbig(q->num) || (num > 255))
  83. X        math_error("Illegal number for char");
  84. X    result.v_type = V_STR;
  85. X    result.v_subtype = V_STRLITERAL;
  86. X    result.v_str = charstr((int) num);
  87. X    return result;
  88. X}
  89. X
  90. X
  91. Xstatic VALUE
  92. Xf_ord(vp)
  93. X    VALUE *vp;
  94. X{
  95. X    char *str;
  96. X    VALUE result;
  97. X
  98. X    if (vp->v_type != V_STR)
  99. X        math_error("Non-string argument for ord");
  100. X    str = vp->v_str;
  101. X    if (str[0] && str[1])
  102. X        math_error("Multi-character string given for ord");
  103. X    result.v_type = V_NUM;
  104. X    result.v_num = itoq((long) (*str & 0xff));
  105. X    return result;
  106. X}
  107. X
  108. X
  109. Xstatic VALUE
  110. Xf_size(vp)
  111. X    VALUE *vp;
  112. X{
  113. X    long count;
  114. X    VALUE result;
  115. X
  116. X    switch (vp->v_type) {
  117. X        case V_NULL:    count = 0; break;
  118. X        case V_MAT:    count = vp->v_mat->m_size; break;
  119. X        case V_LIST:    count = vp->v_list->l_count; break;
  120. X        case V_ASSOC:    count = vp->v_assoc->a_count; break;
  121. X        case V_OBJ:    count = vp->v_obj->o_actions->count; break;
  122. X        default:    count = 1; break;
  123. X    }
  124. X    result.v_type = V_NUM;
  125. X    result.v_num = itoq(count);
  126. X    return result;
  127. X}
  128. X
  129. X
  130. Xstatic VALUE
  131. Xf_search(count, vals)
  132. X    VALUE **vals;
  133. X{
  134. X    VALUE *v1, *v2;
  135. X    NUMBER *q;
  136. X    long start;
  137. X    long index;
  138. X    VALUE result;
  139. X
  140. X    v1 = *vals++;
  141. X    v2 = *vals++;
  142. X    start = 0;
  143. X    if (count == 3) {
  144. X        if ((*vals)->v_type != V_NUM)
  145. X            math_error("Non-numeric start index for search");
  146. X        q = (*vals)->v_num;
  147. X        if (qisfrac(q) || qisneg(q))
  148. X            math_error("Bad start index for search");
  149. X        start = qtoi(q);
  150. X    }
  151. X    switch (v1->v_type) {
  152. X        case V_MAT:
  153. X            index = matsearch(v1->v_mat, v2, start);
  154. X            break;
  155. X        case V_LIST:
  156. X            index = listsearch(v1->v_list, v2, start);
  157. X            break;
  158. X        case V_ASSOC:
  159. X            index = assocsearch(v1->v_assoc, v2, start);
  160. X            break;
  161. X        default:
  162. X            math_error("Bad argument type for search");
  163. X    }
  164. X    result.v_type = V_NULL;
  165. X    if (index >= 0) {
  166. X        result.v_type = V_NUM;
  167. X        result.v_num = itoq(index);
  168. X    }
  169. X    return result;
  170. X}
  171. X
  172. X
  173. Xstatic VALUE
  174. Xf_rsearch(count, vals)
  175. X    VALUE **vals;
  176. X{
  177. X    VALUE *v1, *v2;
  178. X    NUMBER *q;
  179. X    long start;
  180. X    long index;
  181. X    VALUE result;
  182. X
  183. X    v1 = *vals++;
  184. X    v2 = *vals++;
  185. X    start = MAXFULL;
  186. X    if (count == 3) {
  187. X        if ((*vals)->v_type != V_NUM)
  188. X            math_error("Non-numeric start index for rsearch");
  189. X        q = (*vals)->v_num;
  190. X        if (qisfrac(q) || qisneg(q))
  191. X            math_error("Bad start index for rsearch");
  192. X        start = qtoi(q);
  193. X    }
  194. X    switch (v1->v_type) {
  195. X        case V_MAT:
  196. X            index = matrsearch(v1->v_mat, v2, start);
  197. X            break;
  198. X        case V_LIST:
  199. X            index = listrsearch(v1->v_list, v2, start);
  200. X            break;
  201. X        case V_ASSOC:
  202. X            index = assocrsearch(v1->v_assoc, v2, start);
  203. X            break;
  204. X        default:
  205. X            math_error("Bad argument type for rsearch");
  206. X    }
  207. X    result.v_type = V_NULL;
  208. X    if (index >= 0) {
  209. X        result.v_type = V_NUM;
  210. X        result.v_num = itoq(index);
  211. X    }
  212. X    return result;
  213. X}
  214. X
  215. X
  216. Xstatic VALUE
  217. Xf_list(count, vals)
  218. X    VALUE **vals;
  219. X{
  220. X    VALUE result;
  221. X
  222. X    result.v_type = V_LIST;
  223. X    result.v_list = listalloc();
  224. X    while (count-- > 0)
  225. X        insertlistlast(result.v_list, *vals++);
  226. X    return result;
  227. X}
  228. X
  229. X
  230. X/*ARGSUSED*/
  231. Xstatic VALUE
  232. Xf_assoc(count, vals)
  233. X    VALUE **vals;
  234. X{
  235. X    VALUE result;
  236. X
  237. X    result.v_type = V_ASSOC;
  238. X    result.v_assoc = assocalloc(0L);
  239. X    return result;
  240. X}
  241. X
  242. X
  243. Xstatic VALUE
  244. Xf_listinsert(v1, v2, v3)
  245. X    VALUE *v1, *v2, *v3;
  246. X{
  247. X    VALUE result;
  248. X
  249. X    if ((v1->v_type != V_ADDR) || (v1->v_addr->v_type != V_LIST))
  250. X        math_error("Inserting into non-list variable");
  251. X    if (v2->v_type == V_ADDR)
  252. X        v2 = v2->v_addr;
  253. X    if ((v2->v_type != V_NUM) || qisfrac(v2->v_num))
  254. X        math_error("Non-integral index for list insert");
  255. X    if (v3->v_type == V_ADDR)
  256. X        v3 = v3->v_addr;
  257. X    insertlistmiddle(v1->v_addr->v_list, qtoi(v2->v_num), v3);
  258. X    result.v_type = V_NULL;
  259. X    return result;
  260. X}
  261. X
  262. X
  263. Xstatic VALUE
  264. Xf_listpush(v1, v2)
  265. X    VALUE *v1, *v2;
  266. X{
  267. X    VALUE result;
  268. X
  269. X    if ((v1->v_type != V_ADDR) || (v1->v_addr->v_type != V_LIST))
  270. X        math_error("Pushing onto non-list variable");
  271. X    if (v2->v_type == V_ADDR)
  272. X        v2 = v2->v_addr;
  273. X    insertlistfirst(v1->v_addr->v_list, v2);
  274. X    result.v_type = V_NULL;
  275. X    return result;
  276. X}
  277. X
  278. X
  279. Xstatic VALUE
  280. Xf_listappend(v1, v2)
  281. X    VALUE *v1, *v2;
  282. X{
  283. X    VALUE result;
  284. X
  285. X    if ((v1->v_type != V_ADDR) || (v1->v_addr->v_type != V_LIST))
  286. X        math_error("Appending to non-list variable");
  287. X    if (v2->v_type == V_ADDR)
  288. X        v2 = v2->v_addr;
  289. X    insertlistlast(v1->v_addr->v_list, v2);
  290. X    result.v_type = V_NULL;
  291. X    return result;
  292. X}
  293. X
  294. X
  295. Xstatic VALUE
  296. Xf_listdelete(v1, v2)
  297. X    VALUE *v1, *v2;
  298. X{
  299. X    VALUE result;
  300. X
  301. X    if ((v1->v_type != V_ADDR) || (v1->v_addr->v_type != V_LIST))
  302. X        math_error("Deleting from non-list variable");
  303. X    if (v2->v_type == V_ADDR)
  304. X        v2 = v2->v_addr;
  305. X    if ((v2->v_type != V_NUM) || qisfrac(v2->v_num))
  306. X        math_error("Non-integral index for list delete");
  307. X    removelistmiddle(v1->v_addr->v_list, qtoi(v2->v_num), &result);
  308. X    return result;
  309. X}
  310. X
  311. X
  312. Xstatic VALUE
  313. Xf_listpop(vp)
  314. X    VALUE *vp;
  315. X{
  316. X    VALUE result;
  317. X
  318. X    if ((vp->v_type != V_ADDR) || (vp->v_addr->v_type != V_LIST))
  319. X        math_error("Popping from non-list variable");
  320. X    removelistfirst(vp->v_addr->v_list, &result);
  321. X    return result;
  322. X}
  323. X
  324. X
  325. Xstatic VALUE
  326. Xf_listremove(vp)
  327. X    VALUE *vp;
  328. X{
  329. X    VALUE result;
  330. X
  331. X    if ((vp->v_type != V_ADDR) || (vp->v_addr->v_type != V_LIST))
  332. X        math_error("Removing from non-list variable");
  333. X    removelistlast(vp->v_addr->v_list, &result);
  334. X    return result;
  335. X}
  336. X
  337. X
  338. X/*
  339. X * Return the current runtime of calc in seconds.
  340. X * This is the user mode time only.
  341. X */
  342. Xstatic NUMBER *
  343. Xf_runtime()
  344. X{
  345. X    struct tms buf;
  346. X
  347. X    times(&buf);
  348. X    return iitoq((long) buf.tms_utime, (long) CLK_TCK);
  349. X}
  350. X
  351. X
  352. Xstatic VALUE
  353. Xf_fopen(v1, v2)
  354. X    VALUE *v1, *v2;
  355. X{
  356. X    VALUE result;
  357. X    FILEID id;
  358. X
  359. X    if (v1->v_type != V_STR)
  360. X        math_error("Non-string filename for fopen");
  361. X    if (v2->v_type != V_STR)
  362. X        math_error("Non-string mode for fopen");
  363. X    id = openid(v1->v_str, v2->v_str);
  364. X    if (id == FILEID_NONE) {
  365. X        result.v_type = V_NUM;
  366. X        result.v_num = itoq((long) errno);
  367. X    } else {
  368. X        result.v_type = V_FILE;
  369. X        result.v_file = id;
  370. X    }
  371. X    return result;
  372. X}
  373. X
  374. X
  375. Xstatic VALUE
  376. Xf_fclose(vp)
  377. X    VALUE *vp;
  378. X{
  379. X    VALUE result;
  380. X
  381. X    if (vp->v_type != V_FILE)
  382. X        math_error("Non-file for fclose");
  383. X    if (closeid(vp->v_file)) {
  384. X        result.v_type = V_NUM;
  385. X        result.v_num = itoq((long) errno);
  386. X    } else
  387. X        result.v_type = V_NULL;
  388. X    return result;
  389. X}
  390. X
  391. X
  392. Xstatic VALUE
  393. Xf_ferror(vp)
  394. X    VALUE *vp;
  395. X{
  396. X    VALUE result;
  397. X
  398. X    if (vp->v_type != V_FILE)
  399. X        math_error("Non-file for ferror");
  400. X    result.v_type = V_NUM;
  401. X    result.v_num = itoq((long) errorid(vp->v_file));
  402. X    return result;
  403. X}
  404. X
  405. X
  406. Xstatic VALUE
  407. Xf_feof(vp)
  408. X    VALUE *vp;
  409. X{
  410. X    VALUE result;
  411. X
  412. X    if (vp->v_type != V_FILE)
  413. X        math_error("Non-file for feof");
  414. X    result.v_type = V_NUM;
  415. X    result.v_num = itoq((long) eofid(vp->v_file));
  416. X    return result;
  417. X}
  418. X
  419. X
  420. Xstatic VALUE
  421. Xf_fflush(vp)
  422. X    VALUE *vp;
  423. X{
  424. X    VALUE result;
  425. X
  426. X    if (vp->v_type != V_FILE)
  427. X        math_error("Non-file for fflush");
  428. X    flushid(vp->v_file);
  429. X    result.v_type = V_NULL;
  430. X    return result;
  431. X}
  432. X
  433. X
  434. Xstatic VALUE
  435. Xf_fprintf(count, vals)
  436. X    VALUE **vals;
  437. X{
  438. X    VALUE result;
  439. X
  440. X    if (vals[0]->v_type != V_FILE)
  441. X        math_error("Non-file for fprintf");
  442. X    if (vals[1]->v_type != V_STR)
  443. X        math_error("Non-string format for fprintf");
  444. X    idprintf(vals[0]->v_file, vals[1]->v_str, count - 2, vals + 2);
  445. X    result.v_type = V_NULL;
  446. X    return result;
  447. X}
  448. X
  449. X
  450. Xstatic VALUE
  451. Xf_printf(count, vals)
  452. X    VALUE **vals;
  453. X{
  454. X    VALUE result;
  455. X
  456. X    if (vals[0]->v_type != V_STR)
  457. X        math_error("Non-string format for printf");
  458. X    idprintf(FILEID_STDOUT, vals[0]->v_str, count - 1, vals + 1);
  459. X    result.v_type = V_NULL;
  460. X    return result;
  461. X}
  462. X
  463. X
  464. Xstatic VALUE
  465. Xf_strprintf(count, vals)
  466. X    VALUE **vals;
  467. X{
  468. X    VALUE result;
  469. X
  470. X    if (vals[0]->v_type != V_STR)
  471. X        math_error("Non-string format for strprintf");
  472. X    math_divertio();
  473. X    idprintf(FILEID_STDOUT, vals[0]->v_str, count - 1, vals + 1);
  474. X    result.v_str = math_getdivertedio();
  475. X    result.v_type = V_STR;
  476. X    result.v_subtype = V_STRALLOC;
  477. X    return result;
  478. X}
  479. X
  480. X
  481. Xstatic VALUE
  482. Xf_fgetc(vp)
  483. X    VALUE *vp;
  484. X{
  485. X    VALUE result;
  486. X    int ch;
  487. X
  488. X    if (vp->v_type != V_FILE)
  489. X        math_error("Non-file for fgetc");
  490. X    ch = getcharid(vp->v_file);
  491. X    result.v_type = V_NULL;
  492. X    if (ch != EOF) {
  493. X        result.v_type = V_STR;
  494. X        result.v_subtype = V_STRLITERAL;
  495. X        result.v_str = charstr(ch);
  496. X    }
  497. X    return result;
  498. X}
  499. X
  500. X
  501. Xstatic VALUE
  502. Xf_fgetline(vp)
  503. X    VALUE *vp;
  504. X{
  505. X    VALUE result;
  506. X    char *str;
  507. X
  508. X    if (vp->v_type != V_FILE)
  509. X        math_error("Non-file for fgetline");
  510. X    readid(vp->v_file, &str);
  511. X    result.v_type = V_NULL;
  512. X    if (str) {
  513. X        result.v_type = V_STR;
  514. X        result.v_subtype = V_STRALLOC;
  515. X        result.v_str = str;
  516. X    }
  517. X    return result;
  518. X}
  519. X
  520. X
  521. Xstatic VALUE
  522. Xf_files(count, vals)
  523. X    VALUE **vals;
  524. X{
  525. X    VALUE result;
  526. X
  527. X    if (count == 0) {
  528. X        result.v_type = V_NUM;
  529. X        result.v_num = itoq((long) MAXFILES);
  530. X        return result;
  531. X    }
  532. X    if ((vals[0]->v_type != V_NUM) || qisfrac(vals[0]->v_num))
  533. X        math_error("Non-integer for files");
  534. X    result.v_type = V_NULL;
  535. X    result.v_file = indexid(qtoi(vals[0]->v_num));
  536. X    if (result.v_file != FILEID_NONE)
  537. X        result.v_type = V_FILE;
  538. X    return result;
  539. X}
  540. X
  541. X
  542. X/*
  543. X * Show the list of primitive built-in functions
  544. X */
  545. Xvoid
  546. Xshowbuiltins()
  547. X{
  548. X    register struct builtin *bp;    /* current function */
  549. X
  550. X    printf("\nName\tArgs\tDescription\n\n");
  551. X    for (bp = builtins; bp->b_name; bp++) {
  552. X        printf("%-9s ", bp->b_name);
  553. X        if (bp->b_maxargs == IN)
  554. X            printf("%d+    ", bp->b_minargs);
  555. X        else if (bp->b_minargs == bp->b_maxargs)
  556. X            printf("%-6d", bp->b_minargs);
  557. X        else
  558. X            printf("%d-%-4d", bp->b_minargs, bp->b_maxargs);
  559. X        printf(" %s\n", bp->b_desc);
  560. X    }
  561. X    printf("\n");
  562. X}
  563. X
  564. X
  565. X/*
  566. X * Return the index of a built-in function given its name.
  567. X * Returns minus one if the name is not known.
  568. X */
  569. Xgetbuiltinfunc(name)
  570. X    char *name;
  571. X{
  572. X    register struct builtin *bp;
  573. X
  574. X    for (bp = builtins; bp->b_name; bp++) {
  575. X        if ((*name == *bp->b_name) && (strcmp(name, bp->b_name) == 0))
  576. X        return (bp - builtins);
  577. X    }
  578. X    return -1;
  579. X}
  580. X
  581. X
  582. X/*
  583. X * Given the index of a built-in function, return its name.
  584. X */
  585. Xchar *
  586. Xbuiltinname(index)
  587. X    long index;
  588. X{
  589. X    if ((unsigned long)index >= (sizeof(builtins) / sizeof(builtins[0])) - 1)
  590. X        return "";
  591. X    return builtins[index].b_name;
  592. X}
  593. X
  594. X
  595. X/*
  596. X * Given the index of a built-in function, and the number of arguments seen,
  597. X * determine if the number of arguments are legal.  This routine is called
  598. X * during parsing time.
  599. X */
  600. Xvoid
  601. Xbuiltincheck(index, count)
  602. X    long index;
  603. X{
  604. X    register struct builtin *bp;
  605. X
  606. X    if ((unsigned long)index >= (sizeof(builtins) / sizeof(builtins[0])) - 1)
  607. X        math_error("Unknown built in index");
  608. X    bp = &builtins[index];
  609. X    if (count < bp->b_minargs)
  610. X        scanerror(T_NULL, "Too few arguments for builtin function \"%s\"",
  611. X    bp->b_name);
  612. X    if (count > bp->b_maxargs)
  613. X        scanerror(T_NULL, "Too many arguments for builtin function \"%s\"",
  614. X            bp->b_name);
  615. X}
  616. X
  617. X
  618. X/*
  619. X * Return the opcode for a built-in function that can be used to avoid
  620. X * the function call at all.
  621. X */
  622. Xbuiltinopcode(index)
  623. X    long index;
  624. X{
  625. X    if ((unsigned long)index >= (sizeof(builtins) / sizeof(builtins[0])) - 1)
  626. X        return OP_NOP;
  627. X    return builtins[index].b_opcode;
  628. X}
  629. X
  630. X/* END CODE */
  631. SHAR_EOF
  632. echo "File calc2.9.0/func.c is complete"
  633. chmod 0644 calc2.9.0/func.c || echo "restore of calc2.9.0/func.c fails"
  634. set `wc -c calc2.9.0/func.c`;Sum=$1
  635. if test "$Sum" != "48684"
  636. then echo original size 48684, current size $Sum;fi
  637. echo "x - extracting calc2.9.0/func.h (Text)"
  638. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/func.h &&
  639. X/*
  640. X * Copyright (c) 1993 David I. Bell
  641. X * Permission is granted to use, distribute, or modify this source,
  642. X * provided that this copyright notice remains intact.
  643. X */
  644. X
  645. X
  646. X#ifndef    FUNC_H
  647. X#define    FUNC_H
  648. X
  649. X#include "calc.h"
  650. X#include "label.h"
  651. X
  652. X
  653. X/*
  654. X * Structure of a function.
  655. X * The f_opcodes array is actually of variable size.
  656. X */
  657. Xtypedef struct func FUNC;
  658. Xstruct func {
  659. X    FUNC *f_next;            /* next function in list */
  660. X    unsigned long f_opcodecount;    /* size of opcode array */
  661. X    unsigned int f_localcount;    /* number of local variables */
  662. X    unsigned int f_paramcount;    /* max number of parameters */
  663. X    char *f_name;            /* function name */
  664. X    VALUE f_savedvalue;        /* saved value of last expression */
  665. X    long f_opcodes[1];        /* array of opcodes (variable length) */
  666. X};
  667. X
  668. X
  669. X/*
  670. X * Amount of space needed to allocate a function of n opcodes.
  671. X */
  672. X#define funcsize(n) (sizeof(FUNC) + (n) * sizeof(long))
  673. X
  674. X
  675. X/*
  676. X * Size of a character pointer rounded up to a number of opcodes.
  677. X */
  678. X#define PTR_SIZE ((sizeof(char *) + sizeof(long) - 1) / sizeof(long))
  679. X
  680. X
  681. X/*
  682. X * The current function being compiled.
  683. X */
  684. Xextern FUNC *curfunc;
  685. X
  686. X
  687. X/*
  688. X * Functions to handle functions.
  689. X */
  690. Xextern FUNC *findfunc MATH_PROTO((long index));
  691. Xextern char *namefunc MATH_PROTO((long index));
  692. Xextern BOOL evaluate MATH_PROTO((BOOL nestflag));
  693. Xextern long adduserfunc MATH_PROTO((char *name));
  694. Xextern void beginfunc MATH_PROTO((char *name, BOOL newflag));
  695. Xextern int builtinopcode MATH_PROTO((long index));
  696. Xextern char *builtinname MATH_PROTO((long index));
  697. Xextern int dumpop MATH_PROTO((long *pc));
  698. Xextern void addop MATH_PROTO((long op));
  699. Xextern void endfunc MATH_PROTO((void));
  700. Xextern void addopone MATH_PROTO((long op, long arg));
  701. Xextern void addoptwo MATH_PROTO((long op, long arg1, long arg2));
  702. Xextern void addoplabel MATH_PROTO((long op, LABEL *label));
  703. Xextern void addopptr MATH_PROTO((long op, char *ptr));
  704. Xextern void writeindexop MATH_PROTO((void));
  705. Xextern void showbuiltins MATH_PROTO((void));
  706. Xextern int getbuiltinfunc MATH_PROTO((char *name));
  707. Xextern void builtincheck MATH_PROTO((long index, int count));
  708. Xextern void addopfunction MATH_PROTO((long op, long index, int count));
  709. Xextern void showfunctions MATH_PROTO((void));
  710. Xextern void initfunctions MATH_PROTO((void));
  711. Xextern void clearopt MATH_PROTO((void));
  712. Xextern void updateoldvalue MATH_PROTO((FUNC *fp));
  713. Xextern void calculate MATH_PROTO((FUNC *fp, int argcount));
  714. Xextern VALUE builtinfunc MATH_PROTO((long index, int argcount, VALUE *stck));
  715. X
  716. X#endif
  717. X
  718. X/* END CODE */
  719. SHAR_EOF
  720. chmod 0644 calc2.9.0/func.h || echo "restore of calc2.9.0/func.h fails"
  721. set `wc -c calc2.9.0/func.h`;Sum=$1
  722. if test "$Sum" != "2475"
  723. then echo original size 2475, current size $Sum;fi
  724. echo "x - extracting calc2.9.0/hist.c (Text)"
  725. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/hist.c &&
  726. X/*
  727. X * Copyright (c) 1993 David I. Bell
  728. X * Permission is granted to use, distribute, or modify this source,
  729. X * provided that this copyright notice remains intact.
  730. X *
  731. X * Adapted from code written by Stephen Rothwell.
  732. X *
  733. X * Interactive readline module.  This is called to read lines of input,
  734. X * while using emacs-like editing commands within a command stack.
  735. X * The key bindings for the editing commands are (slightly) configurable.
  736. X */
  737. X
  738. X#include <stdio.h>
  739. X#include <ctype.h>
  740. X#include <pwd.h>
  741. X#include "hist.h"
  742. X#include "terminal.h"
  743. X
  744. X
  745. X#if defined(USE_TERMIOS)
  746. X# include <termios.h>
  747. X# define TTYSTRUCT    struct    termios
  748. X#else /* USE_SGTTY */
  749. X# if defined(USE_TERMIO)
  750. X#  include <termio.h>
  751. X#  define TTYSTRUCT    struct    termio
  752. X# else /* USE_TERMIO */
  753. X   /* assume USE_SGTTY */
  754. X#  include <sys/ioctl.h>
  755. X#  define TTYSTRUCT    struct    sgttyb
  756. X# endif /* USE_TERMIO */
  757. X#endif /* USE_SGTTY */
  758. X
  759. X
  760. X#define    STDIN        0
  761. X#define    SAVE_SIZE    256        /* size of save buffer */
  762. X#define    MAX_KEYS    60        /* number of key bindings */
  763. X
  764. X
  765. X#define CONTROL(x)        ((char)(((int)(x)) & 0x1f))
  766. X
  767. Xstatic    struct {
  768. X    char    *prompt;
  769. X    char    *buf;
  770. X    char    *pos;
  771. X    char    *end;
  772. X    char    *mark;
  773. X    int    bufsize;
  774. X    int    linelen;
  775. X    int    histcount;
  776. X    int    curhist;
  777. X} HS;
  778. X
  779. X
  780. Xtypedef    void (*FUNCPTR)();
  781. X
  782. Xtypedef struct {
  783. X    char    *name;
  784. X    FUNCPTR    func;
  785. X} FUNC;
  786. X
  787. X
  788. Xstatic void    flush_input(), start_of_line(), end_of_line();
  789. Xstatic void    forward_char(), backward_char(), forward_word();
  790. Xstatic void    backward_word(), delete_char(), forward_kill_char();
  791. Xstatic void    backward_kill_char(), forward_kill_word(), kill_line();
  792. Xstatic void    new_line(), save_line(), forward_history();
  793. Xstatic void    backward_history(), insert_char();
  794. Xstatic void    goto_line(), list_history(), refresh_line(), swap_chars();
  795. Xstatic void    set_mark(), yank(), save_region(), kill_region();
  796. Xstatic void    reverse_search(), quote_char(), uppercase_word();
  797. Xstatic void    lowercase_word(), ignore_char(), arrow_key();
  798. X
  799. X
  800. Xstatic    FUNC    funcs[] =
  801. X{
  802. X    {"ignore-char",        ignore_char},
  803. X    {"flush-input",        flush_input},
  804. X    {"start-of-line",    start_of_line},
  805. X    {"end-of-line",        end_of_line},
  806. X    {"forward-char",    forward_char},
  807. X    {"backward-char",    backward_char},
  808. X    {"forward-word",    forward_word},
  809. X    {"backward-word",    backward_word},
  810. X    {"delete-char",        delete_char},
  811. X    {"forward-kill-char",    forward_kill_char},
  812. X    {"backward-kill-char",    backward_kill_char},
  813. X    {"forward-kill-word",    forward_kill_word},
  814. X    {"uppercase-word",    uppercase_word},
  815. X    {"lowercase-word",    lowercase_word},
  816. X    {"kill-line",        kill_line},
  817. X    {"goto-line",        goto_line},
  818. X    {"new-line",        new_line},
  819. X    {"save-line",        save_line},
  820. X    {"forward-history",    forward_history},
  821. X    {"backward-history",    backward_history},
  822. X    {"insert-char",        insert_char},
  823. X    {"list-history",    list_history},
  824. X    {"refresh-line",    refresh_line},
  825. X    {"swap-chars",        swap_chars},
  826. X    {"set-mark",        set_mark},
  827. X    {"yank",        yank},
  828. X    {"save-region",        save_region},
  829. X    {"kill-region",        kill_region},
  830. X    {"reverse-search",    reverse_search},
  831. X    {"quote-char",        quote_char},
  832. X    {"arrow-key",        arrow_key},
  833. X    {NULL,             NULL}
  834. X};
  835. X
  836. X
  837. Xtypedef struct key_ent    KEY_ENT;
  838. Xtypedef struct key_map    KEY_MAP;
  839. X
  840. Xstruct key_ent    {
  841. X    FUNCPTR        func;
  842. X    KEY_MAP        *next;
  843. X};
  844. X
  845. X
  846. Xstruct key_map {
  847. X    char        *name;
  848. X    KEY_ENT        default_ent;
  849. X    KEY_ENT        *map[256];
  850. X};
  851. X
  852. X
  853. Xstatic char    base_map_name[] = "base-map";
  854. Xstatic char    esc_map_name[] = "esc-map";
  855. X
  856. X
  857. Xstatic KEY_MAP    maps[] = {
  858. X    {base_map_name},
  859. X    {esc_map_name}
  860. X};
  861. X
  862. X
  863. X#define    INTROUND    (sizeof(int) - 1)
  864. X#define    HISTLEN(hp)    ((((hp)->len + INTROUND) & ~INTROUND) + sizeof(int))
  865. X#define    HISTOFFSET(hp)    (((char *) (hp)) - histbuf)
  866. X#define    FIRSTHIST    ((HIST *) histbuf)
  867. X#define    NEXTHIST(hp)    ((HIST *) (((char *) (hp)) + HISTLEN(hp)))
  868. X
  869. X
  870. Xtypedef struct {
  871. X    int    len;        /* length of data */
  872. X    char    data[1];    /* varying length data */
  873. X} HIST;
  874. X
  875. X
  876. Xstatic    int        inited;
  877. Xstatic    int        canedit;
  878. Xstatic    int        histused;
  879. Xstatic    int        key_count;
  880. Xstatic    int        save_len;
  881. Xstatic    TTYSTRUCT    oldtty;
  882. Xstatic    KEY_MAP        *cur_map;
  883. Xstatic    KEY_MAP        *base_map;
  884. Xstatic    KEY_ENT        key_table[MAX_KEYS];
  885. Xstatic    char        histbuf[HIST_SIZE + 1];
  886. Xstatic    char        save_buffer[SAVE_SIZE];
  887. X
  888. X
  889. Xstatic    FUNCPTR    find_func();
  890. Xstatic    HIST    *get_event();
  891. Xstatic    HIST    *find_event();
  892. Xstatic    void    read_key();
  893. Xstatic    void    erasechar();
  894. Xstatic    void    newline();
  895. Xstatic    void    backspace();
  896. Xstatic    void    beep();
  897. Xstatic    void    echo_char();
  898. Xstatic    void    echo_string();
  899. Xstatic    void    savetext();
  900. Xstatic    void    memrcpy();
  901. Xstatic    int    read_bindings();
  902. Xstatic    int    in_word();
  903. X
  904. X
  905. X/*
  906. X * Read a line into the specified buffer.  The line ends in a newline,
  907. X * and is NULL terminated.  Returns the number of characters read, or
  908. X * zero on an end of file or error.  The prompt is printed before reading
  909. X * the line.
  910. X */
  911. Xint
  912. Xhist_getline(prompt, buf, len)
  913. X    char    *prompt;
  914. X    char    *buf;
  915. X    int    len;
  916. X{
  917. X    if (!inited)
  918. X        (void) hist_init((char *) NULL);
  919. X
  920. X    HS.prompt = prompt;
  921. X    HS.bufsize = len - 2;
  922. X    HS.buf = buf;
  923. X    HS.pos = buf;
  924. X    HS.end = buf;
  925. X    HS.mark = NULL;
  926. X    HS.linelen = -1;
  927. X
  928. X    fputs(prompt, stdout);
  929. X    fflush(stdout);
  930. X
  931. X    if (!canedit) {
  932. X        if (fgets(buf, len, stdin) == NULL)
  933. X            return 0;
  934. X        return strlen(buf);
  935. X    }
  936. X
  937. X    while (HS.linelen < 0)
  938. X        read_key();
  939. X
  940. X    return HS.linelen;
  941. X}
  942. X
  943. X
  944. X/*
  945. X * Initialize the module by reading in the key bindings from the specified
  946. X * filename, and then setting the terminal modes for noecho and cbreak mode.
  947. X * If the supplied filename is NULL, then a default filename will be used.
  948. X * Returns zero if successful, or a nonzero error code if unsuccessful.
  949. X * If this routine fails, hist_getline, hist_saveline, and hist_term can
  950. X * still be called but all fancy editing is disabled.
  951. X */
  952. Xint
  953. Xhist_init(filename)
  954. X    char    *filename;
  955. X{
  956. X    TTYSTRUCT    newtty;
  957. X
  958. X    if (inited)
  959. X        return HIST_INITED;
  960. X
  961. X    inited = 1;
  962. X    canedit = 0;
  963. X
  964. X    if (filename == NULL)
  965. X        filename = HIST_BINDING_FILE;
  966. X
  967. X    if (read_bindings(filename))
  968. X        return HIST_NOFILE;
  969. X
  970. X#ifdef    USE_SGTTY
  971. X    if (ioctl(STDIN, TIOCGETP, &oldtty) < 0)
  972. X        return HIST_NOTTY;
  973. X
  974. X    newtty = oldtty;
  975. X    newtty.sg_flags &= ~ECHO;
  976. X    newtty.sg_flags |= CBREAK;
  977. X
  978. X    if (ioctl(STDIN, TIOCSETP, &newtty) < 0)
  979. X        return HIST_NOTTY;
  980. X#endif
  981. X
  982. X#ifdef    USE_TERMIO
  983. X    if (ioctl(STDIN, TCGETA, &oldtty) < 0)
  984. X        return HIST_NOTTY;
  985. X
  986. X    newtty = oldtty;
  987. X    newtty.c_lflag &= ~(ECHO | ECHOE | ECHOK);
  988. X    newtty.c_iflag |= ISTRIP;
  989. X    newtty.c_lflag &= ~ICANON;
  990. X    newtty.c_cc[VMIN] = 1;
  991. X    newtty.c_cc[VTIME] = 0;
  992. X
  993. X    if (ioctl(STDIN, TCSETAW, &newtty) < 0)
  994. X        return HIST_NOTTY;
  995. X#endif
  996. X
  997. X#ifdef    USE_TERMIOS
  998. X    if (tcgetattr(STDIN, &oldtty) < 0)
  999. X        return HIST_NOTTY;
  1000. X
  1001. X    newtty = oldtty;
  1002. X    newtty.c_lflag &= ~(ECHO | ECHOE | ECHOK);
  1003. X    newtty.c_iflag |= ISTRIP;
  1004. X    newtty.c_lflag &= ~ICANON;
  1005. X    newtty.c_cc[VMIN] = 1;
  1006. X    newtty.c_cc[VTIME] = 0;
  1007. X
  1008. X    if (tcsetattr(STDIN, TCSANOW, &newtty) < 0)
  1009. X        return HIST_NOTTY;
  1010. X#endif
  1011. X
  1012. X    canedit = 1;
  1013. X
  1014. X    return HIST_SUCCESS;
  1015. X}
  1016. X
  1017. X
  1018. X/*
  1019. X * Reset the terminal modes just before exiting.
  1020. X */
  1021. Xvoid
  1022. Xhist_term()
  1023. X{
  1024. X    if (!inited || !canedit) {
  1025. X        inited = 0;
  1026. X        return;
  1027. X    }
  1028. X
  1029. X#ifdef    USE_SGTTY
  1030. X    (void) ioctl(STDIN, TIOCSETP, &oldtty);
  1031. X#endif
  1032. X
  1033. X#ifdef    USE_TERMIO
  1034. X    (void) ioctl(STDIN, TCSETAW, &oldtty);
  1035. X#endif
  1036. X
  1037. X#ifdef    USE_TERMIOS
  1038. X    (void) tcsetattr(STDIN, TCSANOW, &oldtty);
  1039. X#endif
  1040. X}
  1041. X
  1042. X
  1043. Xstatic KEY_MAP *
  1044. Xfind_map(map)
  1045. X    char    *map;
  1046. X{
  1047. X    int    i;
  1048. X
  1049. X    for (i = 0; i < sizeof(maps) / sizeof(maps[0]); i++) {
  1050. X        if (strcmp(map, maps[i].name) == 0)
  1051. X            return &maps[i];
  1052. X    }
  1053. X    return NULL;
  1054. X}
  1055. X
  1056. X
  1057. Xstatic void
  1058. Xunbind_key(map, key)
  1059. X    KEY_MAP        *map;
  1060. X{
  1061. X    map->map[key] = NULL;
  1062. X}
  1063. X
  1064. X
  1065. Xstatic void
  1066. Xraw_bind_key(map, key, func, next_map)
  1067. X    KEY_MAP        *map;
  1068. X    FUNCPTR        func;
  1069. X    KEY_MAP        *next_map;
  1070. X{
  1071. X    if (map->map[key] == NULL) {
  1072. X        if (key_count >= MAX_KEYS)
  1073. X            return;
  1074. X        map->map[key] = &key_table[key_count++];
  1075. X    }
  1076. X    map->map[key]->func = func;
  1077. X    map->map[key]->next = next_map;
  1078. X}
  1079. X
  1080. X
  1081. Xstatic KEY_MAP *
  1082. Xdo_map_line(line)
  1083. X    char    line[];
  1084. X{
  1085. X    char    *cp;
  1086. X    char    *map_name;
  1087. X
  1088. X    cp = line;
  1089. X    while (isspace(*cp))
  1090. X        cp++;
  1091. X    if (*cp == '\0')
  1092. X        return NULL;
  1093. X    map_name = cp;
  1094. X    while ((*cp != '\0') && !isspace(*cp))
  1095. X        cp++;
  1096. X    *cp = '\0';
  1097. X    return find_map(map_name);
  1098. X}
  1099. X
  1100. X
  1101. Xstatic void
  1102. Xdo_bind_line(map, line)
  1103. X    KEY_MAP        *map;
  1104. X    char        line[];
  1105. X{
  1106. X    char        *cp;
  1107. X    char        key;
  1108. X    char        *func_name;
  1109. X    char        *next_name;
  1110. X    KEY_MAP        *next;
  1111. X    FUNCPTR        func;
  1112. X
  1113. X    if (map == NULL)
  1114. X        return;
  1115. X    cp = line;
  1116. X    key = *cp++;
  1117. X    if (*cp == '\0') {
  1118. X        unbind_key(map, key);
  1119. X        return;
  1120. X    }
  1121. X    if (key == '^') {
  1122. X        if (*cp == '?') {
  1123. X            key = 0177;
  1124. X            cp++;
  1125. X        } else
  1126. X            key = CONTROL(*cp++);
  1127. X    }
  1128. X    else if (key == '\\')
  1129. X        key = *cp++;
  1130. X
  1131. X    while (isspace(*cp))
  1132. X        cp++;
  1133. X    if (*cp == '\0') {
  1134. X        unbind_key(map, key);
  1135. X        return;
  1136. X    }
  1137. X
  1138. X    func_name = cp;
  1139. X    while ((*cp != '\0') && !isspace(*cp))
  1140. X        cp++;
  1141. X    if (*cp) {
  1142. X        *cp++ = '\0';
  1143. X        while (isspace(*cp))
  1144. X            cp++;
  1145. X    }
  1146. X    func = find_func(func_name);
  1147. X    if (func == NULL) {
  1148. X        fprintf(stderr, "Unknown function \"%s\"\n", func_name);
  1149. X        return;
  1150. X    }
  1151. X
  1152. X    if (*cp == '\0') {
  1153. X        next = map->default_ent.next;
  1154. X        if (next == NULL)
  1155. X            next = base_map;
  1156. X    } else {
  1157. X        next_name = cp;
  1158. X        while ((*cp != '\0') && !isspace(*cp))
  1159. X            cp++;
  1160. X        if (*cp) {
  1161. X            *cp++ = '\0';
  1162. X            while (isspace(*cp))
  1163. X                cp++;
  1164. X        }
  1165. X        next = find_map(next_name);
  1166. X        if (next == NULL)
  1167. X            return;
  1168. X    }
  1169. X    raw_bind_key(map, key, func, next);
  1170. X}
  1171. X
  1172. X
  1173. Xstatic void
  1174. Xdo_default_line(map, line)
  1175. X    KEY_MAP        *map;
  1176. X    char        *line;
  1177. X{
  1178. X    char        *cp;
  1179. X    char        *func_name;
  1180. X    char        *next_name;
  1181. X    KEY_MAP        *next;
  1182. X    FUNCPTR        func;
  1183. X
  1184. X    if (map == NULL)
  1185. X        return;
  1186. X    cp = line;
  1187. X    while (isspace(*cp))
  1188. X        cp++;
  1189. X    if (*cp == '\0')
  1190. X        return;
  1191. X
  1192. X    func_name = cp;
  1193. X    while ((*cp != '\0') && !isspace(*cp))
  1194. X        cp++;
  1195. X    if (*cp != '\0')
  1196. X    {
  1197. X        *cp++ = '\0';
  1198. X        while (isspace(*cp))
  1199. X            cp++;
  1200. X    }
  1201. X    func = find_func(func_name);
  1202. X    if (func == NULL)
  1203. X        return;
  1204. X
  1205. X    if (*cp == '\0')
  1206. X        next = map;
  1207. X    else
  1208. X    {
  1209. X        next_name = cp;
  1210. X        while ((*cp != '\0') && !isspace(*cp))
  1211. X            cp++;
  1212. X        if (*cp != '\0')
  1213. X        {
  1214. X            *cp++ = '\0';
  1215. X            while (isspace(*cp))
  1216. X                cp++;
  1217. X        }
  1218. X        next = find_map(next_name);
  1219. X        if (next == NULL)
  1220. X            return;
  1221. X    }
  1222. X
  1223. X    map->default_ent.func = func;
  1224. X    map->default_ent.next = next;
  1225. X}
  1226. X
  1227. X
  1228. X/*
  1229. X * Read bindings from specified file.
  1230. X * Returns nonzero on error.
  1231. X */
  1232. Xstatic int
  1233. Xread_bindings(bindfile)
  1234. X    char    *bindfile;
  1235. X{
  1236. X    char    *cp;
  1237. X    KEY_MAP    *input_map;
  1238. X    FILE    *fp;
  1239. X    char    line[100];
  1240. X
  1241. X    base_map = find_map(base_map_name);
  1242. X    cur_map = base_map;
  1243. X    input_map = base_map;
  1244. X
  1245. X    fp = fopen(bindfile, "r");
  1246. X    if (fp == NULL)
  1247. X        return 1;
  1248. X
  1249. X    while (fgets(line, sizeof(line) - 1, fp)) {
  1250. X        cp = line;
  1251. X        while (isspace(*cp))
  1252. X            cp++;
  1253. X
  1254. X        if ((*cp == '\0') || (*cp == '#') || (*cp == '\n'))
  1255. X            continue;
  1256. X
  1257. X        if (cp[strlen(cp) - 1] == '\n')
  1258. X            cp[strlen(cp) - 1] = '\0';
  1259. X
  1260. X        if (memcmp(cp, "map", 3) == 0)
  1261. X            input_map = do_map_line(&cp[3]);
  1262. X        else if (memcmp(cp, "default", 7) == 0)
  1263. X            do_default_line(input_map, &cp[7]);
  1264. X        else
  1265. X            do_bind_line(input_map, cp);
  1266. X    }
  1267. X    fclose(fp);
  1268. X    return 0;
  1269. X}
  1270. X
  1271. X
  1272. Xstatic void
  1273. Xread_key()
  1274. X{
  1275. X    KEY_ENT        *ent;
  1276. X    int        key;
  1277. X
  1278. X    fflush(stdout);
  1279. X    key = fgetc(stdin);
  1280. X    if (key == EOF) {
  1281. X        HS.linelen = 0;
  1282. X        HS.buf[0] = '\0';
  1283. X        return;
  1284. X    }
  1285. X
  1286. X    ent = cur_map->map[key];
  1287. X    if (ent == NULL)
  1288. X        ent = &cur_map->default_ent;
  1289. X    if (ent->next)
  1290. X        cur_map = ent->next;
  1291. X    if (ent->func)
  1292. X        (*ent->func)(key);
  1293. X    else
  1294. X        insert_char(key);
  1295. X}
  1296. X
  1297. X
  1298. X/*
  1299. X * Return the Nth history event, indexed from zero.
  1300. X * Earlier history events are lower in number.
  1301. X */
  1302. Xstatic HIST *
  1303. Xget_event(n)
  1304. X{
  1305. X    register HIST *    hp;
  1306. X
  1307. X    if ((n < 0) || (n >= HS.histcount))
  1308. X        return NULL;
  1309. X    hp = FIRSTHIST;
  1310. X    while (n-- > 0)
  1311. X        hp = NEXTHIST(hp);
  1312. X    return hp;
  1313. X}
  1314. X
  1315. X
  1316. X/*
  1317. X * Search the history list for the specified pattern.
  1318. X * Returns the found history, or NULL.
  1319. X */
  1320. Xstatic HIST *
  1321. Xfind_event(pat, len)
  1322. X    char *    pat;
  1323. X{
  1324. X    register HIST *    hp;
  1325. X
  1326. X    for (hp = FIRSTHIST; hp->len; hp = NEXTHIST(hp)) {
  1327. X        if ((hp->len == len) && (memcmp(hp->data, pat, len) == 0))
  1328. X                return hp;
  1329. X    }
  1330. X    return NULL;
  1331. X}
  1332. X
  1333. X
  1334. X/*
  1335. X * Insert a line into the end of the history table.
  1336. X * If the line already appears in the table, then it is moved to the end.
  1337. X * If the table is full, then the earliest commands are deleted as necessary.
  1338. X * Warning: the incoming line cannot point into the history table.
  1339. X */
  1340. Xvoid
  1341. Xhist_saveline(line, len)
  1342. X    char *    line;
  1343. X{
  1344. X    HIST *    hp;
  1345. X    HIST *    hp2;
  1346. X    int    left;
  1347. X
  1348. X    if ((len > 0) && (line[len - 1] == '\n'))
  1349. X        len--;
  1350. X    if (len <= 0)
  1351. X        return;
  1352. X
  1353. X    /*
  1354. X     * See if the line is already present in the history table.
  1355. X     * If so, and it is already at the end, then we are all done.
  1356. X     * Otherwise delete it since we will reinsert it at the end.
  1357. X     */
  1358. X    hp = find_event(line, len);
  1359. X    if (hp) {
  1360. X        hp2 = NEXTHIST(hp);
  1361. X        left = histused - HISTOFFSET(hp2);
  1362. X        if (left <= 0)
  1363. X            return;
  1364. X        histused -= HISTLEN(hp);
  1365. X        memcpy(hp, hp2, left + 1);
  1366. X        HS.histcount--;
  1367. X    }
  1368. X
  1369. X    /*
  1370. X     * If there is not enough room left in the history buffer to add
  1371. X     * the new command, then repeatedly delete the earliest command
  1372. X     * as many times as necessary in order to make enough room.
  1373. X     */
  1374. X    while ((histused + len) >= HIST_SIZE) {
  1375. X        hp = (HIST *) histbuf;
  1376. X        hp2 = NEXTHIST(hp);
  1377. X        left = histused - HISTOFFSET(hp2);
  1378. X        histused -= HISTLEN(hp);
  1379. X        memcpy(hp, hp2, left + 1);
  1380. X        HS.histcount--;
  1381. X    }
  1382. X
  1383. X    /*
  1384. X     * Add the line to the end of the history table.
  1385. X     */
  1386. X    hp = (HIST *) &histbuf[histused];
  1387. X    hp->len = len;
  1388. X    memcpy(hp->data, line, len);
  1389. X    histused += HISTLEN(hp);
  1390. X    histbuf[histused] = 0;
  1391. X    HS.curhist = ++HS.histcount;
  1392. X}
  1393. X
  1394. X
  1395. X/*
  1396. X * Find the function for a specified name.
  1397. X */
  1398. Xstatic FUNCPTR
  1399. Xfind_func(name)
  1400. X    char    *name;
  1401. X{
  1402. X    FUNC    *fp;
  1403. X
  1404. X    for (fp = funcs; fp->name; fp++) {
  1405. X        if (strcmp(fp->name, name) == 0)
  1406. X            return fp->func;
  1407. X    }
  1408. X    return NULL;
  1409. X}
  1410. X
  1411. X
  1412. Xstatic void
  1413. Xarrow_key()
  1414. X{
  1415. X    switch (fgetc(stdin)) {
  1416. X        case 'A':
  1417. X            backward_history();
  1418. X            break;
  1419. X        case 'B':
  1420. X            forward_history();
  1421. X            break;
  1422. X        case 'C':
  1423. X            forward_char();
  1424. X            break;
  1425. X        case 'D':
  1426. X            backward_char();
  1427. X            break;
  1428. X    }
  1429. X}
  1430. X
  1431. X
  1432. Xstatic void
  1433. Xback_over_char(ch)
  1434. X    char    ch;
  1435. X{
  1436. X    backspace();
  1437. X    if (!isprint(ch))
  1438. X        backspace();
  1439. X}
  1440. X
  1441. X
  1442. Xstatic void
  1443. Xremove_char(ch)
  1444. X    char    ch;
  1445. X{
  1446. X    erasechar();
  1447. X    if (!isprint(ch))
  1448. X        erasechar();
  1449. X}
  1450. X
  1451. X
  1452. Xstatic void
  1453. Xecho_rest_of_line()
  1454. X{
  1455. X    echo_string(HS.pos, HS.end - HS.pos);
  1456. X}
  1457. X
  1458. X
  1459. Xstatic void
  1460. Xgoto_start_of_line()
  1461. X{
  1462. X    while (HS.pos > HS.buf)
  1463. X        back_over_char(*--HS.pos);
  1464. X}
  1465. X
  1466. X
  1467. Xstatic void
  1468. Xgoto_end_of_line()
  1469. X{
  1470. X    echo_rest_of_line();
  1471. X    HS.pos = HS.end;
  1472. X}
  1473. X
  1474. X
  1475. Xstatic void
  1476. Xdecrement_end(n)
  1477. X{
  1478. X    HS.end -= n;
  1479. X    if (HS.mark && (HS.mark > HS.end))
  1480. X        HS.mark = NULL;
  1481. X}
  1482. X
  1483. X
  1484. Xstatic void
  1485. Xignore_char()
  1486. X{
  1487. X}
  1488. X
  1489. X
  1490. Xstatic void
  1491. Xflush_input()
  1492. X{
  1493. X    echo_rest_of_line();
  1494. X    while (HS.end > HS.buf)
  1495. X        remove_char(*--HS.end);
  1496. X    HS.pos = HS.buf;
  1497. X    HS.mark = NULL;
  1498. X}
  1499. X
  1500. X
  1501. Xstatic void
  1502. Xstart_of_line()
  1503. X{
  1504. X    goto_start_of_line();
  1505. X}
  1506. X
  1507. X
  1508. Xstatic void
  1509. Xend_of_line()
  1510. X{
  1511. X    goto_end_of_line();
  1512. X}
  1513. X
  1514. X
  1515. Xstatic void
  1516. Xforward_char()
  1517. X{
  1518. X    if (HS.pos < HS.end)
  1519. X        echo_char(*HS.pos++);
  1520. X}
  1521. X
  1522. X
  1523. Xstatic void
  1524. Xbackward_char()
  1525. X{
  1526. X    if (HS.pos > HS.buf)
  1527. X        back_over_char(*--HS.pos);
  1528. X}
  1529. X
  1530. X
  1531. Xstatic void
  1532. Xuppercase_word()
  1533. X{
  1534. X    while ((HS.pos < HS.end) && !in_word(*HS.pos))
  1535. X        echo_char(*HS.pos++);
  1536. X    while ((HS.pos < HS.end) && in_word(*HS.pos)) {
  1537. X        if ((*HS.pos >= 'a') && (*HS.pos <= 'z'))
  1538. X            *HS.pos += 'A' - 'a';
  1539. X        echo_char(*HS.pos++);
  1540. X    }
  1541. X}
  1542. X
  1543. X
  1544. Xstatic void
  1545. Xlowercase_word()
  1546. X{
  1547. X    while ((HS.pos < HS.end) && !in_word(*HS.pos))
  1548. X        echo_char(*HS.pos++);
  1549. X    while ((HS.pos < HS.end) && in_word(*HS.pos)) {
  1550. X        if ((*HS.pos >= 'A') && (*HS.pos <= 'Z'))
  1551. X            *HS.pos += 'a' - 'A';
  1552. X        echo_char(*HS.pos++);
  1553. X    }
  1554. X}
  1555. X
  1556. X
  1557. Xstatic void
  1558. Xforward_word()
  1559. X{
  1560. X    while ((HS.pos < HS.end) && !in_word(*HS.pos))
  1561. X        echo_char(*HS.pos++);
  1562. X    while ((HS.pos < HS.end) && in_word(*HS.pos))
  1563. X        echo_char(*HS.pos++);
  1564. X}
  1565. X
  1566. X
  1567. Xstatic void
  1568. Xbackward_word()
  1569. X{
  1570. X    if ((HS.pos > HS.buf) && in_word(*HS.pos))
  1571. X        back_over_char(*--HS.pos);
  1572. X    while ((HS.pos > HS.buf) && !in_word(*HS.pos))
  1573. X        back_over_char(*--HS.pos);
  1574. X    while ((HS.pos > HS.buf) && in_word(*HS.pos))
  1575. X        back_over_char(*--HS.pos);
  1576. X    if ((HS.pos < HS.end) && !in_word(*HS.pos))
  1577. X        echo_char(*HS.pos++);
  1578. X}
  1579. X
  1580. X
  1581. Xstatic void
  1582. Xforward_kill_char()
  1583. X{
  1584. X    int    rest;
  1585. X    char    ch;
  1586. X
  1587. X    rest = HS.end - HS.pos;
  1588. X    if (rest-- <= 0)
  1589. X        return;
  1590. X    ch = *HS.pos;
  1591. X    if (rest > 0) {
  1592. X        memcpy(HS.pos, HS.pos + 1, rest);
  1593. X        *(HS.end - 1) = ch;
  1594. X    }
  1595. X    echo_rest_of_line();
  1596. X    remove_char(ch);
  1597. X    decrement_end(1);
  1598. X    while (rest > 0)
  1599. X        back_over_char(HS.pos[--rest]);
  1600. X}
  1601. X
  1602. X
  1603. Xstatic void
  1604. Xdelete_char()
  1605. X{
  1606. X    if (HS.end > HS.buf)
  1607. X        forward_kill_char();
  1608. X}
  1609. X
  1610. X
  1611. Xstatic void
  1612. Xbackward_kill_char()
  1613. X{
  1614. X    if (HS.pos > HS.buf) {
  1615. X        HS.pos--;
  1616. X        back_over_char(*HS.pos);
  1617. X        forward_kill_char();
  1618. X    }
  1619. X}
  1620. X
  1621. X
  1622. Xstatic void
  1623. Xforward_kill_word()
  1624. X{
  1625. X    char    *cp;
  1626. X
  1627. X    if (HS.pos >= HS.end)
  1628. X        return;
  1629. X    echo_rest_of_line();
  1630. X    for (cp = HS.end; cp > HS.pos;)
  1631. X        remove_char(*--cp);
  1632. X    cp = HS.pos;
  1633. X    while ((cp < HS.end) && !in_word(*cp))
  1634. X        cp++;
  1635. X    while ((cp < HS.end) && in_word(*cp))
  1636. X        cp++;
  1637. X    savetext(HS.pos, cp - HS.pos);
  1638. X    memcpy(HS.pos, cp, HS.end - cp);
  1639. X    decrement_end(cp - HS.pos);
  1640. X    echo_rest_of_line();
  1641. X    for (cp = HS.end; cp > HS.pos;)
  1642. X        back_over_char(*--cp);
  1643. X}
  1644. X
  1645. X
  1646. Xstatic void
  1647. Xkill_line()
  1648. X{
  1649. X    if (HS.end <= HS.pos)
  1650. X        return;
  1651. X    savetext(HS.pos, HS.end - HS.pos);
  1652. X    echo_rest_of_line();
  1653. X    while (HS.end > HS.pos)
  1654. X        remove_char(*--HS.end);
  1655. X    decrement_end(0);
  1656. X}
  1657. X
  1658. X
  1659. X/*
  1660. X * This is the function which completes a command line editing session.
  1661. X * The final line length is returned in the HS.linelen variable.
  1662. X * The line is NOT put into the edit history, so that the caller can
  1663. X * decide whether or not this should be done.
  1664. X */
  1665. Xstatic void
  1666. Xnew_line()
  1667. X{
  1668. X    int    len;
  1669. X
  1670. X    newline();
  1671. X    fflush(stdout);
  1672. X
  1673. X    HS.mark = NULL;
  1674. X    HS.end[0] = '\n';
  1675. X    HS.end[1] = '\0';
  1676. X    len = HS.end - HS.buf + 1;
  1677. X    if (len <= 1) {
  1678. X        HS.curhist = HS.histcount;
  1679. X        HS.linelen = 1;
  1680. X        return;
  1681. X    }
  1682. X    HS.curhist = HS.histcount;
  1683. X    HS.pos = HS.buf;
  1684. X    HS.end = HS.buf;
  1685. X    HS.linelen = len;
  1686. X}
  1687. X
  1688. X
  1689. Xstatic void
  1690. Xsave_line()
  1691. X{
  1692. X    int    len;
  1693. X
  1694. X    len = HS.end - HS.buf;
  1695. X    if (len > 0) {
  1696. X        hist_saveline(HS.buf, len);
  1697. X        flush_input();
  1698. X    }
  1699. X    HS.curhist = HS.histcount;
  1700. X}
  1701. X
  1702. X
  1703. Xstatic void
  1704. Xgoto_line()
  1705. X{
  1706. X    int    num;
  1707. X    char    *cp;
  1708. X    HIST    *hp;
  1709. X
  1710. X    num = 0;
  1711. X    cp = HS.buf;
  1712. X    while ((*cp >= '0') && (*cp <= '9') && (cp < HS.pos))
  1713. X        num = num * 10 + (*cp++ - '0');
  1714. X    if ((num <= 0) || (num > HS.histcount) || (cp != HS.pos)) {
  1715. X        beep();
  1716. X        return;
  1717. X    }
  1718. X    flush_input();
  1719. X    HS.curhist = HS.histcount - num;
  1720. X    hp = get_event(HS.curhist);
  1721. X    memcpy(HS.buf, hp->data, hp->len);
  1722. X    HS.end = &HS.buf[hp->len];
  1723. X    goto_end_of_line();
  1724. X}
  1725. X
  1726. X
  1727. Xstatic void
  1728. Xforward_history()
  1729. X{
  1730. X    HIST    *hp;
  1731. X
  1732. X    flush_input();
  1733. X    if (++HS.curhist >= HS.histcount)
  1734. X        HS.curhist = 0;
  1735. X    hp = get_event(HS.curhist);
  1736. X    if (hp) {
  1737. X        memcpy(HS.buf, hp->data, hp->len);
  1738. X        HS.end = &HS.buf[hp->len];
  1739. X    }
  1740. X    goto_end_of_line();
  1741. X}
  1742. X
  1743. X
  1744. Xstatic void
  1745. Xbackward_history()
  1746. X{
  1747. X    HIST    *hp;
  1748. X
  1749. X    flush_input();
  1750. X    if (--HS.curhist < 0)
  1751. X        HS.curhist = HS.histcount - 1;
  1752. X    hp = get_event(HS.curhist);
  1753. X    if (hp) {
  1754. X        memcpy(HS.buf, hp->data, hp->len);
  1755. X        HS.end = &HS.buf[hp->len];
  1756. X    }
  1757. X    goto_end_of_line();
  1758. X}
  1759. X
  1760. X
  1761. Xstatic void
  1762. Xinsert_char(key)
  1763. X{
  1764. X    int    len;
  1765. X    int    rest;
  1766. X
  1767. X    len = HS.end - HS.buf;
  1768. X    if (len >= HS.bufsize) {
  1769. X        beep();
  1770. X        return;
  1771. X    }
  1772. X    rest = HS.end - HS.pos;
  1773. X    if (rest > 0)
  1774. X        memrcpy(HS.pos + 1, HS.pos, rest);
  1775. X    HS.end++;
  1776. X    *HS.pos++ = key;
  1777. X    echo_char(key);
  1778. X    echo_rest_of_line();
  1779. X    while (rest > 0)
  1780. X        back_over_char(HS.pos[--rest]);
  1781. X}
  1782. X
  1783. X
  1784. Xstatic void
  1785. Xinsert_string(str, len)
  1786. X    char    *str;
  1787. X{
  1788. X    int    rest;
  1789. X    int    totallen;
  1790. X
  1791. X    if (len <= 0)
  1792. X        return;
  1793. X    totallen = (HS.end - HS.buf) + len;
  1794. X    if (totallen > HS.bufsize) {
  1795. X        beep();
  1796. X        return;
  1797. X    }
  1798. X    rest = HS.end - HS.pos;
  1799. X    if (rest > 0)
  1800. X        memrcpy(HS.pos + len, HS.pos, rest);
  1801. X    HS.end += len;
  1802. X    memcpy(HS.pos, str, len);
  1803. X    HS.pos += len;
  1804. X    echo_string(str, len);
  1805. X    echo_rest_of_line();
  1806. X    while (rest > 0)
  1807. X        back_over_char(HS.pos[--rest]);
  1808. X}
  1809. X
  1810. X
  1811. Xstatic void
  1812. Xlist_history()
  1813. X{
  1814. X    HIST    *hp;
  1815. X    int    num;
  1816. X
  1817. X    for (num = 0; num < HS.histcount; num++) {
  1818. X        hp = get_event(num);
  1819. X        printf("\n%3d: ", HS.histcount - num);
  1820. X        echo_string(hp->data, hp->len);
  1821. X    }
  1822. X    refresh_line();
  1823. X}
  1824. X
  1825. X
  1826. Xstatic void
  1827. Xrefresh_line()
  1828. X{
  1829. X    char    *cp;
  1830. X
  1831. X    newline();
  1832. X    fputs(HS.prompt, stdout);
  1833. X    if (HS.end > HS.buf) {
  1834. X        echo_string(HS.buf, HS.end - HS.buf);
  1835. X        cp = HS.end;
  1836. X        while (cp > HS.pos)
  1837. X            back_over_char(*--cp);
  1838. X    }
  1839. X}
  1840. X
  1841. X
  1842. Xstatic void
  1843. Xswap_chars()
  1844. X{
  1845. X    char    ch1;
  1846. X    char    ch2;
  1847. X
  1848. X    if ((HS.pos <= HS.buf) || (HS.pos >= HS.end))
  1849. X        return;
  1850. X    ch1 = *HS.pos--;
  1851. X    ch2 = *HS.pos;
  1852. X    *HS.pos++ = ch1;
  1853. X    *HS.pos = ch2;
  1854. X    back_over_char(ch2);
  1855. X    echo_char(ch1);
  1856. X    echo_char(ch2);
  1857. X    back_over_char(ch2);
  1858. X}
  1859. X
  1860. X
  1861. Xstatic void
  1862. Xset_mark()
  1863. X{
  1864. X    HS.mark = HS.pos;
  1865. X}
  1866. X
  1867. X
  1868. Xstatic void
  1869. Xsave_region()
  1870. X{
  1871. X    int    len;
  1872. X
  1873. X    if (HS.mark == NULL)
  1874. X        return;
  1875. X    len = HS.mark - HS.pos;
  1876. X    if (len > 0)
  1877. X        savetext(HS.pos, len);
  1878. X    if (len < 0)
  1879. X        savetext(HS.mark, -len);
  1880. X}
  1881. X
  1882. X
  1883. Xstatic void
  1884. Xkill_region()
  1885. X{
  1886. X    char    *cp;
  1887. X    char    *left;
  1888. X    char    *right;
  1889. X
  1890. X    if ((HS.mark == NULL) || (HS.mark == HS.pos))
  1891. X        return;
  1892. X
  1893. X    echo_rest_of_line();
  1894. X    if (HS.mark < HS.pos) {
  1895. X        left = HS.mark;
  1896. X        right = HS.pos;
  1897. X        HS.pos = HS.mark;
  1898. X    } else {
  1899. X        left = HS.pos;
  1900. X        right = HS.mark;
  1901. X        HS.mark = HS.pos;
  1902. X    }
  1903. X    savetext(left, right - left);
  1904. X    for (cp = HS.end; cp > left;)
  1905. X        remove_char(*--cp);
  1906. X    if (right < HS.end)
  1907. X        memcpy(left, right, HS.end - right);
  1908. X    decrement_end(right - left);
  1909. X    echo_rest_of_line();
  1910. X    for (cp = HS.end; cp > HS.pos;)
  1911. X        back_over_char(*--cp);
  1912. X}
  1913. X
  1914. X
  1915. Xstatic void
  1916. Xyank()
  1917. X{
  1918. X    insert_string(save_buffer, save_len);
  1919. X}
  1920. X
  1921. X
  1922. Xstatic void
  1923. Xreverse_search()
  1924. X{
  1925. X    int    len;
  1926. X    int    count;
  1927. X    int    testhist;
  1928. X    HIST    *hp;
  1929. X    char    *save_pos;
  1930. X
  1931. X    count = HS.histcount;
  1932. X    len = HS.pos - HS.buf;
  1933. X    if (len <= 0)
  1934. X        count = 0;
  1935. X    testhist = HS.curhist;
  1936. X    do {
  1937. X        if (--count < 0) {
  1938. X            beep();
  1939. X            return;
  1940. X        }
  1941. X        if (--testhist < 0)
  1942. X            testhist = HS.histcount - 1;
  1943. X        hp = get_event(testhist);
  1944. X    } while ((hp == NULL) || (hp->len < len) ||
  1945. X        memcmp(hp->data, HS.buf, len));
  1946. X
  1947. X    HS.curhist = testhist;
  1948. X    save_pos = HS.pos;
  1949. X    flush_input();
  1950. X    memcpy(HS.buf, hp->data, hp->len);
  1951. X    HS.end = &HS.buf[hp->len];
  1952. X    goto_end_of_line();
  1953. X    while (HS.pos > save_pos)
  1954. X        back_over_char(*--HS.pos);
  1955. X}
  1956. X
  1957. X
  1958. Xstatic void
  1959. Xquote_char()
  1960. X{
  1961. X    int    ch;
  1962. X
  1963. X    ch = fgetc(stdin);
  1964. X    if (ch != EOF)
  1965. X        insert_char(ch);
  1966. X}
  1967. X
  1968. X
  1969. X/*
  1970. X * Save data in the save buffer.
  1971. X */
  1972. Xstatic void
  1973. Xsavetext(str, len)
  1974. X    char    *str;
  1975. X{
  1976. X    save_len = 0;
  1977. X    if (len <= 0)
  1978. X        return;
  1979. X    if (len > SAVE_SIZE)
  1980. X        len = SAVE_SIZE;
  1981. X    memcpy(save_buffer, str, len);
  1982. X    save_len = len;
  1983. X}
  1984. X
  1985. X
  1986. X/*
  1987. X * Test whether a character is part of a word.
  1988. X */
  1989. Xstatic int
  1990. Xin_word(ch)
  1991. X    char    ch;
  1992. X{
  1993. X    return (isalnum(ch) || (ch == '_'));
  1994. X}
  1995. X
  1996. X
  1997. Xstatic void
  1998. Xerasechar()
  1999. X{
  2000. X    fputs("\b \b", stdout);
  2001. X}
  2002. X
  2003. X
  2004. Xstatic void
  2005. Xnewline()
  2006. X{
  2007. X    fputc('\n', stdout);
  2008. X}
  2009. X
  2010. X
  2011. Xstatic void
  2012. Xbackspace()
  2013. X{
  2014. X    fputc('\b', stdout);
  2015. X}
  2016. X
  2017. X
  2018. Xstatic void
  2019. Xbeep()
  2020. X{
  2021. X    fputc('\007', stdout);
  2022. X}
  2023. X
  2024. X
  2025. Xstatic void
  2026. Xecho_char(ch)
  2027. X{
  2028. X    if (isprint(ch))
  2029. X        putchar(ch);
  2030. X    else {
  2031. X        putchar('^');
  2032. X        putchar((ch + '@') & 0x7f);
  2033. X    }
  2034. X}
  2035. X
  2036. X
  2037. Xstatic void
  2038. Xecho_string(str, len)
  2039. X    char    *str;
  2040. X{
  2041. X    while (len-- > 0)
  2042. X        echo_char(*str++);
  2043. X}
  2044. X
  2045. X
  2046. Xstatic void
  2047. Xmemrcpy(dest, src, len)
  2048. X    char    *dest, *src;
  2049. X{
  2050. X    dest += len - 1;
  2051. X    src += len - 1;
  2052. X    while (len-- > 0)
  2053. X        *dest-- = *src--;
  2054. X}
  2055. X
  2056. X
  2057. X#ifdef    HIST_TEST
  2058. X
  2059. X/*
  2060. X * Main routine to test history.
  2061. X */
  2062. Xmain(argc, argv)
  2063. X    int    argc;
  2064. X    char    *argv[];
  2065. X{
  2066. X    char    *filename;
  2067. X    int    len;
  2068. X    char    buf[256];
  2069. X
  2070. X    filename = NULL;
  2071. X    if (argc > 1)
  2072. X        filename = argv[1];
  2073. X
  2074. X    switch (hist_init(filename)) {
  2075. X        case HIST_SUCCESS:
  2076. X            break;
  2077. X        case HIST_NOFILE:
  2078. X            fprintf(stderr, "Binding file was not found\n");
  2079. X            break;
  2080. X        case HIST_NOTTY:
  2081. X            fprintf(stderr, "Cannot set terminal parameters\n");
  2082. X            break;
  2083. X        case HIST_INITED:
  2084. X            fprintf(stderr, "Hist is already inited\n");
  2085. X            break;
  2086. X        default:
  2087. X            fprintf(stderr, "Unknown error from hist_init\n");
  2088. X            break;
  2089. X    }
  2090. X
  2091. X    do {
  2092. X        len = hist_getline("HIST> ", buf, sizeof(buf));
  2093. X        hist_saveline(buf, len);        
  2094. X    } while (len && (buf[0] != 'q'));
  2095. X
  2096. X    hist_term();
  2097. X
  2098. X    return 0;
  2099. X}
  2100. X#endif
  2101. X
  2102. X/* END CODE */
  2103. SHAR_EOF
  2104. chmod 0644 calc2.9.0/hist.c || echo "restore of calc2.9.0/hist.c fails"
  2105. set `wc -c calc2.9.0/hist.c`;Sum=$1
  2106. if test "$Sum" != "22702"
  2107. then echo original size 22702, current size $Sum;fi
  2108. echo "x - extracting calc2.9.0/hist.h (Text)"
  2109. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/hist.h &&
  2110. X/*
  2111. X * Copyright (c) 1993 David I. Bell
  2112. X * Permission is granted to use, distribute, or modify this source,
  2113. X * provided that this copyright notice remains intact.
  2114. X *
  2115. X * Definitions for command history module.
  2116. X */
  2117. X
  2118. X
  2119. X#ifdef    __STDC__
  2120. X#define    HIST_PROTO(a) a
  2121. X#else
  2122. X#define    HIST_PROTO(a) ()
  2123. X#endif
  2124. X
  2125. X
  2126. X/*
  2127. X * Default binding file and history size.
  2128. X */
  2129. X#ifndef    HIST_BINDING_FILE
  2130. X#define    HIST_BINDING_FILE    "/usr/lib/hist.bind"
  2131. X#endif
  2132. X
  2133. X#ifndef    HIST_SIZE
  2134. X#define    HIST_SIZE        (1024*10)
  2135. X#endif
  2136. X
  2137. X
  2138. X/* 
  2139. X * path search defines
  2140. X */
  2141. X#define    HOMECHAR    '~'    /* char which indicates home directory */
  2142. X#define DOTCHAR        '.'    /* char which indicates current directory */
  2143. X#define    PATHCHAR    '/'    /* char which separates path components */
  2144. X#define    LISTCHAR    ':'    /* char which separates paths in a list */
  2145. X#define    PATHSIZE    1024    /* maximum length of path name */
  2146. X
  2147. X
  2148. X/*
  2149. X * Possible returns from hist_init.  Note that an error from hist_init does
  2150. X * not prevent calling the other routines, but fancy command line editing
  2151. X * is then disabled.
  2152. X */
  2153. X#define    HIST_SUCCESS    0    /* successfully inited */
  2154. X#define    HIST_INITED    1    /* initialization is already done */
  2155. X#define    HIST_NOFILE    2    /* bindings file could not be read */
  2156. X#define    HIST_NOTTY    3    /* terminal modes could not be set */
  2157. X
  2158. X
  2159. Xextern    int    hist_init HIST_PROTO((char *filename));
  2160. Xextern    void    hist_term HIST_PROTO((void));
  2161. Xextern    int    hist_getline HIST_PROTO((char *prompt, char *buf, int len));
  2162. Xextern    void    hist_saveline HIST_PROTO((char *line, int len));
  2163. X
  2164. X/* END CODE */
  2165. SHAR_EOF
  2166. chmod 0644 calc2.9.0/hist.h || echo "restore of calc2.9.0/hist.h fails"
  2167. set `wc -c calc2.9.0/hist.h`;Sum=$1
  2168. if test "$Sum" != "1475"
  2169. then echo original size 1475, current size $Sum;fi
  2170. echo "x - extracting calc2.9.0/input.c (Text)"
  2171. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/input.c &&
  2172. X/*
  2173. X * Copyright (c) 1993 David I. Bell
  2174. X * Permission is granted to use, distribute, or modify this source,
  2175. X * provided that this copyright notice remains intact.
  2176. X *
  2177. X * Nested input source file reader.
  2178. X * For terminal input, this also provides a simple command stack.
  2179. X */
  2180. X
  2181. X#include <ctype.h>
  2182. X#include <pwd.h>
  2183. X#include "calc.h"
  2184. X#include "config.h"
  2185. X#include "hist.h"
  2186. X
  2187. X
  2188. X#define TTYSIZE        100    /* reallocation size for terminal buffers */
  2189. X#define DEPTH        10    /* maximum depth of input */
  2190. X#define IS_READ        1    /* reading normally */
  2191. X#define IS_REREAD    2    /* reread current character */
  2192. X#define chartoint(ch)    ((ch) & 0xff)    /* make sure char is not negative */
  2193. X
  2194. X
  2195. Xtypedef struct {
  2196. X    short i_state;        /* state (read, reread) */
  2197. X    short i_char;        /* currently read char */
  2198. X    long i_line;        /* line number */
  2199. X    char *i_str;        /* current string for input (if not NULL) */
  2200. X    char *i_origstr;    /* original string so it can be freed */
  2201. X    char *i_ttystr;        /* current character of tty line (or NULL) */
  2202. X    FILE *i_fp;        /* current file for input (if not NULL) */
  2203. X    char *i_name;        /* file name if known */
  2204. X} INPUT;
  2205. X
  2206. X
  2207. Xstatic int linesize;        /* current max size of input line */
  2208. Xstatic char *linebuf;        /* current input line buffer */
  2209. Xstatic char *prompt;        /* current prompt for terminal */
  2210. Xstatic BOOL noprompt;        /* TRUE if should not print prompt */
  2211. X
  2212. Xstatic int depth;        /* current input depth */
  2213. Xstatic INPUT *cip;        /* current input source */
  2214. Xstatic INPUT inputs[DEPTH];    /* input sources */
  2215. X
  2216. X
  2217. Xstatic int openfile MATH_PROTO((char *name));
  2218. Xstatic int ttychar MATH_PROTO((void));
  2219. X
  2220. X
  2221. X/*
  2222. X * Open an input file by possibly searching through a path list
  2223. X * and also possibly applying the specified extension.  For example:
  2224. X * opensearchfile("barf", ".:/tmp", ".c") searches in order for the
  2225. X * files "./barf", "./barf.c", "/tmp/barf", and "/tmp/barf.c".
  2226. X *
  2227. X * Returns -1 if all specified files cannot be opened.
  2228. X */
  2229. Xint
  2230. Xopensearchfile(name, pathlist, extension)
  2231. X    char *name;        /* file name to be read */
  2232. X    char *pathlist;        /* list of colon separated paths (or NULL) */
  2233. X    char *extension;    /* extra extension to try (or NULL) */
  2234. X{
  2235. X    int i;
  2236. X    char *cp;
  2237. X    char path[PATHSIZE+1];    /* name being searched for */
  2238. X
  2239. X    /*
  2240. X     * Don't try the extension if the filename already contains it.
  2241. X     */
  2242. X    if (extension) {
  2243. X        i = strlen(name) - strlen(extension);
  2244. X        if ((i >= 0) && (strcmp(&name[i], extension) == 0))
  2245. X            extension = NULL;
  2246. X    }
  2247. X    /*
  2248. X     * If the name is absolute, or if there is no path list, then
  2249. X     * make one which just searches for the name straight.  Then
  2250. X     * search through the path list for the file, without and with
  2251. X     * the specified extension.
  2252. X     */
  2253. X    if (name[0] == PATHCHAR || 
  2254. X        name[0] == HOMECHAR || 
  2255. X        (name[0] == DOTCHAR && name[1] == PATHCHAR) || 
  2256. X        pathlist == NULL) {
  2257. X        pathlist = "";
  2258. X    }
  2259. X    pathlist--;
  2260. X    do {
  2261. X        pathlist++;
  2262. X        cp = path;
  2263. X        while (*pathlist && (*pathlist != LISTCHAR))
  2264. X            *cp++ = *pathlist++;
  2265. X        if (cp != path)
  2266. X            *cp++ = PATHCHAR;
  2267. X        strcpy(cp, name);
  2268. X        i = openfile(path);
  2269. X        if ((i < 0) && extension) {
  2270. X            strcat(path, extension);
  2271. X            i = openfile(path);
  2272. X        }
  2273. X    } while ((i < 0) && *pathlist);
  2274. X    return i;
  2275. X}
  2276. X
  2277. X
  2278. X/*
  2279. X * Given a filename with a leading ~, expand it into a home directory for 
  2280. X * that user.  This function will malloc the space for the expanded path.
  2281. X *
  2282. X * If the path is just ~, or begins with ~/, expand it to the home
  2283. X * directory of the current user.  If the environment variable $HOME
  2284. X * is known, it will be used, otherwise the password file will be
  2285. X * consulted.
  2286. X *
  2287. X * If the path is just ~username, or ~username/, expand it to the home
  2288. X * directory of that user by looking it up in the password file.
  2289. X *
  2290. X * If the password file must be consulted and the username is not found
  2291. X * a NULL pointer is returned.
  2292. X */
  2293. Xstatic char *
  2294. Xhomeexpand(name)
  2295. X    char *name;        /* a filename with a leading ~ */
  2296. X{
  2297. X    struct passwd *ent;    /* password entry */
  2298. X    char *home2;        /* fullpath of the home directory */
  2299. X    char *fullpath;        /* the malloced expanded path */
  2300. X    char *after;        /* after the ~user or ~ */
  2301. X    char username[PATHSIZE+1];    /* extratced username */
  2302. X
  2303. X    /* firewall */
  2304. X    if (name[0] != HOMECHAR)
  2305. X        return NULL;
  2306. X
  2307. X    /*
  2308. X     * obtain the home directory component
  2309. X     */
  2310. X    switch (name[1]) {
  2311. X    case PATHCHAR:        /* ~/... */
  2312. X    case '\0':        /* ~ */
  2313. X        home2 = home;
  2314. X        after = name+1;
  2315. X        break;
  2316. X    default:        /* ~username or ~username/... */
  2317. X
  2318. X        /* extract the username after the ~ */
  2319. X        after = (char *)strchr(name+2, PATHCHAR);
  2320. X        if (after == NULL) {
  2321. X            /* path is just ~username */
  2322. X            ent = getpwnam(name+1);
  2323. X            if (ent == NULL) {
  2324. X                /* unknown user */
  2325. X                return NULL;
  2326. X            }
  2327. X            /* just malloc the home directory and return it */
  2328. X            fullpath = (char *)malloc(strlen(ent->pw_dir)+1);
  2329. X            strcpy(fullpath, ent->pw_dir);
  2330. X            return fullpath;
  2331. X        }
  2332. X        if (after-name > PATHSIZE+1) {
  2333. X            /* username is too big */
  2334. X            return NULL;
  2335. X        }
  2336. X        strncpy(username, name+1, after-name-1);
  2337. X        username[after-name-1] = '\0';
  2338. X
  2339. X        /* get that user's home directory */
  2340. X        ent = getpwnam(username);
  2341. X        if (ent == NULL) {
  2342. X            /* unknown user */
  2343. X            return NULL;
  2344. X        }
  2345. X        home2 = ent->pw_dir;
  2346. X        break;
  2347. X    }
  2348. X
  2349. X    /*
  2350. X     * build the fullpath given the home directory
  2351. X     */
  2352. X    fullpath = (char *)malloc(strlen(home2)+strlen(after)+1);
  2353. X    sprintf(fullpath, "%s%s", home2, after);
  2354. X    return fullpath;
  2355. X}
  2356. X
  2357. X
  2358. X/*
  2359. X * f_open - ~-expand a filename and fopen() it
  2360. X */
  2361. XFILE *
  2362. Xf_open(name, mode)
  2363. X    char *name;        /* the filename to open */
  2364. X    char *mode;        /* the fopen mode to use */
  2365. X{
  2366. X    FILE *fp;        /* open file descriptor */
  2367. X    char *fullname;        /* file name with HOMECHAR expansion */
  2368. X
  2369. X    /*
  2370. X     * expand ~ if needed
  2371. X     */
  2372. X    if (name[0] == HOMECHAR) {
  2373. X        fullname = homeexpand(name);
  2374. X        if (fullname == NULL)
  2375. X            return NULL;
  2376. X        fp = fopen(fullname, mode);
  2377. X        free(fullname);
  2378. X    } else {
  2379. X        fp = fopen(name, mode);
  2380. X    }
  2381. X    return fp;
  2382. X}
  2383. X
  2384. X
  2385. X/*
  2386. X * Setup for reading from a input file.
  2387. X * Returns -1 if file could not be opened.
  2388. X */
  2389. Xstatic int
  2390. Xopenfile(name)
  2391. X    char *name;        /* file name to be read */
  2392. X{
  2393. X    FILE *fp;        /* open file descriptor */
  2394. X
  2395. X    if (depth >= DEPTH)
  2396. X         return -1;
  2397. X    fp = f_open(name, "r");
  2398. X    if (fp == NULL)
  2399. X         return -1;
  2400. X    cip++;
  2401. X    cip->i_state = IS_READ;
  2402. X    cip->i_char = '\0';
  2403. X    cip->i_str = NULL;
  2404. X    cip->i_origstr = NULL;
  2405. X    cip->i_ttystr = NULL;
  2406. X    cip->i_fp = fp;
  2407. X    cip->i_line = 1;
  2408. X    cip->i_name = (char *)malloc(strlen(name) + 1);
  2409. X    strcpy(cip->i_name, name);
  2410. X    depth++;
  2411. X    return 0;
  2412. X}
  2413. X
  2414. X
  2415. X/*
  2416. X * Open a string for scanning. String is ended by a null character.
  2417. X * String is copied into local memory so it can be trashed afterwards.
  2418. X * Returns -1 if cannot open string.
  2419. X */
  2420. Xint
  2421. Xopenstring(str)
  2422. X    char *str;        /* string to be opened */
  2423. X{
  2424. X    char *cp;        /* copied string */
  2425. X
  2426. X    if ((depth >= DEPTH) || (str == NULL))
  2427. X         return -1;
  2428. X    cp = (char *)malloc(strlen(str) + 1);
  2429. X    if (cp == NULL)
  2430. X         return -1;
  2431. X    strcpy(cp, str);
  2432. X    cip++;
  2433. X    cip->i_state = IS_READ;
  2434. X    cip->i_char = '\0';
  2435. X    cip->i_str = cp;
  2436. X    cip->i_origstr = cp;
  2437. X    cip->i_fp = NULL;
  2438. X    cip->i_name = NULL;
  2439. X    cip->i_ttystr = NULL;
  2440. X    cip->i_line = 1;
  2441. X    depth++;
  2442. X    return 0;
  2443. X}
  2444. X
  2445. X
  2446. X/*
  2447. X * Set to read input from the terminal.
  2448. X * Returns -1 if there is no more depth for input.
  2449. X */
  2450. Xint
  2451. Xopenterminal()
  2452. X{
  2453. X    if (depth >= DEPTH)
  2454. X         return -1;
  2455. X    cip++;
  2456. X    cip->i_state = IS_READ;
  2457. X    cip->i_char = '\0';
  2458. X    cip->i_str = NULL;
  2459. X    cip->i_origstr = NULL;
  2460. X    cip->i_ttystr = NULL;
  2461. X    cip->i_fp = NULL;
  2462. X    cip->i_name = NULL;
  2463. X    cip->i_line = 1;
  2464. X    depth++;
  2465. X    return 0;
  2466. X}
  2467. X
  2468. X
  2469. X/*
  2470. X * Close the current input source.
  2471. X */
  2472. Xstatic void
  2473. Xcloseinput()
  2474. X{
  2475. X    if (depth <= 0)
  2476. X        return;
  2477. X    if (cip->i_origstr)
  2478. X        free(cip->i_origstr);
  2479. X    if (cip->i_fp)
  2480. X        fclose(cip->i_fp);
  2481. X    if (cip->i_name)
  2482. X        free(cip->i_name);
  2483. X    cip--;
  2484. X    depth--;
  2485. X}
  2486. X
  2487. X
  2488. X/*
  2489. X * Reset the input sources back to the initial state.
  2490. X */
  2491. Xvoid
  2492. Xresetinput()
  2493. X{
  2494. X    while (depth > 0)
  2495. X        closeinput();
  2496. X    cip = inputs;
  2497. X    noprompt = FALSE;
  2498. X}
  2499. X
  2500. X
  2501. X/*
  2502. X * Set the prompt for terminal input.
  2503. X */
  2504. Xvoid
  2505. Xsetprompt(str)
  2506. X    char *str;
  2507. X{
  2508. X    prompt = str;
  2509. X    noprompt = FALSE;
  2510. X}
  2511. X
  2512. X
  2513. X/*
  2514. X * Read the next character from the current input source.
  2515. X * End of file closes current input source, and returns EOF character.
  2516. X */
  2517. Xint
  2518. Xnextchar()
  2519. X{
  2520. X    int ch;            /* current input character */
  2521. X
  2522. X    if (depth == 0)        /* input finished */
  2523. X         return EOF;
  2524. X    if (cip->i_state == IS_REREAD) {    /* rereading current char */
  2525. X         ch = cip->i_char;
  2526. X         cip->i_state = IS_READ;
  2527. X         if (ch == '\n')
  2528. X            cip->i_line++;
  2529. X         return ch;
  2530. X    }
  2531. X    if (cip->i_str) {        /* from string */
  2532. X        ch = chartoint(*cip->i_str++);
  2533. X        if (ch == '\0')
  2534. X            ch = EOF;
  2535. X    } else if (cip->i_fp) {        /* from file */
  2536. X        ch = fgetc(cip->i_fp);
  2537. X    } else {            /* from terminal */
  2538. X        ch = ttychar();
  2539. X    }
  2540. X    if (ch == EOF) {        /* fix up end of file */
  2541. X        closeinput();
  2542. X        ch = EOF;
  2543. X    }
  2544. X    if (depth > 0)
  2545. X        cip->i_char = (char)ch;    /* save for rereads */
  2546. X    if (ch == '\n')
  2547. X        cip->i_line++;
  2548. X    return ch;
  2549. X}
  2550. X
  2551. X
  2552. X/*
  2553. X * Read in the next line of input from the current input source.
  2554. X * The line is terminated with a null character, and does not contain
  2555. X * the final newline character.  The returned string is only valid
  2556. X * until the next such call, and so must be copied if necessary.
  2557. X * Returns NULL on end of file.
  2558. X */
  2559. Xchar *
  2560. Xnextline()
  2561. X{
  2562. X    char *cp;
  2563. X    int ch;
  2564. X    int len;
  2565. X
  2566. X    cp = linebuf;
  2567. X    if (linesize == 0) {
  2568. X        cp = (char *)malloc(TTYSIZE + 1);
  2569. X        if (cp == NULL)
  2570. X            math_error("Cannot allocate line buffer");
  2571. X        linebuf = cp;
  2572. X        linesize = TTYSIZE;
  2573. X    }
  2574. X    len = 0;
  2575. X    for (;;) {
  2576. X        noprompt = TRUE;
  2577. X        ch = nextchar();
  2578. X        noprompt = FALSE;
  2579. X        if (ch == EOF)
  2580. X            return NULL;
  2581. X        if (ch == '\0')
  2582. X            continue;
  2583. X        if (ch == '\n')
  2584. X            break;
  2585. X        if (len >= linesize) {
  2586. X            cp = (char *)realloc(cp, linesize + TTYSIZE + 1);
  2587. X            if (cp == NULL)
  2588. X                math_error("Cannot realloc line buffer");
  2589. X            linebuf = cp;
  2590. X            linesize += TTYSIZE;
  2591. X        }
  2592. X        cp[len++] = (char)ch;
  2593. X    }
  2594. X    cp[len] = '\0';
  2595. X    return linebuf;
  2596. X}
  2597. X
  2598. X
  2599. X/*
  2600. X * Read the next character from the terminal.
  2601. X * The routines in the history module are called so that the user
  2602. X * can use a command history and emacs-like editing of the line.
  2603. X */
  2604. Xstatic int
  2605. Xttychar()
  2606. X{
  2607. X    int ch;            /* current char */
  2608. X    int len;        /* length of current command */
  2609. X    static char charbuf[1000];
  2610. X
  2611. X    /*
  2612. X     * If we have more to read from the saved command line, then do that.
  2613. X     * When we see a newline character, then clear the pointer so we will
  2614. X     * read a new line on the next call.
  2615. X     */
  2616. X    if (cip->i_ttystr) {
  2617. X        ch = chartoint(*cip->i_ttystr++);
  2618. X        if (ch == '\n')
  2619. X            cip->i_ttystr = NULL;
  2620. X        return ch;
  2621. X    }
  2622. X
  2623. X    /*
  2624. X     * We need another complete line.
  2625. X     */
  2626. X    abortlevel = 0;
  2627. X    inputwait = TRUE;
  2628. X    len = hist_getline(noprompt ? "" : prompt, charbuf, sizeof(charbuf));
  2629. X    if (len == 0) {
  2630. X        inputwait = FALSE;
  2631. X        return EOF;
  2632. X    }
  2633. X    inputwait = FALSE;
  2634. X
  2635. X    /*
  2636. X     * Handle shell escape if present
  2637. X     */
  2638. X    if (charbuf[0] == '!') {        /* do a shell command */
  2639. X        char *cmd;
  2640. X
  2641. X        cmd = charbuf + 1;
  2642. X        if (*cmd == '\0' || *cmd == '\n')
  2643. X            cmd = shell;
  2644. X        system(cmd);
  2645. X        return '\n';
  2646. X    }
  2647. X    hist_saveline(charbuf, len);
  2648. X
  2649. X    /*
  2650. X     * Return the first character of the line, and set up to
  2651. X     * return the rest of it with later calls.
  2652. X     */
  2653. X    ch = chartoint(charbuf[0]);
  2654. X    if (ch != '\n')
  2655. X        cip->i_ttystr = charbuf + 1;
  2656. X    return ch;
  2657. X}
  2658. X
  2659. X
  2660. X/*
  2661. X * Return whether or not the input source is the terminal.
  2662. X */
  2663. XBOOL
  2664. Xinputisterminal()
  2665. X{
  2666. X    return ((depth <= 0) || ((cip->i_str == NULL) && (cip->i_fp == NULL)));
  2667. X}
  2668. X
  2669. X
  2670. X/*
  2671. X * Return the name of the current input file.
  2672. X * Returns NULL for terminal or strings.
  2673. X */
  2674. Xchar *
  2675. Xinputname()
  2676. X{
  2677. X    if (depth <= 0)
  2678. X        return NULL;
  2679. X    return cip->i_name;
  2680. X}
  2681. X
  2682. X
  2683. X/*
  2684. X * Return the current line number.
  2685. X */
  2686. Xlong
  2687. Xlinenumber()
  2688. X{
  2689. X    if (depth > 0)
  2690. X        return cip->i_line;
  2691. X    return 1;
  2692. X}
  2693. X
  2694. X
  2695. X/*
  2696. X * Restore the next character to be read again on the next nextchar call.
  2697. X */
  2698. Xvoid
  2699. Xreread()
  2700. X{
  2701. X    if ((depth <= 0) || (cip->i_state == IS_REREAD))
  2702. X        return;
  2703. X    cip->i_state = IS_REREAD;
  2704. X    if (cip->i_char == '\n')
  2705. X        cip->i_line--;
  2706. X}
  2707. X
  2708. X
  2709. X/*
  2710. X * Process all startup files found in the $CALCRC path.
  2711. X */
  2712. Xvoid
  2713. Xrunrcfiles()
  2714. X{
  2715. X    char path[PATHSIZE+1];    /* name being searched for */
  2716. X    char *cp;
  2717. X    char *newcp;
  2718. X    char *p;
  2719. X    int i;
  2720. X
  2721. X    /* execute each file in the list */
  2722. X    for (cp=calcrc, newcp=(char *)strchr(calcrc, LISTCHAR);
  2723. X         cp != NULL && *cp;
  2724. X         cp = newcp, 
  2725. X         newcp=(newcp) ? (char *)strchr(newcp+1, LISTCHAR) : NULL) {
  2726. X
  2727. X        /* load file name into the path */
  2728. X        if (newcp == NULL) {
  2729. X            strcpy(path, cp);
  2730. X        } else {
  2731. X            strncpy(path, cp, newcp-cp);
  2732. X            path[newcp-cp] = '\0';
  2733. X        }
  2734. X
  2735. X        /* find the start of the path */
  2736. X        p = (path[0] == ':') ? path+1 : path;
  2737. X        if (p[0] == '\0') {
  2738. X            continue;
  2739. X        }
  2740. X
  2741. X        /* process the current file in the list */
  2742. X        i = openfile(p);
  2743. X        if (i < 0)
  2744. X            continue;
  2745. X        getcommands(FALSE);
  2746. X    }
  2747. X}
  2748. X
  2749. X/* END CODE */
  2750. SHAR_EOF
  2751. chmod 0644 calc2.9.0/input.c || echo "restore of calc2.9.0/input.c fails"
  2752. set `wc -c calc2.9.0/input.c`;Sum=$1
  2753. if test "$Sum" != "12268"
  2754. then echo original size 12268, current size $Sum;fi
  2755. echo "x - extracting calc2.9.0/label.c (Text)"
  2756. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/label.c &&
  2757. X/*
  2758. X * Copyright (c) 1993 David I. Bell
  2759. X * Permission is granted to use, distribute, or modify this source,
  2760. X * provided that this copyright notice remains intact.
  2761. X *
  2762. X * Label handling routines.
  2763. X */
  2764. X
  2765. X#include "calc.h"
  2766. X#include "token.h"
  2767. X#include "label.h"
  2768. X#include "string.h"
  2769. X#include "opcodes.h"
  2770. X#include "func.h"
  2771. X
  2772. Xstatic long labelcount;            /* number of user labels defined */
  2773. Xstatic STRINGHEAD labelnames;        /* list of user label names */
  2774. Xstatic LABEL labels[MAXLABELS];        /* list of user labels */
  2775. X
  2776. X
  2777. X/*
  2778. X * Initialize the table of labels for a function.
  2779. X */
  2780. Xvoid
  2781. Xinitlabels()
  2782. X{
  2783. X    labelcount = 0;
  2784. X    initstr(&labelnames);
  2785. X}
  2786. X
  2787. X
  2788. X/*
  2789. X * Define a user named label to have the offset of the next opcode.
  2790. X */
  2791. Xvoid
  2792. Xdefinelabel(name)
  2793. X    char *name;            /* label name */
  2794. X{
  2795. X    register LABEL *lp;        /* current label */
  2796. X    long i;                /* current label index */
  2797. X
  2798. X    i = findstr(&labelnames, name);
  2799. X    if (i >= 0) {
  2800. X        lp = &labels[i];
  2801. X        if (lp->l_offset) {
  2802. X            scanerror(T_NULL, "Label \"%s\" is multiply defined",
  2803. X                name);
  2804. X            return;
  2805. X        }
  2806. X        setlabel(lp);
  2807. X        return;
  2808. X    }
  2809. X    if (labelcount >= MAXLABELS) {
  2810. X        scanerror(T_NULL, "Too many labels in use");
  2811. X        return;
  2812. X    }
  2813. X    lp = &labels[labelcount++];
  2814. X    lp->l_chain = 0;
  2815. X    lp->l_offset = curfunc->f_opcodecount;
  2816. X    lp->l_name = addstr(&labelnames, name);
  2817. X    clearopt();
  2818. X}
  2819. X
  2820. X
  2821. X/*
  2822. X * Add the offset corresponding to the specified user label name to the
  2823. X * opcode table for a function. If the label is not yet defined, then a
  2824. X * chain of undefined offsets is built using the offset value, and it
  2825. X * will be fixed up when the label is defined.
  2826. X */
  2827. Xvoid
  2828. Xaddlabel(name)
  2829. X    char *name;            /* user symbol name */
  2830. X{
  2831. X    register LABEL *lp;        /* current label */
  2832. X    long i;                /* counter */
  2833. X
  2834. X    for (i = labelcount, lp = labels; --i >= 0; lp++) {
  2835. X        if (strcmp(name, lp->l_name))
  2836. X            continue;
  2837. X        uselabel(lp);
  2838. X        return;
  2839. X    }
  2840. X    if (labelcount >= MAXLABELS) {
  2841. X        scanerror(T_NULL, "Too many labels in use");
  2842. X        return;
  2843. X    }
  2844. X    lp = &labels[labelcount++];
  2845. X    lp->l_offset = 0;
  2846. X    lp->l_chain = curfunc->f_opcodecount;
  2847. X    lp->l_name = addstr(&labelnames, name);
  2848. X    addop((long)0);
  2849. X}
  2850. X
  2851. X
  2852. X/*
  2853. X * Check to make sure that all labels are defined.
  2854. X */
  2855. Xvoid
  2856. Xchecklabels()
  2857. X{
  2858. X    register LABEL *lp;        /* label being checked */
  2859. X    long i;                /* counter */
  2860. X
  2861. X    for (i = labelcount, lp = labels; --i >= 0; lp++) {
  2862. X        if (lp->l_offset > 0)
  2863. X            continue;
  2864. X        scanerror(T_NULL, "Label \"%s\" was never defined",
  2865. X            lp->l_name);
  2866. X    }
  2867. X}
  2868. X
  2869. X
  2870. X/*
  2871. X * Clear an internal label for use.
  2872. X */
  2873. Xvoid
  2874. Xclearlabel(lp)
  2875. X    register LABEL *lp;    /* label being cleared */
  2876. X{
  2877. X    lp->l_offset = 0;
  2878. X    lp->l_chain = 0;
  2879. X    lp->l_name = NULL;
  2880. X}
  2881. X
  2882. X
  2883. X/*
  2884. X * Set any label to have the value of the next opcode in the current
  2885. X * function being defined.  If there were forward references to it,
  2886. X * all such references are patched up.
  2887. X */
  2888. Xvoid
  2889. Xsetlabel(lp)
  2890. X    register LABEL *lp;    /* label being set */
  2891. X{
  2892. X    register FUNC *fp;    /* current function */
  2893. X    long curfix;        /* offset of current location being fixed */
  2894. X    long nextfix;        /* offset of next location to fix up */
  2895. X    long offset;        /* offset of this label */
  2896. X
  2897. X    fp = curfunc;
  2898. X    offset = fp->f_opcodecount;
  2899. X    nextfix = lp->l_chain;
  2900. X    while (nextfix > 0) {
  2901. X        curfix = nextfix;
  2902. X        nextfix = fp->f_opcodes[curfix];
  2903. X        fp->f_opcodes[curfix] = offset;
  2904. X    }
  2905. X    lp->l_chain = 0;
  2906. X    lp->l_offset = offset;
  2907. X    clearopt();
  2908. X}
  2909. X
  2910. X
  2911. X/*
  2912. X * Use the specified label at the current location in the function
  2913. X * being compiled.  This adds one word to the current function being
  2914. X * compiled.  If the label is not yet defined, a patch chain is built
  2915. X * so the reference can be fixed when the label is defined.
  2916. X */
  2917. Xvoid
  2918. Xuselabel(lp)
  2919. X    register LABEL *lp;        /* label being used */
  2920. X{
  2921. X    long offset;            /* offset being added */
  2922. X
  2923. X    offset = curfunc->f_opcodecount;
  2924. X    if (lp->l_offset > 0) {
  2925. X        addop(lp->l_offset);
  2926. X        return;
  2927. X    }
  2928. X    addop(lp->l_chain);
  2929. X    lp->l_chain = offset;
  2930. X}
  2931. X
  2932. X/* END CODE */
  2933. SHAR_EOF
  2934. chmod 0644 calc2.9.0/label.c || echo "restore of calc2.9.0/label.c fails"
  2935. set `wc -c calc2.9.0/label.c`;Sum=$1
  2936. if test "$Sum" != "3757"
  2937. then echo original size 3757, current size $Sum;fi
  2938. echo "x - extracting calc2.9.0/label.h (Text)"
  2939. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/label.h &&
  2940. X/*
  2941. X * Copyright (c) 1993 David I. Bell
  2942. X * Permission is granted to use, distribute, or modify this source,
  2943. X * provided that this copyright notice remains intact.
  2944. X */
  2945. X
  2946. X#ifndef    LABEL_H
  2947. X#define    LABEL_H
  2948. X
  2949. X
  2950. X#include "zmath.h"
  2951. X
  2952. X
  2953. X#define    NULL_LABEL    ((LABEL *) 0)
  2954. X
  2955. X
  2956. X/*
  2957. X * Label structures.
  2958. X */
  2959. Xtypedef struct {
  2960. X    long l_offset;          /* offset into code of label */
  2961. X    long l_chain;          /* offset into code of undefined chain */
  2962. X    char *l_name;          /* name of label if any */
  2963. X} LABEL;
  2964. X
  2965. X
  2966. Xextern void initlabels MATH_PROTO((void));
  2967. Xextern void definelabel MATH_PROTO((char *name));
  2968. Xextern void addlabel MATH_PROTO((char *name));
  2969. Xextern void clearlabel MATH_PROTO((LABEL *lp));
  2970. Xextern void setlabel MATH_PROTO((LABEL *lp));
  2971. Xextern void uselabel MATH_PROTO((LABEL *lp));
  2972. Xextern void checklabels MATH_PROTO((void));
  2973. X
  2974. X#endif
  2975. X
  2976. X/* END CODE */
  2977. SHAR_EOF
  2978. chmod 0644 calc2.9.0/label.h || echo "restore of calc2.9.0/label.h fails"
  2979. set `wc -c calc2.9.0/label.h`;Sum=$1
  2980. if test "$Sum" != "817"
  2981. then echo original size 817, current size $Sum;fi
  2982. echo "x - extracting calc2.9.0/lint.sed (Text)"
  2983. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/lint.sed &&
  2984. X/: warning: conversion from long may lose accuracy$/d
  2985. SHAR_EOF
  2986. echo "End of part 5"
  2987. echo "File calc2.9.0/lint.sed is continued in part 6"
  2988. echo "6" > s2_seq_.tmp
  2989. exit 0
  2990.