/e.c

https://github.com/casey/e · C · 297 lines · 210 code · 73 blank · 14 comment · 80 complexity · 55957ee2d71897a8f2bf4331323757e1 MD5 · raw file

  1. #include <stdlib.h>
  2. #include <math.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. int argc, arg;
  6. char **argv, *p, c;
  7. typedef double type;
  8. void next()
  9. {
  10. do
  11. {
  12. if(arg != argc && !*p) p = argv[++arg];
  13. if(arg != argc) c = *p++; else c = 0;
  14. }
  15. while(c == ' ');
  16. }
  17. void syntax()
  18. {
  19. int tc, c = -1, g = 1;
  20. char *t = argv[g];
  21. while(1)
  22. {
  23. if(t == p) tc = c;
  24. c++;
  25. if(g != argc && !*t) t = argv[++g];
  26. if(g != argc) putchar(*t++); else break;
  27. }
  28. putchar('\n');
  29. if(tc>16)
  30. {
  31. for(c=0;c<tc-16;c++) putchar(' ');
  32. printf("syntax error ---^\n");
  33. }
  34. else
  35. {
  36. for(c=0;c<tc;c++) putchar(' ');
  37. printf("^--- syntax error\n");
  38. }
  39. exit(1);
  40. }
  41. void unknown(char *s)
  42. {
  43. printf("'%s': unknown function\n",s);
  44. exit(1);
  45. }
  46. type E();
  47. type term();
  48. type constant()
  49. {
  50. type r = 0;
  51. while(c >= '0' && c <= '9')
  52. { r = 10*r + (c-'0'); next(); }
  53. if(c == '.')
  54. {
  55. type p = 0.1;
  56. next();
  57. while(c >= '0' && c <= '9')
  58. { r += p * (c-'0'); p /= 10; next(); }
  59. }
  60. if(c == 'e' || c == 'E')
  61. {
  62. type m = 1;
  63. next();
  64. if(c == '-') { m = -m; next(); } else if(c == '+') next();
  65. r *= pow(10,m*term());
  66. }
  67. return r;
  68. }
  69. type function()
  70. {
  71. char f[20], *p;
  72. type v;
  73. p = f;
  74. while(p-f < 19 && c >= 'a' && c <= 'z') { *p++ = c; next(); }
  75. *p = 0;
  76. if(!strcmp(f,"pi")) return M_PI;
  77. if(!strcmp(f,"e" )) return M_E;
  78. v = term();
  79. #define mathfunc(a,b) if(!strcmp(f,a)) return b;
  80. mathfunc("abs" , fabs(v));
  81. mathfunc("fabs" , fabs(v));
  82. mathfunc("floor" , floor(v));
  83. mathfunc("ceil" , ceil(v));
  84. mathfunc("sqrt" , sqrt(v));
  85. mathfunc("exp" , exp(v));
  86. mathfunc("sin" , sin(v));
  87. mathfunc("cos" , cos(v));
  88. mathfunc("tan" , tan(v));
  89. mathfunc("asin" , asin(v));
  90. mathfunc("acos" , acos(v));
  91. mathfunc("atan" , atan(v));
  92. mathfunc("sinh" , sinh(v));
  93. mathfunc("cosh" , cosh(v));
  94. mathfunc("tanh" , tanh(v));
  95. mathfunc("asinh" , asinh(v));
  96. mathfunc("acosh" , acosh(v));
  97. mathfunc("atanh" , atanh(v));
  98. mathfunc("ln" , log(v));
  99. mathfunc("log" , log(v)/log(2));
  100. unknown(f);
  101. return 0;
  102. }
  103. type term()
  104. {
  105. /*type m = 1;*/
  106. const int m = 1;
  107. /*
  108. if(c == '-') { m = -m; next(); }
  109. else
  110. if(c == '+') next();
  111. */
  112. if(c=='(' || c=='[')
  113. {
  114. type r;
  115. next();
  116. r = E();
  117. if(c != ')' && c !=']') syntax();
  118. next();
  119. return m * r;
  120. }
  121. else if((c >= '0' && c <= '9') || c == '.')
  122. return m * constant();
  123. else if(c >= 'a' && c <= 'z')
  124. return m * function();
  125. /* exit to silence warnings */
  126. exit(1);
  127. }
  128. static inline
  129. type factorial(type v)
  130. {
  131. type i, r = 1;
  132. for(i=2;i<=v;i++) r *= i;
  133. return r;
  134. }
  135. type H()
  136. {
  137. type r = term();
  138. if(c == '!') { next(); r = factorial(r); }
  139. return r;
  140. }
  141. type G()
  142. {
  143. type q, r = H();
  144. while(c == '^')
  145. { next(); q = G(); r = pow(r,q); }
  146. return r;
  147. }
  148. type F()
  149. {
  150. type r = G();
  151. while(1)
  152. {
  153. if(c=='*') { next(); r *= G(); }
  154. else
  155. if(c=='/') { next(); r /= G(); }
  156. else
  157. if(c=='%') { next(); r = fmod(r,G()); }
  158. else break;
  159. }
  160. return r;
  161. }
  162. type E()
  163. {
  164. type r = F();
  165. while(1)
  166. {
  167. if(c=='+') { next(); r += F(); }
  168. else
  169. if(c=='-') { next(); r -= F(); }
  170. else break;
  171. }
  172. return r;
  173. }
  174. type S()
  175. {
  176. type r = E();
  177. if(c != 0) syntax();
  178. return r;
  179. }
  180. void
  181. format(type X)
  182. {
  183. type i,f;
  184. int d;
  185. if(!isfinite(X)) { printf("%f", X); return ; }
  186. f = fabs(modf(X,&i));
  187. d = floor(log10(fabs(X)))+1;
  188. /* f is fractional part, i is integer part */
  189. /* printf("%.30f\n",(X)); */
  190. if(isfinite(f) && f!=0)
  191. {
  192. char *p, s[2000], t[2000];
  193. sprintf(t, "%%.%df", 15-d);
  194. sprintf(s,t,f);
  195. /*
  196. printf("(t=%s)",t);
  197. printf("(s=%s)",s);
  198. */
  199. /* remove all zeros from s */
  200. p = s;
  201. while(*p) p++; p--;
  202. while(p>s && *p=='0') *p-- = 0;
  203. if(s[0] == '1') /* decimal part has been rounded */
  204. printf("%.0f",i+(X>=0?1:-1));
  205. else
  206. {
  207. printf("%.0f",i);
  208. if(s[2] != 0) printf("%s",s+1);
  209. }
  210. }
  211. else
  212. printf("%.0f",i);
  213. }
  214. int main(int _argc, char **_argv)
  215. {
  216. argc = _argc;
  217. argv = _argv;
  218. arg = 1;
  219. p = argv[arg];
  220. next();
  221. format(S());
  222. printf("\n");
  223. return 0;
  224. }