home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume11 / gnuplot2 / part14 < prev    next >
Encoding:
Text File  |  1990-03-25  |  29.2 KB  |  1,316 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Pixar -- Marin County, California
  3. subject: v11i079: Gnuplot 2.0 - 14 of 14
  4. From: thaw@ucbvax.Berkeley.EDU@pixar.UUCP (Tom Williams)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 11, Issue 79
  8. Submitted-by: thaw@ucbvax.Berkeley.EDU@pixar.UUCP (Tom Williams)
  9. Archive-name: gnuplot2/part14
  10.  
  11. This is gnuplot.sh14 (whew!!)
  12.  
  13. --- CUT HERE ---
  14. #! /bin/sh
  15. echo x - translate/plot.h
  16. sed 's/^X//' >translate/plot.h <<'*-*-END-of-translate/plot.h-*-*'
  17. X/*
  18. X *
  19. X *    gnutex/gnuplot translator  --  plot.h
  20. X *
  21. X * By David Kotz, 1990.
  22. X * Department of Computer Science, Duke University, Durham, NC 27706.
  23. X * Mail to dfk@cs.duke.edu.
  24. X */
  25. X
  26. X#define PROGRAM "gnut2p"
  27. X#define PROMPT "gnut2p>"
  28. X
  29. X#define TRUE 1
  30. X#define FALSE 0
  31. X
  32. X#define Pi 3.141592653589793
  33. X
  34. X#define MAX_PLOTS 16            /* max number of overlapping plots */
  35. X#define MAX_LINE_LEN 512    /* maximum number of chars allowed on line */
  36. X#define MAX_TOKENS 200
  37. X#define MAX_ID_LEN 200        /* max length of an identifier (long for files)*/
  38. X
  39. X#ifdef PC
  40. X#define MAX_UDFS 20            /* max number of user-defined functions */
  41. X#else /* PC */
  42. X#define MAX_UDFS 100
  43. X#endif /* PC */
  44. X
  45. X#define MAX_STYLES 20        /* max number of user-defined styles */
  46. X#define MAX_KEYS 16            /* max number of entries in key */
  47. X#define MAX_VALUES 50        /* max number of user-defined constants */
  48. X#define MAX_AT_LEN 100        /* max number of entries in action table */
  49. X#define STACK_DEPTH 100
  50. X#define NO_CARET (-1)
  51. X
  52. X#define SAMPLES 160            /* default number of samples for a plot */
  53. X#define ZERO    1e-8        /* default for 'zero' set option */
  54. X
  55. X/*
  56. X * note about HUGE:  this number is just used as a flag for really
  57. X *   big numbers, so it doesn't have to be the absolutely biggest number
  58. X *   on the machine.
  59. X */
  60. X
  61. X#ifdef PC
  62. X#define  HUGE 1e38
  63. X#endif /* PC */
  64. X
  65. X#define END_OF_COMMAND (c_token == num_tokens || equals(c_token,";"))
  66. X#define push(arg) f_pushc(arg)    /* same thing! */
  67. X
  68. X#define top_of_stack stack[s_p]
  69. X
  70. Xtypedef int BOOLEAN;
  71. Xtypedef int (*FUNC_PTR)();
  72. X
  73. Xenum {
  74. X    C_PI, NEXT_VALUE
  75. X};
  76. X
  77. Xenum operators {
  78. X    PUSH, PUSHC, PUSHD, CALL, TERNIARY, LNOT, BNOT, UMINUS, LOR, LAND, BOR,
  79. X    XOR, BAND, EQ, NE, GT, LT, GE, LE, PLUS, MINUS, MULT, DIV, MOD, POWER,
  80. X    SF_START
  81. X};
  82. X
  83. Xenum DATA_TYPES {
  84. X    INT, CMPLX
  85. X};
  86. X
  87. Xenum PLOT_TYPES {
  88. X    FUNC, DATA
  89. X};
  90. X
  91. Xenum PLOT_STYLE {
  92. X    LINES, POINTS, IMPULSES, LINESPOINTS, DOTS
  93. X};
  94. X#define FIXED_STYLES ((int)DOTS) /* highest numbered fixed style */
  95. X
  96. Xstruct cmplx {
  97. X    double real, imag;
  98. X};
  99. X
  100. Xstruct value {
  101. X    enum DATA_TYPES type;
  102. X    union {
  103. X        char *str_val;
  104. X        int int_val;
  105. X        struct cmplx cmplx_val;
  106. X    } v;
  107. X};
  108. X
  109. Xstruct lexical_unit {
  110. X    BOOLEAN is_token;        /* true if token, false if a value */ 
  111. X    struct value l_val;
  112. X    int start_index;    /* index of first char in token */
  113. X    int length;        /* length of token in chars */
  114. X};
  115. X
  116. Xstruct at_entry {        /* action table entry */
  117. X    int index;        /* index into function table */
  118. X    struct value arg;
  119. X};
  120. X
  121. Xstruct at_type {
  122. X    int count;
  123. X    struct at_entry actions[MAX_AT_LEN];
  124. X};
  125. X
  126. Xstruct ft_entry {        /* standard function table entry */
  127. X    char *ft_name;        /* pointer to name of this function */
  128. X    FUNC_PTR funct;        /* address of function to call */
  129. X};
  130. X
  131. Xstruct udft_entry {        /* user-defined function table entry */
  132. X    char udft_name[MAX_ID_LEN+1];/* name of this function entry */
  133. X    struct at_type at;    /* action table to execute */
  134. X    char definition[MAX_LINE_LEN+1]; /* definition of function as typed */
  135. X    struct value dummy_value;/* current value of dummy variable */
  136. X};
  137. X
  138. Xstruct vt_entry {        /* value table entry */
  139. X    char vt_name[MAX_ID_LEN+1];/* name of this value entry */
  140. X    BOOLEAN vt_undef;        /* true if not defined yet */
  141. X    struct value vt_value;    /* value it has */
  142. X};
  143. X
  144. Xstruct st_entry {        /* style table entry */
  145. X    char st_name[MAX_ID_LEN+1];/* name of this style entry */
  146. X    BOOLEAN st_undef;        /* true if not defined yet */
  147. X    char st_point[MAX_ID_LEN+1]; /* string for point */
  148. X    float st_spacing;        /* spacing of seqence */
  149. X    short st_length;        /* length of sequence */
  150. X#define MAX_STYLE_SEQ_LENGTH 5
  151. X    char st_seq[MAX_STYLE_SEQ_LENGTH][MAX_ID_LEN+1]; /* dot sequence */
  152. X};
  153. Xextern int next_style;
  154. X
  155. Xstruct curve_points {
  156. X    enum PLOT_TYPES plot_type;
  157. X    unsigned int plot_style;    /* now an int to include user-defined styles */
  158. X    char def[MAX_LINE_LEN + 1];
  159. X    char title[MAX_LINE_LEN + 1];
  160. X};
  161. X
  162. Xstruct termentry {
  163. X    char name[MAX_ID_LEN + 1];
  164. X    unsigned int xmax,ymax,v_char,h_char,v_tic,h_tic;
  165. X    FUNC_PTR init,reset,text,graphics,move,vector,linetype,lrput_text,
  166. X        ulput_text,point;
  167. X    FUNC_PTR xyput_text, xtick_text, ytick_text;
  168. X    FUNC_PTR plotstyle;
  169. X};
  170. X
  171. X/*
  172. X * SS$_NORMAL is "normal completion", STS$M_INHIB_MSG supresses
  173. X * printing a status message.
  174. X * SS$_ABORT is the general abort status code.
  175. X from:    Martin Minow
  176. X    decvax!minow
  177. X */
  178. X#ifdef    vms
  179. X#include        <ssdef.h>
  180. X#include        <stsdef.h>
  181. X#define    IO_SUCCESS    (SS$_NORMAL | STS$M_INHIB_MSG)
  182. X#define    IO_ERROR    SS$_ABORT
  183. X#endif /* vms */
  184. X
  185. X#ifndef    IO_SUCCESS    /* DECUS or VMS C will have defined these already */
  186. X#define    IO_SUCCESS    0
  187. X#endif
  188. X#ifndef    IO_ERROR
  189. X#define    IO_ERROR    1
  190. X#endif
  191. *-*-END-of-translate/plot.h-*-*
  192. echo x - translate/scanner.c
  193. sed 's/^X//' >translate/scanner.c <<'*-*-END-of-translate/scanner.c-*-*'
  194. X/*
  195. X *
  196. X *    G N U P L O T  --  scanner.c
  197. X *
  198. X *  Copyright (C) 1986 Colin Kelley, Thomas Williams
  199. X *
  200. X *  You may use this code as you wish if credit is given and this message
  201. X *  is retained.
  202. X *
  203. X *  Please e-mail any useful additions to vu-vlsi!plot so they may be
  204. X *  included in later releases.
  205. X *
  206. X *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
  207. X */
  208. X/*
  209. X * Modifications for LaTeX and other support by David Kotz, 1988.
  210. X * Department of Computer Science, Duke University, Durham, NC 27706.
  211. X * Mail to dfk@cs.duke.edu.
  212. X */
  213. X
  214. X#include <stdio.h>
  215. X#include <ctype.h>
  216. X#include "plot.h"
  217. X
  218. X#ifdef vms
  219. X
  220. X#include stdio
  221. X#include descrip
  222. X#include errno
  223. X
  224. X#define MAILBOX "PLOT$MAILBOX"
  225. X#define pclose(f) fclose(f)
  226. X
  227. X#endif /* vms */
  228. X
  229. X
  230. X#ifndef STDOUT
  231. X#define STDOUT 1
  232. X#endif
  233. X
  234. X#define LBRACE '{'
  235. X#define RBRACE '}'
  236. X
  237. X#define APPEND_TOKEN {token[t_num].length++; current++;}
  238. X
  239. X#define SCAN_IDENTIFIER while (isalpha(expression[current + 1]) ||\
  240. X                   isdigit(expression[current + 1]))\
  241. X                APPEND_TOKEN
  242. X
  243. Xextern struct lexical_unit token[MAX_TOKENS];
  244. X
  245. Xstatic int t_num;    /* number of token I'm working on */
  246. Xint comment_pos;            /* position of comment in string (-1 == none) */
  247. X
  248. Xchar *strcat(), *strcpy();
  249. X
  250. X/*
  251. X * scanner() breaks expression[] into lexical units, storing them in token[].
  252. X *   The total number of tokens found is returned as the function value.
  253. X *   Scanning will stop when '\0' is found in expression[], or when token[]
  254. X *     is full.
  255. X *
  256. X *     Scanning is performed by following rules:
  257. X *
  258. X *        Current char    token should contain
  259. X *     -------------    -----------------------
  260. X *        1.  alpha        all following alpha-numerics
  261. X *        2.  digit        0 or more following digits, 0 or 1 decimal point,
  262. X *                          0 or more digits, 0 or 1 'e' or 'E',
  263. X *                          0 or more digits.
  264. X *        3.  ^,+,-,/        only current char
  265. X *            %,~,(,)
  266. X *            [,],;,:,
  267. X *            ?,comma
  268. X *        4.  &,|,=,*        current char; also next if next is same
  269. X *        5.  !,<,>        current char; also next if next is =
  270. X *        6.  ", '        all chars up until matching quote
  271. X *        7.  #          this token cuts off scanning of the line (DFK).
  272. X *
  273. X *        white space between tokens is ignored
  274. X */
  275. Xscanner(expression)
  276. Xchar expression[];
  277. X{
  278. Xregister int current;    /* index of current char in expression[] */
  279. Xregister int quote;
  280. Xchar brace;
  281. X
  282. X     comment_pos = -1;        /* initialize to no comment found */
  283. X
  284. X    for (current = t_num = 0;
  285. X        t_num < MAX_TOKENS && expression[current] != '\0';
  286. X        current++) {
  287. Xagain:
  288. X        if (isspace(expression[current]))
  289. X            continue;                        /* skip the whitespace */
  290. X        token[t_num].start_index = current;
  291. X        token[t_num].length = 1;
  292. X        token[t_num].is_token = TRUE;    /* to start with...*/
  293. X
  294. X        if (expression[current] == '`') {
  295. X            substitute(&expression[current],MAX_LINE_LEN - current);
  296. X            goto again;
  297. X        }
  298. X        if (isalpha(expression[current])) {
  299. X            SCAN_IDENTIFIER;
  300. X        } else if (isdigit(expression[current]) ||
  301. X               expression[current] == '.') {
  302. X            token[t_num].is_token = FALSE;
  303. X            token[t_num].length = get_num(&expression[current]);
  304. X            current += (token[t_num].length - 1);
  305. X        } else if (expression[current] == LBRACE) {
  306. X            token[t_num].is_token = FALSE;
  307. X            token[t_num].l_val.type = CMPLX;
  308. X            if ((sscanf(&expression[++current],"%lf , %lf %c",
  309. X                &token[t_num].l_val.v.cmplx_val.real,
  310. X                &token[t_num].l_val.v.cmplx_val.imag,
  311. X                &brace) != 3) || (brace != RBRACE))
  312. X                    int_error("invalid complex constant",t_num);
  313. X            token[t_num].length += 2;
  314. X            while (expression[++current] != RBRACE) {
  315. X                token[t_num].length++;
  316. X                if (expression[current] == '\0')
  317. X                    int_error("no matching '}'", t_num);
  318. X            }
  319. X        } else if (expression[current] == '\'' || expression[current] == '\"') {
  320. X            token[t_num].length++;
  321. X            quote = expression[current];
  322. X            while (expression[++current] != quote) {
  323. X                if (expression[current] == '\0')
  324. X                    int_error("unmatched quote",t_num);
  325. X                token[t_num].length++;
  326. X            }
  327. X        } else switch (expression[current]) {
  328. X            case '#':        /* DFK: add comments to gnutex */
  329. X              comment_pos = current; /* remember position */
  330. X                 goto endline;    /* ignore the rest of the line */
  331. X            case '^':
  332. X            case '+':
  333. X            case '-':
  334. X            case '/':
  335. X            case '%':
  336. X            case '~':
  337. X            case '(':
  338. X            case ')':
  339. X            case '[':
  340. X            case ']':
  341. X            case ';':
  342. X            case ':':
  343. X            case '?':
  344. X            case ',':
  345. X                break;
  346. X            case '&':
  347. X            case '|':
  348. X            case '=':
  349. X            case '*':
  350. X                if (expression[current] ==
  351. X                    expression[current + 1])
  352. X                    APPEND_TOKEN;
  353. X                break;
  354. X            case '!':
  355. X            case '<':
  356. X            case '>':
  357. X                if (expression[current + 1] == '=')
  358. X                    APPEND_TOKEN;
  359. X                break;
  360. X            default:
  361. X                int_error("invalid character",t_num);
  362. X            }
  363. X        ++t_num;    /* next token if not white space */
  364. X    }
  365. X
  366. Xendline:                    /* comments jump here to ignore line */
  367. X
  368. X/* Now kludge an extra token which points to '\0' at end of expression[].
  369. X   This is useful so printerror() looks nice even if we've fallen off the
  370. X   line. */
  371. X
  372. X        token[t_num].start_index = current;
  373. X        token[t_num].length = 0;
  374. X    return(t_num);
  375. X}
  376. X
  377. X
  378. Xget_num(str)
  379. Xchar str[];
  380. X{
  381. Xdouble atof();
  382. Xregister int count = 0;
  383. Xlong atol();
  384. Xregister long lval;
  385. X
  386. X    token[t_num].is_token = FALSE;
  387. X    token[t_num].l_val.type = INT;        /* assume unless . or E found */
  388. X    while (isdigit(str[count]))
  389. X        count++;
  390. X    if (str[count] == '.') {
  391. X        token[t_num].l_val.type = CMPLX;
  392. X        while (isdigit(str[++count]))    /* swallow up digits until non-digit */
  393. X            ;
  394. X        /* now str[count] is other than a digit */
  395. X    }
  396. X    if (str[count] == 'e' || str[count] == 'E') {
  397. X        token[t_num].l_val.type = CMPLX;
  398. X        if (str[++count] == '-')
  399. X            count++;
  400. X        if (!isdigit(str[count])) {
  401. X            token[t_num].start_index += count;
  402. X            int_error("expecting exponent",t_num);
  403. X        }
  404. X        while (isdigit(str[++count]))
  405. X            ;
  406. X    }
  407. X    if (token[t_num].l_val.type == INT) {
  408. X         lval = atol(str);
  409. X        if ((token[t_num].l_val.v.int_val = lval) != lval)
  410. X            int_error("integer overflow; change to floating point",t_num);
  411. X    } else {
  412. X        token[t_num].l_val.v.cmplx_val.imag = 0.0;
  413. X        token[t_num].l_val.v.cmplx_val.real = atof(str);
  414. X    }
  415. X    return(count);
  416. X}
  417. X
  418. X
  419. X#ifdef MSDOS
  420. X
  421. Xsubstitute()
  422. X{
  423. X    int_error("substitution not supported by MS-DOS!",t_num);
  424. X}
  425. X
  426. X#else /* MSDOS */
  427. X
  428. Xsubstitute(str,max)            /* substitute output from ` ` */
  429. Xchar *str;
  430. Xint max;
  431. X{
  432. Xregister char *last;
  433. Xregister int i,c;
  434. Xregister FILE *f;
  435. XFILE *popen();
  436. Xstatic char pgm[MAX_LINE_LEN],output[MAX_LINE_LEN];
  437. X
  438. X#ifdef vms
  439. Xint chan;
  440. Xstatic $DESCRIPTOR(pgmdsc,pgm);
  441. Xstatic $DESCRIPTOR(lognamedsc,MAILBOX);
  442. X#endif /* vms */
  443. X
  444. X    i = 0;
  445. X    last = str;
  446. X    while (*(++last) != '`') {
  447. X        if (*last == '\0')
  448. X            int_error("unmatched `",t_num);
  449. X        pgm[i++] = *last;
  450. X    }
  451. X    pgm[i] = '\0';        /* end with null */
  452. X    max -= strlen(last);    /* max is now the max length of output sub. */
  453. X  
  454. X#ifdef vms
  455. X      pgmdsc.dsc$w_length = i;
  456. X       if (!((vaxc$errno = sys$crembx(0,&chan,0,0,0,0,&lognamedsc)) & 1))
  457. X           os_error("sys$crembx failed",NO_CARET);
  458. X   
  459. X       if (!((vaxc$errno = lib$spawn(&pgmdsc,0,&lognamedsc,&1)) & 1))
  460. X           os_error("lib$spawn failed",NO_CARET);
  461. X   
  462. X       if ((f = fopen(MAILBOX,"r")) == NULL)
  463. X           os_error("mailbox open failed",NO_CARET);
  464. X#else /* vms */
  465. X      if ((f = popen(pgm,"r")) == NULL)
  466. X          os_error("popen failed",NO_CARET);
  467. X#endif /* vms */
  468. X
  469. X    i = 0;
  470. X    while ((c = getc(f)) != EOF) {
  471. X        output[i++] = ((c == '\n') ? ' ' : c);    /* newlines become blanks*/
  472. X        if (i == max) {
  473. X            (void) pclose(f);
  474. X            int_error("substitution overflow", t_num);
  475. X        }
  476. X    }
  477. X    (void) pclose(f);
  478. X    if (i + strlen(last) > max)
  479. X        int_error("substitution overflowed rest of line", t_num);
  480. X    (void) strcpy(output+i,last+1);        /* tack on rest of line to output */
  481. X    (void) strcpy(str,output);                /* now replace ` ` with output */
  482. X}
  483. X#endif /* MS-DOS */
  484. *-*-END-of-translate/scanner.c-*-*
  485. echo x - translate/standard.c
  486. sed 's/^X//' >translate/standard.c <<'*-*-END-of-translate/standard.c-*-*'
  487. X/*
  488. X *
  489. X *    G N U P L O T  --  header.c
  490. X *
  491. X *  Copyright (C) 1986 Thomas Williams, Colin Kelley
  492. X *
  493. X *  You may use this code as you wish if credit is given and this message
  494. X *  is retained.
  495. X *
  496. X *  Please e-mail any useful additions to vu-vlsi!plot so they may be
  497. X *  included in later releases.
  498. X *
  499. X *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
  500. X */
  501. X
  502. X#include <math.h>
  503. X#include <stdio.h>
  504. X#include "plot.h"
  505. X
  506. Xextern BOOLEAN undefined;
  507. X
  508. X#ifdef vms
  509. X#include <errno.h>
  510. X#else
  511. Xextern int errno;
  512. X#endif /* vms */
  513. X
  514. X
  515. Xextern struct value stack[STACK_DEPTH];
  516. Xextern int s_p;
  517. X
  518. Xstruct value *pop(), *complex(), *integer();
  519. X
  520. Xdouble magnitude(), angle(), real(), imag();
  521. X
  522. X
  523. Xf_real()
  524. X{
  525. Xstruct value a;
  526. X    push( complex(&a,real(pop(&a)), 0.0) );
  527. X}
  528. X
  529. Xf_imag()
  530. X{
  531. Xstruct value a;
  532. X    push( complex(&a,imag(pop(&a)), 0.0) );
  533. X}
  534. X
  535. Xf_arg()
  536. X{
  537. Xstruct value a;
  538. X    push( complex(&a,angle(pop(&a)), 0.0) );
  539. X}
  540. X
  541. Xf_conjg()
  542. X{
  543. Xstruct value a;
  544. X    (void) pop(&a);
  545. X    push( complex(&a,real(&a),-imag(&a) ));
  546. X}
  547. X
  548. Xf_sin()
  549. X{
  550. Xstruct value a;
  551. X    (void) pop(&a);
  552. X    push( complex(&a,sin(real(&a))*cosh(imag(&a)), cos(real(&a))*sinh(imag(&a))) );
  553. X}
  554. X
  555. Xf_cos()
  556. X{
  557. Xstruct value a;
  558. X    (void) pop(&a);
  559. X    push( complex(&a,cos(real(&a))*cosh(imag(&a)), -sin(real(&a))*sinh(imag(&a))));
  560. X}
  561. X
  562. Xf_tan()
  563. X{
  564. Xstruct value a;
  565. Xregister double den;
  566. X    (void) pop(&a);
  567. X    den = cos(2*real(&a))+cosh(2*imag(&a));
  568. X    push( complex(&a,sin(2*real(&a))/den, sinh(2*imag(&a))/den) );
  569. X}
  570. X
  571. Xf_asin()
  572. X{
  573. Xstruct value a;
  574. Xregister double alpha, beta, x, y;
  575. X    (void) pop(&a);
  576. X    x = real(&a); y = imag(&a);
  577. X    if (y == 0.0) {
  578. X        if (fabs(x) > 1.0) {
  579. X            undefined = TRUE;
  580. X            push(complex(&a,0.0, 0.0));
  581. X        } else
  582. X            push( complex(&a,asin(x),0.0) );
  583. X    } else {
  584. X        beta  = sqrt((x + 1)*(x + 1) + y*y)/2 - sqrt((x - 1)*(x - 1) + y*y)/2;
  585. X        alpha = sqrt((x + 1)*(x + 1) + y*y)/2 + sqrt((x - 1)*(x - 1) + y*y)/2;
  586. X        push( complex(&a,asin(beta), log(alpha + sqrt(alpha*alpha-1))) );
  587. X    }
  588. X}
  589. X
  590. Xf_acos()
  591. X{
  592. Xstruct value a;
  593. Xregister double alpha, beta, x, y;
  594. X    (void) pop(&a);
  595. X    x = real(&a); y = imag(&a);
  596. X    if (y == 0.0) {
  597. X        if (fabs(x) > 1.0) {
  598. X            undefined = TRUE;
  599. X            push(complex(&a,0.0, 0.0));
  600. X        } else
  601. X            push( complex(&a,acos(x),0.0) );
  602. X    } else {
  603. X        alpha = sqrt((x + 1)*(x + 1) + y*y)/2 + sqrt((x - 1)*(x - 1) + y*y)/2;
  604. X        beta  = sqrt((x + 1)*(x + 1) + y*y)/2 - sqrt((x - 1)*(x - 1) + y*y)/2;
  605. X        push( complex(&a,acos(beta), log(alpha + sqrt(alpha*alpha-1))) );
  606. X    }
  607. X}
  608. X
  609. Xf_atan()
  610. X{
  611. Xstruct value a;
  612. Xregister double x, y;
  613. X    (void) pop(&a);
  614. X    x = real(&a); y = imag(&a);
  615. X    if (y == 0.0)
  616. X        push( complex(&a,atan(x), 0.0) );
  617. X    else if (x == 0.0 && fabs(y) == 1.0) {
  618. X        undefined = TRUE;
  619. X        push(complex(&a,0.0, 0.0));
  620. X    } else
  621. X        push( complex(&a,atan(2*x/(1-x*x-y*y)),
  622. X                log((x*x+(y+1)*(y+1))/(x*x+(y-1)*(y-1)))/4) );
  623. X}
  624. X
  625. Xf_sinh()
  626. X{
  627. Xstruct value a;
  628. X    (void) pop(&a);
  629. X    push( complex(&a,sinh(real(&a))*cos(imag(&a)), cosh(real(&a))*sin(imag(&a))) );
  630. X}
  631. X
  632. Xf_cosh()
  633. X{
  634. Xstruct value a;
  635. X    (void) pop(&a);
  636. X    push( complex(&a,cosh(real(&a))*cos(imag(&a)), sinh(real(&a))*sin(imag(&a))) );
  637. X}
  638. X
  639. Xf_tanh()
  640. X{
  641. Xstruct value a;
  642. Xregister double den;
  643. X    (void) pop(&a);
  644. X    den = cosh(2*real(&a)) + cos(2*imag(&a));
  645. X    push( complex(&a,sinh(2*real(&a))/den, sin(2*imag(&a))/den) );
  646. X}
  647. X
  648. Xf_int()
  649. X{
  650. Xstruct value a;
  651. X    push( integer(&a,(int)real(pop(&a))) );
  652. X}
  653. X
  654. X
  655. Xf_abs()
  656. X{
  657. Xstruct value a;
  658. X    (void) pop(&a);
  659. X    switch (a.type) {
  660. X        case INT:
  661. X            push( integer(&a,abs(a.v.int_val)) );            
  662. X            break;
  663. X        case CMPLX:
  664. X            push( complex(&a,magnitude(&a), 0.0) );
  665. X    }
  666. X}
  667. X
  668. Xf_sgn()
  669. X{
  670. Xstruct value a;
  671. X    (void) pop(&a);
  672. X    switch(a.type) {
  673. X        case INT:
  674. X            push( integer(&a,(a.v.int_val > 0) ? 1 : 
  675. X                    (a.v.int_val < 0) ? -1 : 0) );
  676. X            break;
  677. X        case CMPLX:
  678. X            push( integer(&a,(a.v.cmplx_val.real > 0.0) ? 1 : 
  679. X                    (a.v.cmplx_val.real < 0.0) ? -1 : 0) );
  680. X            break;
  681. X    }
  682. X}
  683. X
  684. X
  685. Xf_sqrt()
  686. X{
  687. Xstruct value a;
  688. X    double mag, ang;
  689. X    (void) pop(&a);
  690. X    mag = sqrt(magnitude(&a));
  691. X    if ( (ang = angle(&a)) < 0.0)
  692. X        ang += 2*Pi;
  693. X    ang /= 2;
  694. X    push( complex(&a,mag*cos(ang), mag*sin(ang)) );
  695. X}
  696. X
  697. X
  698. Xf_exp()
  699. X{
  700. Xregister double mag, ang;
  701. Xstruct value a;
  702. X    (void) pop(&a);
  703. X    mag = exp(real(&a));
  704. X    ang = imag(&a);
  705. X    push( complex(&a,mag*cos(ang), mag*sin(ang)) );
  706. X}
  707. X
  708. X
  709. Xf_log10()
  710. X{
  711. Xstruct value a;
  712. Xregister double l10;;
  713. X    (void) pop(&a);
  714. X    l10 = log(10.0);    /***** replace with a constant! ******/
  715. X    push( complex(&a,log(magnitude(&a))/l10, angle(&a)/l10) );
  716. X}
  717. X
  718. X
  719. Xf_log()
  720. X{
  721. Xstruct value a;
  722. X    (void) pop(&a);
  723. X    push( complex(&a,log(magnitude(&a)), angle(&a)) );
  724. X}
  725. X
  726. Xf_besj0()    /* j0(a) = sin(a)/a */
  727. X{
  728. Xstruct value a;
  729. X    a = top_of_stack;
  730. X    f_sin();
  731. X    push(&a);
  732. X    f_div();
  733. X}
  734. X
  735. X
  736. Xf_besj1()    /* j1(a) = sin(a)/(a**2) - cos(a)/a */
  737. X{
  738. Xstruct value a;
  739. X    a = top_of_stack;
  740. X    f_sin();
  741. X    push(&a);
  742. X    push(&a);
  743. X    f_mult();
  744. X    f_div();
  745. X    push(&a);
  746. X    f_cos();
  747. X    push(&a);
  748. X    f_div();
  749. X    f_minus();
  750. X}
  751. X
  752. X
  753. Xf_besy0()    /* y0(a) = -cos(a)/a */
  754. X{
  755. Xstruct value a;
  756. X    a = top_of_stack;
  757. X    f_cos();
  758. X    push(&a);
  759. X    f_div();
  760. X    f_uminus();
  761. X}
  762. X
  763. X
  764. Xf_besy1()    /* y1(a) = -cos(a)/(a**2) - sin(a)/a */
  765. X{
  766. Xstruct value a;
  767. X
  768. X    a = top_of_stack;
  769. X    f_cos();
  770. X    push(&a);
  771. X    push(&a);
  772. X    f_mult();
  773. X    f_div();
  774. X    push(&a);
  775. X    f_sin();
  776. X    push(&a);
  777. X    f_div();
  778. X    f_plus();
  779. X    f_uminus();
  780. X}
  781. X
  782. X
  783. Xf_floor()
  784. X{
  785. Xstruct value a;
  786. X
  787. X    (void) pop(&a);
  788. X    switch (a.type) {
  789. X        case INT:
  790. X            push( integer(&a,(int)floor((double)a.v.int_val)));            
  791. X            break;
  792. X        case CMPLX:
  793. X            push( complex(&a,floor(a.v.cmplx_val.real),
  794. X                floor(a.v.cmplx_val.imag)) );
  795. X    }
  796. X}
  797. X
  798. X
  799. X
  800. Xf_ceil()
  801. X{
  802. Xstruct value a;
  803. X
  804. X    (void) pop(&a);
  805. X    switch (a.type) {
  806. X        case INT:
  807. X            push( integer(&a,(int)ceil((double)a.v.int_val)));            
  808. X            break;
  809. X        case CMPLX:
  810. X            push( complex(&a,ceil(a.v.cmplx_val.real), ceil(a.v.cmplx_val.imag)) );
  811. X    }
  812. X}
  813. *-*-END-of-translate/standard.c-*-*
  814. echo x - translate/test1
  815. sed 's/^X//' >translate/test1 <<'*-*-END-of-translate/test1-*-*'
  816. Xset terminal latex
  817. Xset output "plot.tex" # a short comment here
  818. Xset size 4,2.75; help foo; set term latex
  819. Xset title "Effect of Prefetching Lead on Total execution time"
  820. X!echo this is a shell command
  821. Xset ylabel "Total\\Execution\\time\\(seconds)" 1
  822. Xset xlabel "Minimum prefetching lead in blocks"
  823. X# full-line comment goes here
  824. Xset style lp1 "\scriptsize 1" 7 "\circle*{1}"
  825. Xset style lp2 "\scriptsize 2" 7 "\circle*{1}"
  826. Xset style lp3 "\scriptsize 3" 7 "\circle*{1}"
  827. Xset style lp4 "\scriptsize 4" 7 "\circle*{1}"
  828. Xset noclip
  829. Xplot [0:90] [0:10] "points.gps" w lp1, "points.gw" w lp2, \
  830. X  "points.lps" w lp3, "points.lw" w lp4
  831. Xlabel 10,7 "gfp"
  832. Xlabel 80,5.5 "gw"
  833. Xlabel 70,3.4 "lfp"
  834. Xlabel 40,1.8 "lw"
  835. Xplot [0:pi] sin(x) w points
  836. Xkey 1,.5 "sin(x)" w points, "" w lines, "dummy" w lp1
  837. *-*-END-of-translate/test1-*-*
  838. echo x - translate/test2
  839. sed 's/^X//' >translate/test2 <<'*-*-END-of-translate/test2-*-*'
  840. Xset terminal latex
  841. Xset output "plot.tex" # a short comment here
  842. Xset size 4,2.75; help foo; set term latex
  843. Xset title "Effect of Prefetching
  844. Xset ylabel "Total\\Execution\\time\\(seconds)" 1
  845. Xset xlabel "Minimum prefetching lead in blocks"
  846. X# full-line comment goes here
  847. Xset style lp1 "\scriptsize 1" 7 "\circle*{1}"
  848. Xset style lp2 "\scriptsize 2" 7 "\circle*{1}"
  849. Xset style lp3 "\scriptsize 3" 7 "\circle*{1}"
  850. Xset style lp4 "\scriptsize 4" 7 
  851. Xset noclip
  852. Xplot [0:90] [0:10] "points.gps" w lp1, "points.gw" w lp2, \
  853. X  "points.lps" w lp3, "points.lw" w lp4,
  854. Xlabel 10,7 "gfp"
  855. Xlabel 80,5.5 "gw"
  856. Xlabel ,3.4 "lfp"
  857. Xlabel 40,1.8 "lw"
  858. Xplot [0:pi] sin(x) w points
  859. Xkey 1,.5 "sin(x)" w points, "" w lines, "dummy" w lp1
  860. *-*-END-of-translate/test2-*-*
  861. echo x - translate/util.c
  862. sed 's/^X//' >translate/util.c <<'*-*-END-of-translate/util.c-*-*'
  863. X/*
  864. X *
  865. X *    G N U P L O T  --  util.c
  866. X *
  867. X *  Copyright (C) 1986 Thomas Williams, Colin Kelley
  868. X *
  869. X *  You may use this code as you wish if credit is given and this message
  870. X *  is retained.
  871. X *
  872. X *  Please e-mail any useful additions to vu-vlsi!plot so they may be
  873. X *  included in later releases.
  874. X *
  875. X *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
  876. X */
  877. X
  878. X#include <ctype.h>
  879. X#include <setjmp.h>
  880. X#include <stdio.h>
  881. X#include <errno.h>
  882. X#include "plot.h"
  883. X
  884. X#ifndef vms
  885. Xextern int errno, sys_nerr;
  886. Xextern char *sys_errlist[];
  887. X#endif /* vms */
  888. X
  889. Xextern int inline;            /* line number of input */
  890. Xextern char input_line[MAX_LINE_LEN];
  891. Xextern struct lexical_unit token[MAX_TOKENS];
  892. Xextern jmp_buf env;    /* from plot.c */
  893. X
  894. X/*
  895. X * equals() compares string value of token number t_num with str[], and
  896. X *   returns TRUE if they are identical.
  897. X */
  898. Xequals(t_num, str)
  899. Xint t_num;
  900. Xchar *str;
  901. X{
  902. Xregister int i;
  903. X
  904. X    if (!token[t_num].is_token)
  905. X        return(FALSE);                /* must be a value--can't be equal */
  906. X    for (i = 0; i < token[t_num].length; i++) {
  907. X        if (input_line[token[t_num].start_index+i] != str[i])
  908. X            return(FALSE);
  909. X        }
  910. X    /* now return TRUE if at end of str[], FALSE if not */
  911. X    return(str[i] == '\0');
  912. X}
  913. X
  914. X
  915. X
  916. X/*
  917. X * almost_equals() compares string value of token number t_num with str[], and
  918. X *   returns TRUE if they are identical up to the first $ in str[].
  919. X */
  920. Xalmost_equals(t_num, str)
  921. Xint t_num;
  922. Xchar *str;
  923. X{
  924. Xregister int i;
  925. Xregister int after = 0;
  926. Xregister start = token[t_num].start_index;
  927. Xregister length = token[t_num].length;
  928. X
  929. X    if (!token[t_num].is_token)
  930. X        return(FALSE);                /* must be a value--can't be equal */
  931. X    for (i = 0; i < length + after; i++) {
  932. X        if (str[i] != input_line[start + i]) {
  933. X            if (str[i] != '$')
  934. X                return(FALSE);
  935. X            else {
  936. X                after = 1;
  937. X                start--;    /* back up token ptr */
  938. X                }
  939. X            }
  940. X        }
  941. X
  942. X    /* i now beyond end of token string */
  943. X
  944. X    return(after || str[i] == '$' || str[i] == '\0');
  945. X}
  946. X
  947. X
  948. X
  949. Xisstring(t_num)
  950. Xint t_num;
  951. X{
  952. X    
  953. X    return(token[t_num].is_token &&
  954. X           (input_line[token[t_num].start_index] == '\'' ||
  955. X           input_line[token[t_num].start_index] == '\"'));
  956. X}
  957. X
  958. X
  959. Xisnumber(t_num)
  960. Xint t_num;
  961. X{
  962. X    return(!token[t_num].is_token);
  963. X}
  964. X
  965. X
  966. Xisletter(t_num)
  967. Xint t_num;
  968. X{
  969. X    return(token[t_num].is_token &&
  970. X            (isalpha(input_line[token[t_num].start_index])));
  971. X}
  972. X
  973. X
  974. X/*
  975. X * is_definition() returns TRUE if the next tokens are of the form
  976. X *   identifier =
  977. X *        -or-
  978. X *   identifier ( identifer ) =
  979. X */
  980. Xis_definition(t_num)
  981. Xint t_num;
  982. X{
  983. X    return (isletter(t_num) &&
  984. X            (equals(t_num+1,"=") ||            /* variable */
  985. X            (equals(t_num+1,"(") &&        /* function */
  986. X             isletter(t_num+2)   &&
  987. X             equals(t_num+3,")") &&
  988. X             equals(t_num+4,"=") )
  989. X        ));
  990. X}
  991. X
  992. X
  993. X
  994. X/*
  995. X * copy_str() copies the string in token number t_num into str, appending
  996. X *   a null.  No more than MAX_ID_LEN chars are copied.
  997. X */
  998. Xcopy_str(str, t_num)
  999. Xchar str[];
  1000. Xint t_num;
  1001. X{
  1002. Xregister int i = 0;
  1003. Xregister int start = token[t_num].start_index;
  1004. Xregister int count;
  1005. X
  1006. X    if ((count = token[t_num].length) > MAX_ID_LEN)
  1007. X        count = MAX_ID_LEN;
  1008. X    do {
  1009. X        str[i++] = input_line[start++];
  1010. X        } while (i != count);
  1011. X    str[i] = '\0';
  1012. X}
  1013. X
  1014. X
  1015. X/*
  1016. X * quote_str() does the same thing as copy_str, except it ignores the
  1017. X *   quotes at both ends.  This seems redundant, but is done for 
  1018. X *   efficency.
  1019. X */
  1020. Xquote_str(str, t_num)
  1021. Xchar str[];
  1022. Xint t_num;
  1023. X{
  1024. Xregister int i = 0;
  1025. Xregister int start = token[t_num].start_index + 1;
  1026. Xregister int count;
  1027. X
  1028. X    if ((count = token[t_num].length - 2) > MAX_ID_LEN)
  1029. X        count = MAX_ID_LEN;
  1030. X    while (i != count) {
  1031. X        str[i++] = input_line[start++];
  1032. X     }
  1033. X    str[i] = '\0';
  1034. X}
  1035. X
  1036. X/*
  1037. X *    capture() returns in str[] the the part of input_line[] which lies
  1038. X *    between the begining of token[start] and end of token[end]
  1039. X */
  1040. Xcapture(str,start,end)
  1041. Xchar str[];
  1042. Xint start,end;
  1043. X{
  1044. Xregister int i,j;
  1045. Xchar *s = str;
  1046. X
  1047. X    j = token[end].start_index + token[end].length;
  1048. X    for (i = token[start].start_index; i < j && input_line[i] != '\0'; i++)
  1049. X        *s++ = input_line[i];
  1050. X    *s = '\0';
  1051. X}
  1052. X
  1053. X
  1054. Xconvert(val_ptr, t_num)
  1055. Xstruct value *val_ptr;
  1056. Xint t_num;
  1057. X{
  1058. X    *val_ptr = token[t_num].l_val;
  1059. X}
  1060. X
  1061. X
  1062. X
  1063. Xshow_value(fp,val)
  1064. XFILE *fp;
  1065. Xstruct value *val;
  1066. X{
  1067. X        switch(val->type) {
  1068. X            case INT:
  1069. X                fprintf(fp,"%d",val->v.int_val);
  1070. X                break;
  1071. X            case CMPLX:
  1072. X                if (val->v.cmplx_val.imag != 0.0 )
  1073. X                    fprintf(fp,"{%g, %g}",
  1074. X                        val->v.cmplx_val.real,val->v.cmplx_val.imag);
  1075. X                else
  1076. X                    fprintf(fp,"%g", val->v.cmplx_val.real);
  1077. X                break;
  1078. X            default:
  1079. X                int_error("unknown type in show_value()",NO_CARET);
  1080. X        }
  1081. X}
  1082. X
  1083. X
  1084. Xdouble
  1085. Xreal(val)        /* returns the real part of val */
  1086. Xstruct value *val;
  1087. X{
  1088. X    switch(val->type) {
  1089. X        case INT:
  1090. X            return((double) val->v.int_val);
  1091. X            break;
  1092. X        case CMPLX:
  1093. X            return(val->v.cmplx_val.real);
  1094. X    }
  1095. X    int_error("unknown type in real()",NO_CARET);
  1096. X    /* NOTREACHED */
  1097. X}
  1098. X
  1099. X
  1100. Xdouble
  1101. Ximag(val)        /* returns the imag part of val */
  1102. Xstruct value *val;
  1103. X{
  1104. X    switch(val->type) {
  1105. X        case INT:
  1106. X            return(0.0);
  1107. X            break;
  1108. X        case CMPLX:
  1109. X            return(val->v.cmplx_val.imag);
  1110. X    }
  1111. X    int_error("unknown type in real()",NO_CARET);
  1112. X    /* NOTREACHED */
  1113. X}
  1114. X
  1115. X
  1116. X
  1117. Xdouble
  1118. Xmagnitude(val)        /* returns the magnitude of val */
  1119. Xstruct value *val;
  1120. X{
  1121. X    double sqrt();
  1122. X
  1123. X    switch(val->type) {
  1124. X        case INT:
  1125. X            return((double) abs(val->v.int_val));
  1126. X            break;
  1127. X        case CMPLX:
  1128. X            return(sqrt(val->v.cmplx_val.real*
  1129. X                    val->v.cmplx_val.real +
  1130. X                    val->v.cmplx_val.imag*
  1131. X                    val->v.cmplx_val.imag));
  1132. X    }
  1133. X    int_error("unknown type in magnitude()",NO_CARET);
  1134. X    /* NOTREACHED */
  1135. X}
  1136. X
  1137. X
  1138. X
  1139. Xdouble
  1140. Xangle(val)        /* returns the angle of val */
  1141. Xstruct value *val;
  1142. X{
  1143. X    double atan2();
  1144. X
  1145. X    switch(val->type) {
  1146. X        case INT:
  1147. X            return((val->v.int_val > 0) ? 0.0 : Pi);
  1148. X            break;
  1149. X        case CMPLX:
  1150. X            if (val->v.cmplx_val.imag == 0.0) {
  1151. X                if (val->v.cmplx_val.real >= 0.0)
  1152. X                    return(0.0);
  1153. X                else
  1154. X                    return(Pi);
  1155. X            }
  1156. X            return(atan2(val->v.cmplx_val.imag,
  1157. X                     val->v.cmplx_val.real));
  1158. X    }
  1159. X    int_error("unknown type in angle()",NO_CARET);
  1160. X    /* NOTREACHED */
  1161. X}
  1162. X
  1163. X
  1164. Xstruct value *
  1165. Xcomplex(a,realpart,imagpart)
  1166. Xstruct value *a;
  1167. Xdouble realpart, imagpart;
  1168. X{
  1169. X    a->type = CMPLX;
  1170. X    a->v.cmplx_val.real = realpart;
  1171. X    a->v.cmplx_val.imag = imagpart;
  1172. X    return(a);
  1173. X}
  1174. X
  1175. X
  1176. Xstruct value *
  1177. Xinteger(a,i)
  1178. Xstruct value *a;
  1179. Xint i;
  1180. X{
  1181. X    a->type = INT;
  1182. X    a->v.int_val = i;
  1183. X    return(a);
  1184. X}
  1185. X
  1186. X/* Lower-case the given string (DFK) */
  1187. X/* Done in place. */
  1188. Xvoid
  1189. Xlower_case(s)
  1190. X     char *s;
  1191. X{
  1192. X  register char *p = s;
  1193. X
  1194. X  while (*p != '\0') {
  1195. X    if (*p >= 'A' && *p <= 'Z')
  1196. X      *p = *p - 'A' + 'a';
  1197. X    p++;
  1198. X  }
  1199. X}
  1200. X
  1201. X
  1202. Xint space_count(line, t_num)
  1203. X    int line;
  1204. X    int t_num;
  1205. X{
  1206. X    char string[20];
  1207. X
  1208. X    sprintf(string, "---%d: ", line);
  1209. X    return(strlen(string) + token[t_num].start_index);
  1210. X}
  1211. X
  1212. Xshow_line(always)
  1213. X    BOOLEAN always;
  1214. X{
  1215. X    static int last_line_printed = 0;    /* number of line printed out last. */
  1216. X
  1217. X    if (always || inline != last_line_printed) {
  1218. X       /* print line if not printed yet */
  1219. X       fprintf(stderr,"\n---%d: %s\n", inline, input_line);
  1220. X       last_line_printed = inline;
  1221. X    }
  1222. X}
  1223. X
  1224. Xos_error(str,t_num)
  1225. Xchar str[];
  1226. Xint t_num;
  1227. X{
  1228. X#ifdef vms
  1229. Xstatic status[2] = {1, 0};        /* 1 is count of error msgs */
  1230. X#endif
  1231. X
  1232. Xregister int i;
  1233. Xint count;
  1234. X
  1235. X    show_line(TRUE);
  1236. X
  1237. X    if (t_num != NO_CARET) {        /* put caret under error */
  1238. X        count = space_count(inline, t_num);
  1239. X        for (i = 0; i < count; i++) {
  1240. X            (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  1241. X            }
  1242. X        (void) putc('^',stderr);
  1243. X        (void) putc('\n',stderr);
  1244. X    }
  1245. X
  1246. X    fprintf(stderr,"###%d: %s\n",str);
  1247. X
  1248. X#ifdef vms
  1249. X    status[1] = vaxc$errno;
  1250. X    sys$putmsg(status);
  1251. X    (void) putc('\n',stderr);
  1252. X#else
  1253. X    if (errno >= sys_nerr)
  1254. X        fprintf(stderr, "unknown errno %d\n\n", errno);
  1255. X    else
  1256. X        fprintf(stderr,"(%s)\n",sys_errlist[errno]);
  1257. X#endif
  1258. X
  1259. X    longjmp(env, TRUE);    /* bail out to command line */
  1260. X}
  1261. X
  1262. X/* fatal error for this line; no return */
  1263. Xint_error(str,t_num)
  1264. Xchar str[];
  1265. Xint t_num;
  1266. X{
  1267. X    register int i;
  1268. X    int count;
  1269. X
  1270. X    show_line(TRUE);
  1271. X
  1272. X    if (t_num != NO_CARET) {    /* put caret under error */
  1273. X       count = space_count(inline, t_num);
  1274. X       for (i = 0; i < count; i++) {
  1275. X          (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  1276. X       }
  1277. X       (void) putc('^',stderr);
  1278. X       (void) putc('\n',stderr);
  1279. X    }
  1280. X
  1281. X    fprintf(stderr,"###%d: %s\n", inline, str);
  1282. X
  1283. X    longjmp(env, TRUE);        /* bail out to command line */
  1284. X}
  1285. X
  1286. X/* print an error for this line and return */
  1287. Xerr_msg(str)
  1288. X    char str[];
  1289. X{
  1290. X    show_line(FALSE);
  1291. X    fprintf(stderr,"***%d: %s\n", inline, str);
  1292. X}
  1293. X
  1294. X
  1295. X/* find char c in string str; return p such that str[p]==c;
  1296. X * if c not in str then p=strlen(str)
  1297. X */
  1298. Xint
  1299. Xinstring(str, c)
  1300. X    char *str;
  1301. X    char c;
  1302. X{
  1303. X    int pos = 0;
  1304. X
  1305. X    while (str != NULL && *str != '\0' && c != *str) {
  1306. X       str++; 
  1307. X       pos++;
  1308. X    }
  1309. X    return (pos);
  1310. X}
  1311. X
  1312. *-*-END-of-translate/util.c-*-*
  1313. exit
  1314.  
  1315.  
  1316.