psnuspc.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. """
  2. This program compiles SNUSP programs to C.
  3. Copyright (C) 2004 John Bauman
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. """
  16. import fileinput
  17. #preamble
  18. print """#include <stdio.h>
  19. #include <setjmp.h>
  20. #include <stdlib.h>
  21. #ifdef WIN32
  22. #define gtch() getche()
  23. #else
  24. #include <termios.h>
  25. #define gtch() getchar()
  26. #endif
  27. int main(int argc, char **argv) {
  28. int *pvals = malloc(30000 * sizeof(int));
  29. jmp_buf envs[1000];
  30. jmp_buf *penvs = envs;
  31. #ifndef WIN32
  32. struct termios old_tio, new_tio;
  33. /* get the terminal settings for stdin */
  34. tcgetattr(STDIN_FILENO,&old_tio);
  35. /* we want to keep the old setting to restore them at the end */
  36. new_tio=old_tio;
  37. /* disable canonical mode (buffered i/o) */
  38. new_tio.c_lflag &=(~ICANON);
  39. /* set the new settings immediately */
  40. tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);
  41. #endif
  42. goto progstart;
  43. """
  44. program = []
  45. hasstart = 0
  46. progwidth = 0
  47. for line in fileinput.input():
  48. n = [c for c in line]
  49. if line.find("$") >= 0:
  50. hasstart = 1
  51. program.append(n)
  52. if progwidth < len(n):
  53. progwidth = len(n)
  54. progheight = len(program)
  55. for line in range(len(program)): #pad the lines out
  56. program[line] += " " * (progwidth - len(program[line]))
  57. if not hasstart:
  58. print "progstart:"
  59. proglocs = {}
  60. jnum = 0
  61. for y, line in enumerate(program):
  62. for x, char in enumerate(line):
  63. if char == "\\" or char == "/":
  64. proglocs[(x,y)] = jnum
  65. jnum += 1
  66. jumpnum = 0
  67. callnum = 0
  68. skipnum = 0
  69. def outputrowdata(y, row, myname, left, right, realx, realy):
  70. """Print out the code for a "row" of data."""
  71. global skipnum, callnum, jumpnum
  72. amskipping = amcalling = amjumping = 0
  73. for x, char in enumerate(row):
  74. skipinturn = 0
  75. callinturn = 0
  76. jumpinturn = 0
  77. xypos = (realx(x,y), realy(x,y)) #find out the REAL position
  78. #check each character
  79. if myname == "right" and char == "$":
  80. print "progstart:"
  81. if char == "+":
  82. print "(*pvals)++;"
  83. if char == "-":
  84. print "(*pvals)--;"
  85. if char == ">":
  86. print "pvals++;"
  87. if char == "<":
  88. print "pvals--;"
  89. if char == ",":
  90. print "*pvals = gtch();"
  91. print "if (*pvals == 3) goto endprogram;"
  92. if char == ".":
  93. print "putchar(*pvals);"
  94. if char == "\\":
  95. print "goto %s_%i;" % (right, proglocs[xypos])
  96. print "%s_%i:" % (myname, proglocs[xypos])
  97. if char == "/":
  98. print "goto %s_%i;" % (left, proglocs[xypos])
  99. print "%s_%i:" % (myname, proglocs[xypos])
  100. if char == "?":
  101. print "if (*pvals == 0)"
  102. print "goto jump_%i;" % (jumpnum)
  103. jumpnum += 1
  104. jumpinturn = 1
  105. if char == "!":
  106. print "goto skip_%i;" % (skipnum)
  107. skipnum += 1
  108. skipinturn = 1
  109. if char == "@":
  110. print "if (penvs > envs + 999) {"
  111. print 'printf("Too many @ calls - Ran out of space.");'
  112. print "goto endprogram;"
  113. print "}"
  114. print "if (setjmp(*penvs)) {"
  115. print "goto call_%i;" % (callnum)
  116. print "} else {"
  117. print "penvs++;"
  118. print "}"
  119. callnum += 1
  120. callinturn = 1
  121. if char == "#":
  122. print "penvs--;"
  123. print "if (penvs < envs) "
  124. print "goto endprogram;"
  125. print "longjmp(*penvs, 1);"
  126. #jump-to points for the instructions that skip over others
  127. #these are annoyingly complicated, to account for the fact
  128. #that there might be two in a row
  129. if amjumping:
  130. print "jump_%i:" % (jumpnum - 1 - jumpinturn)
  131. amjumping -= 1
  132. if char == "?":
  133. amjumping += 1
  134. if amcalling:
  135. print "call_%i:" % (callnum - 1 - callinturn)
  136. amcalling -= 1
  137. if char == "@":
  138. amcalling += 1
  139. if amskipping:
  140. print "skip_%i:" % (skipnum - 1 - skipinturn)
  141. amskipping -= 1
  142. if char == "!":
  143. amskipping += 1
  144. #just make sure to clean up - no dangling references
  145. if amjumping:
  146. print "jump_%i:" % (jumpnum - 1)
  147. if amcalling:
  148. print "call_%i:" % (callnum - 1)
  149. if amskipping:
  150. print "skip_%i:" % (skipnum - 1)
  151. print "goto endprogram;"
  152. #these parts output the rows of code, forwards and backwards, up and down
  153. for y, row in enumerate(program):
  154. if "/" in row or "\\" in row or "$" in row or (y == 0 and not hasstart):
  155. outputrowdata(y, row, "right", "up", "down",
  156. lambda a,b:a,
  157. lambda a,b:b)
  158. for y, row in enumerate(program):
  159. row = row[:]
  160. row.reverse()
  161. if "/" in row or "\\" in row:
  162. outputrowdata(y, row, "left", "down", "up",
  163. lambda a,b:progwidth - a - 1,
  164. lambda a,b:b)
  165. for x, row in enumerate(zip(*program)):
  166. if "/" in row or "\\" in row:
  167. outputrowdata(x, row, "down", "left", "right",
  168. lambda a,b:b,
  169. lambda a,b:a)
  170. for x, row in enumerate(zip(*program)):
  171. row = list(row)
  172. row.reverse()
  173. if "/" in row or "\\" in row:
  174. outputrowdata(x, row, "up", "right", "left",
  175. lambda a,b:b,
  176. lambda a,b:progheight - a - 1)
  177. print """
  178. endprogram:
  179. #ifndef WIN32
  180. tcsetattr(STDIN_FILENO,TCSANOW,&old_tio);
  181. #endif
  182. return 0;
  183. }
  184. """