cipple-0.2.1.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*
  2. * cipple the c kipple interpreter
  3. * version 0.2.1
  4. * by Jannis Harder (jix)
  5. *
  6. * Usage: cipple [program]
  7. * if program is omitted, cipple reads from stdin.
  8. *
  9. * compile using: gcc -O3 cipple.c -o cipple
  10. * optional flags:
  11. * -DNOINLINE disable inlineing
  12. * -DINCR <int value> sets memory increment for stacks
  13. * -DDECR <int value> sets memory decrement for stacks (should be a multiply of INCR)
  14. * -DSTARTS <int value> sets initial stack size (should be less than DECR and a multiply of INCR)
  15. * -DINSPECT enables instruction dumping (generating kipple code form the internal representation)
  16. */
  17. /*
  18. * Copyright (c) 2005 Jannis Harder
  19. *
  20. * Permission is hereby granted, free of charge, to any person obtaining a copy
  21. * of this software and associated documentation files (the "Software"), to deal
  22. * in the Software without restriction, including without limitation the rights
  23. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  24. * copies of the Software, and to permit persons to whom the Software is
  25. * furnished to do so, subject to the following conditions:
  26. *
  27. * The above copyright notice and this permission notice shall be included in
  28. * all copies or substantial portions of the Software.
  29. *
  30. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  31. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  32. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  33. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  34. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  35. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  36. * SOFTWARE.
  37. */
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <string.h>
  41. #ifndef INCR
  42. #define INCR 262144
  43. #endif
  44. #ifndef DECR
  45. #define DECR (INCR*4)
  46. #endif
  47. #ifndef STARTS
  48. #define STARTS (INCR*2)
  49. #endif
  50. #ifdef NOINLINE
  51. #define ILINE /*ignore*/
  52. #else
  53. #define ILINE inline
  54. #endif
  55. enum {
  56. PuNone = 0,
  57. PuItoa
  58. };
  59. enum {
  60. PoNone = 0,
  61. };
  62. typedef struct {
  63. int *data;
  64. int usize;
  65. int msize;
  66. int puspecial;
  67. /*int pospecial;
  68. int clrspecial;*/
  69. } stack;
  70. ILINE void push(stack *cstack,int value) {
  71. char temp[13];
  72. int ccount, i;
  73. if(cstack->puspecial) {
  74. ccount = sprintf(temp,"%i",value);
  75. if(cstack->usize+ccount+1 > cstack->msize){
  76. cstack->msize+=INCR;
  77. cstack->data = realloc(cstack->data, cstack->msize*sizeof(int));
  78. }
  79. for(i=0;i<ccount;i++)
  80. cstack->data[++(cstack->usize)]=temp[i];
  81. }
  82. else {
  83. if(cstack->usize+1 == cstack->msize){
  84. cstack->msize+=INCR;
  85. cstack->data = realloc(cstack->data, cstack->msize*sizeof(int));
  86. }
  87. cstack->data[++(cstack->usize)]=value;
  88. }
  89. }
  90. ILINE int pop(stack *cstack) {
  91. int rv;
  92. /*switch(cstack->pospecial) {
  93. case 0:*/
  94. if(cstack->usize == 0)
  95. return 0;
  96. rv = cstack->data[cstack->usize--];
  97. if(cstack->usize < cstack->msize-DECR){
  98. cstack->msize-=DECR;
  99. cstack->data = realloc(cstack->data, cstack->msize*sizeof(int));
  100. }
  101. /* break;
  102. }*/
  103. return rv;
  104. }
  105. ILINE void clear(stack *cstack) {
  106. /*if(!cstack->clrspecial){*/
  107. /*free(cstack->data);
  108. cstack->data = malloc(STARTS*sizeof(int));*/
  109. cstack->usize = 0;
  110. /*cstack->msize = STARTS;*/
  111. /*}*/
  112. }
  113. ILINE void init(stack *cstack) {
  114. cstack->data = malloc(STARTS*sizeof(int)+1);
  115. cstack->usize = 0;
  116. cstack->msize = STARTS;
  117. cstack->puspecial = 0;
  118. /*cstack->pospecial = 0;
  119. cstack->clrspecial = 0;*/
  120. }
  121. ILINE void freestack(stack *cstack) {
  122. free(cstack->data);
  123. free(cstack);
  124. }
  125. ILINE int empty(stack *cstack) {
  126. return cstack->usize == 0;
  127. }
  128. ILINE int last(stack *cstack) {
  129. return cstack->data[cstack->usize];
  130. }
  131. enum {
  132. Inoop = 0,
  133. Ipush,
  134. Imove,
  135. Iaddv,
  136. Iadds,
  137. Isubv,
  138. Isubs,
  139. Izclr,
  140. Iloop,
  141. };
  142. typedef struct s_ins {
  143. int instruction;
  144. union {
  145. stack* s;
  146. int i;
  147. } op_a;
  148. union {
  149. stack* s;
  150. int i;
  151. struct s_ins *p;
  152. } op_b;
  153. struct s_ins *next;
  154. } instruction;
  155. void freeprog (instruction *program) {
  156. instruction *cins = program;
  157. instruction *tins;
  158. while(cins){
  159. if(cins->instruction == Iloop)
  160. freeprog(cins->op_b.p);
  161. tins = cins;
  162. cins = cins->next;
  163. free(tins);
  164. }
  165. }
  166. void run (instruction *program) {
  167. instruction *cins = program;
  168. while(cins) {
  169. switch(cins->instruction){
  170. case Inoop:
  171. break;
  172. case Ipush:
  173. push(cins->op_a.s,cins->op_b.i);
  174. break;
  175. case Imove:
  176. push(cins->op_a.s,pop(cins->op_b.s));
  177. break;
  178. case Iaddv:
  179. push(cins->op_a.s,last(cins->op_a.s)+cins->op_b.i);
  180. break;
  181. case Iadds:
  182. push(cins->op_a.s,last(cins->op_a.s)+pop(cins->op_b.s));
  183. break;
  184. case Isubv:
  185. push(cins->op_a.s,last(cins->op_a.s)-cins->op_b.i);
  186. break;
  187. case Isubs:
  188. push(cins->op_a.s,last(cins->op_a.s)-pop(cins->op_b.s));
  189. break;
  190. case Izclr:
  191. if(!last(cins->op_a.s))
  192. clear(cins->op_a.s);
  193. break;
  194. case Iloop:
  195. while(!empty(cins->op_a.s))
  196. run(cins->op_b.p);
  197. break;
  198. }
  199. cins = cins->next;
  200. }
  201. }
  202. #define UCASE(X) (((X)>96)?((X)-32):(X))
  203. #define CRANGE(X) ((X)>63 && (X)<91)
  204. #define NRANGE(X) ((X)>47 && (X)<58)
  205. #define MALLOCI nins = malloc(sizeof(instruction)); \
  206. nins->next = NULL;\
  207. if(!first) first = nins; \
  208. if(current) current->next = nins; \
  209. current = nins;
  210. instruction * iparse(stack *stacks,int length, char *ldata) {
  211. instruction *first = NULL;
  212. instruction *current = NULL;
  213. instruction *nins = NULL;
  214. int isstring = 0;
  215. char *lchr = ldata;
  216. char *mchr = ldata+length;
  217. int i1,i2,i3,i4;
  218. /* search for instructions */
  219. isstring = 0;
  220. for(lchr=ldata;lchr<mchr;lchr++) {
  221. if((*lchr) == '"'){
  222. isstring = !isstring;
  223. }
  224. else if(!isstring){
  225. switch(*lchr){
  226. case '+':
  227. if(lchr==ldata || lchr==mchr-1) break;
  228. i1 = UCASE(*(lchr-1));
  229. i2 = UCASE(*(lchr+1));
  230. if(!(CRANGE(i1) && (CRANGE(i2) || NRANGE(i2))))
  231. break;
  232. MALLOCI;
  233. current->op_a.s = &stacks[i1-'@'];
  234. if(CRANGE(i2)){
  235. current->instruction = Iadds;
  236. current->op_b.s = &stacks[i2-'@'];
  237. }
  238. else {
  239. current->instruction = Iaddv;
  240. current->op_b.i = 0;
  241. for(i3=1;lchr+i3<mchr && NRANGE(lchr[i3]);i3++){
  242. current->op_b.i*=10;
  243. current->op_b.i+=lchr[i3]-'0';
  244. }
  245. }
  246. break;
  247. case '-':
  248. if(lchr==ldata || lchr==mchr-1) break;
  249. i1 = UCASE(*(lchr-1));
  250. i2 = UCASE(*(lchr+1));
  251. if(!(CRANGE(i1) && (CRANGE(i2) || NRANGE(i2))))
  252. break;
  253. MALLOCI;
  254. current->op_a.s = &stacks[i1-'@'];
  255. if(CRANGE(i2)){
  256. current->instruction = Isubs;
  257. current->op_b.s = &stacks[i2-'@'];
  258. }
  259. else {
  260. current->instruction = Isubv;
  261. current->op_b.i = 0;
  262. for(i3=1;lchr+i3<mchr && NRANGE(lchr[i3]);i3++){
  263. current->op_b.i*=10;
  264. current->op_b.i+=lchr[i3]-'0';
  265. }
  266. }
  267. break;
  268. case '?':
  269. if(lchr==ldata) break;
  270. i1 = UCASE(*(lchr-1));
  271. if(!CRANGE(i1))
  272. break;
  273. MALLOCI;
  274. current->instruction = Izclr;
  275. current->op_a.s = &stacks[i1-'@'];
  276. break;
  277. case '<':
  278. if(lchr==ldata || lchr==mchr-1) break;
  279. i1 = UCASE(*(lchr-1));
  280. i2 = UCASE(*(lchr+1));
  281. if(!CRANGE(i1))
  282. break;
  283. if(CRANGE(i2)){
  284. MALLOCI;
  285. current->instruction = Imove;
  286. current->op_a.s = &stacks[i1-'@'];
  287. current->op_b.s = &stacks[i2-'@'];
  288. }
  289. else if(NRANGE(i2)){
  290. MALLOCI;
  291. current->instruction = Ipush;
  292. current->op_a.s = &stacks[i1-'@'];
  293. current->op_b.i = 0;
  294. for(i3=1;lchr+i3<mchr && NRANGE(lchr[i3]);i3++){
  295. current->op_b.i*=10;
  296. current->op_b.i+=lchr[i3]-'0';
  297. }
  298. }
  299. else if(i2=='"'){
  300. for(i3=2;lchr+i3<mchr && (lchr[i3]!='"');i3++){
  301. MALLOCI;
  302. current->instruction = Ipush;
  303. current->op_a.s = &stacks[i1-'@'];
  304. current->op_b.i = lchr[i3];
  305. }
  306. }
  307. break;
  308. case '>':
  309. if(lchr==ldata || lchr==mchr-1) break;
  310. i1 = UCASE(*(lchr-1));
  311. i2 = UCASE(*(lchr+1));
  312. if(!CRANGE(i2))
  313. break;
  314. if(CRANGE(i1)){
  315. MALLOCI;
  316. current->instruction = Imove;
  317. current->op_a.s = &stacks[i2-'@'];
  318. current->op_b.s = &stacks[i1-'@'];
  319. }
  320. else if(NRANGE(i1)){
  321. MALLOCI;
  322. current->instruction = Ipush;
  323. current->op_a.s = &stacks[i2-'@'];
  324. current->op_b.i = 0;
  325. i4=1;
  326. for(i3=-1;lchr+i3>=ldata && NRANGE(lchr[i3]);i3--){
  327. current->op_b.i+= i4 * (lchr[i3]-'0');
  328. i4*=10;
  329. }
  330. }
  331. else if(i1=='"'){
  332. for(i3=-2;lchr+i3>=ldata && (lchr[i3]!='"');i3--){
  333. MALLOCI;
  334. current->instruction = Ipush;
  335. current->op_a.s = &stacks[i2-'@'];
  336. current->op_b.i = lchr[i3];
  337. }
  338. }
  339. break;
  340. case '(':
  341. if(lchr==mchr-1) break;
  342. i1 = UCASE(*(lchr+1));
  343. if(!CRANGE(i1))
  344. break;
  345. i3=0;
  346. i4=1;
  347. for(i2=1;lchr+i2<mchr && i4 > 0;i2++){
  348. if(lchr[i2]=='"')
  349. i3=!i3;
  350. if(!i3){
  351. if(lchr[i2]=='(')
  352. i4++;
  353. else if(lchr[i2]==')')
  354. i4--;
  355. }
  356. }
  357. MALLOCI;
  358. current->instruction = Iloop;
  359. current->op_a.s = &stacks[i1-'@'];
  360. current->op_b.p = iparse(stacks,i2-1,lchr+1);
  361. lchr+=i2-1;
  362. break;
  363. }
  364. }
  365. }
  366. return first;
  367. }
  368. instruction * parse(stack *stacks,int length, char *data) {
  369. char *ldata = malloc(length);
  370. instruction *rv;
  371. char *lchr = ldata;
  372. char *mchr = ldata+length;
  373. int isstring = 0;
  374. int comment = 0;
  375. memcpy(ldata,data,length);
  376. /* clear comments */
  377. for(;lchr<mchr;lchr++) {
  378. if(isstring && *lchr == '"')
  379. isstring = 0;
  380. else if((!comment) && *lchr == '"')
  381. isstring = 1;
  382. else if(comment && *lchr == '\n')
  383. comment = 0;
  384. else if((!isstring) && *lchr == '#')
  385. comment = 1;
  386. if(comment)
  387. *lchr = ' ';
  388. }
  389. rv = iparse(stacks,length,ldata);
  390. free(ldata);
  391. return rv;
  392. }
  393. #ifdef INSPECT
  394. void dumpprog(int depth,stack *stacks,instruction *program) {
  395. char *e;
  396. instruction *cins = program;
  397. e = malloc(depth+1);
  398. memset(e,':',depth);
  399. e[depth]=0;
  400. while(cins){
  401. switch(cins->instruction){
  402. case Inoop:
  403. fprintf(stderr,"%s noop\n",e);
  404. break;
  405. case Ipush:
  406. fprintf(stderr,"%s push %c<%i\n",e,'@'+cins->op_a.s-stacks,cins->op_b.i);
  407. break;
  408. case Imove:
  409. fprintf(stderr,"%s move %c<%c\n",e,'@'+cins->op_a.s-stacks,'@'+cins->op_b.s-stacks);
  410. break;
  411. case Iaddv:
  412. fprintf(stderr,"%s addv %c+%i\n",e,'@'+cins->op_a.s-stacks,cins->op_b.i);
  413. break;
  414. case Iadds:
  415. fprintf(stderr,"%s adds %c+%c\n",e,'@'+cins->op_a.s-stacks,'@'+cins->op_b.s-stacks);
  416. break;
  417. case Isubv:
  418. fprintf(stderr,"%s subv %c-%i\n",e,'@'+cins->op_a.s-stacks,cins->op_b.i);
  419. break;
  420. case Isubs:
  421. fprintf(stderr,"%s subs %c-%c\n",e,'@'+cins->op_a.s-stacks,'@'+cins->op_b.s-stacks);
  422. break;
  423. case Izclr:
  424. fprintf(stderr,"%s zclr %c?\n",e,'@'+cins->op_a.s-stacks);
  425. break;
  426. case Iloop:
  427. fprintf(stderr,"%s loop (%c\n",e,'@'+cins->op_a.s-stacks);
  428. dumpprog(depth+2,stacks,cins->op_b.p);
  429. fprintf(stderr,"%s )\n",e);
  430. break;
  431. }
  432. cins = cins->next;
  433. }
  434. }
  435. #endif
  436. void runstring(int length,char *program) {
  437. stack stacks[27];
  438. int i;
  439. int t;
  440. instruction *bc;
  441. for(i=0;i<27;i++)
  442. init(&stacks[i]);
  443. stacks[0].puspecial = PuItoa;
  444. bc = parse(stacks,length,program);
  445. #ifdef INSPECT
  446. dumpprog(1,stacks,bc);
  447. #endif
  448. while((t = getchar()) && !feof(stdin)){
  449. push(&stacks[9],t);
  450. }
  451. run(bc);
  452. freeprog(bc);
  453. while(!empty(&stacks[15])){
  454. putchar(pop(&stacks[15]));
  455. }
  456. fflush(stdout);
  457. for(i=0;i<27;i++)
  458. free(stacks[i].data);
  459. }
  460. /*void runcstring(char *program) {
  461. runstring(strlen(program),program);
  462. }*/
  463. int main (int argc, const char * argv[]) {
  464. char *program;
  465. int size = 0;
  466. FILE *infile;
  467. if(argc<2)
  468. infile = stdin;
  469. else
  470. infile= fopen(argv[1],"r");
  471. if(!infile)
  472. return 1;
  473. program = malloc(200);
  474. while(!feof(infile)){
  475. program = realloc(program,size+200);
  476. size+=fread(program+size,1,200,infile);
  477. }
  478. if(argc<2){
  479. clearerr(stdin);
  480. rewind(stdin);
  481. }
  482. runstring(size,program);
  483. return 0;
  484. }