Advertisement
Guest User

Untitled

a guest
Jun 30th, 2011
930
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Batch 12.45 KB | None | 0 0
  1. @ECHO off
  2. setlocal ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
  3. rem Глобальные переменные
  4. rem Набор выводимых символов. Символы, вывод которых вызывал ошибки исполнения cmd заменены символом "."
  5. set char=".#$...'()*+,-./0123456789.....?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]._`abcdefghijklmnopqrstuvwxyz{.}~_"
  6. rem Размер maxmem можно поставить 30000 ячеек памяти, но тогда инициализация идет очень долго.
  7. set maxmem=100
  8.  
  9. echo Brainfuck Interpreter
  10. echo.
  11.  
  12. IF "%1" NEQ "" GOTO :init
  13. echo Usage: %~nx0 file.bf
  14. goto :eof
  15.  
  16. :init
  17. rem Инициализируем память.
  18. call :array create mem %maxmem% 0
  19. set mp=0
  20. set sp=0
  21. set cp=0
  22.  
  23. rem читаем программу в память
  24. set work_file=%1
  25. set bf_prog=
  26. FOR /F "eol=c delims=*" %%I IN (%work_file%) DO SET bf_prog=!bf_prog!%%I
  27. rem узнаем длину программы
  28. Echo.%bf_prog%>"%TEMP%\%~n0.tmp"
  29. For %%i In ("%TEMP%\%~n0.tmp") Do Set /A bf_len=%%~zi-2
  30. rem Выводим тест, что программа работает, а не зависла.
  31. echo Executing programm
  32. echo %bf_prog%
  33. echo.
  34.  
  35. rem рабочий цикл
  36. :work
  37. set cop=!bf_prog:~%cp%,1!
  38.  
  39. if "%cop%" == "+" (
  40.   call :array get mem %mp% tmp
  41.   set /a tmp += 1
  42.   if "!tmp!" == "256" set tmp=0
  43.   call :array set mem %mp% !tmp!
  44. ) else if "%cop%" == "-" (
  45.   call :array get mem %mp% tmp
  46.   set /a tmp -= 1
  47.   if !tmp! LSS 0 set tmp=255
  48.   call :array set mem %mp% !tmp!
  49. ) else if "%cop%" == ")" (
  50.   set /a mp +=1
  51.   if !mp! == %maxmem% set mp=0
  52. ) else if "%cop%" == "(" (
  53.   set /a mp -=1
  54.   if !mp! == -1 set /a mp=%maxmem% - 1
  55. ) else if "%cop%" == "," (
  56.   call :comma
  57. ) else if "%cop%" == "." (
  58.   call :array get mem %mp% tmp
  59.   call :Echochr !tmp!
  60. ) else if "%cop%" == "[" (
  61.   call :array get mem %mp% tmp
  62.   if "!tmp!" == "0" (
  63.     call :skip1
  64.   )
  65. ) else if "%cop%" == "]" (
  66.   call :array get mem %mp% tmp
  67.   if "!tmp!" NEQ "0" (
  68.     call :skip2
  69.   )
  70. )
  71.  
  72. set /a cp += 1
  73. if %cp% == %bf_len% goto :exit
  74. goto :work
  75.  
  76. :skip1
  77. :w11
  78.     set /a cp += 1
  79.     if %cp% == %bf_len% (
  80.       call :err_print "] not found"
  81.       goto :exit
  82.     )
  83.     set cop=!bf_prog:~%cp%,1!
  84.     if "%cop%" == "[" (set /a sp +=1)
  85.     if "%cop%" == "]" if %sp% NEQ 0 (set /a sp -=1) else (goto :w12)
  86.     goto :w11
  87. :w12
  88. exit /b 0
  89.  
  90. :skip2
  91. :w21
  92.     set /a cp -= 1
  93.     if "%cp%" LSS "0" (
  94.       call :err_print "[ not found"
  95.       goto :exit
  96.     )
  97.     set cop=!bf_prog:~%cp%,1!
  98.     if "%cop%" == "]" (set /a sp +=1)
  99.     if "%cop%" == "[" if %sp% NEQ 0 (set /a sp -=1) else (goto :w22)
  100.     goto :w21
  101. :w22
  102. exit /b 0
  103.  
  104. :comma
  105. rem Не реализованно
  106. exit /b 0
  107.  
  108. rem ==========================================================================
  109. rem Процедура echochr
  110. rem Эмуляция функции chr()
  111. rem ==========================================================================
  112. :echochr
  113. if %1==10 echo.
  114. if %1==13 echo.
  115. if %1==32 <nul set /p strTemp="_"
  116. if %1 GTR 32 (
  117. set /a code=%1 - 32
  118. for /f %%t in ('cmd /c "echo %%char:~!code!,1%%"') do <nul set /p strTemp="%%t"
  119. )
  120. exit /b 0
  121.  
  122.  
  123. rem ==========================================================================
  124. rem Процедура debug
  125. rem Печать состояния переменных и памяти
  126. rem ==========================================================================
  127. :debug
  128. call :array get mem %mp% tmp
  129. echo cp=%cp%, mp=%mp%, cop=%cop%, mem[mp]=%tmp%
  130. rem pause
  131. exit /b 0
  132. rem ==========================================================================
  133.  
  134.  
  135. rem ==========================================================================
  136. rem Процедура EchoWithoutCrLf
  137. rem %1 : текст для вывода.
  138. rem ==========================================================================
  139. :EchoWithoutCrLf
  140. <nul set /p strTemp="%~1"
  141. exit /b 0
  142. rem ==========================================================================
  143.  
  144.  
  145. rem ==========================================================================
  146. rem Процедура err_print
  147. rem Печать кода ошибки. Создание дампов работы.
  148. rem ==========================================================================
  149. :err_print
  150. echo Error on %cp% position.
  151. echo %1
  152. echo.
  153. echo cp: %cp% >register.dmp
  154. echo mp: %mp% >>register.dmp
  155. echo sp: %sp% >>register.dmp
  156. call :array save mem memory.dmp
  157. exit /b 0
  158. rem ==========================================================================
  159.  
  160.  
  161. rem =====  Arrays =====
  162. rem Важно помнить, что после каждого вызова функции удаляются все переменные, начинающиеся на __
  163. :array
  164.     rem Сохранение аргументов в локальных переменных
  165.     rem чтобы можно было обращать отложенным методом !__1!
  166.     rem ~ - убрать кавычки
  167.     set __1=%~1
  168.     set __2=%~2
  169.     set __3=%~3
  170.     set __4=%~4
  171.     set __5=%~5
  172.     set __6=%~6
  173.  
  174.    
  175.     rem == create ==
  176.     rem Создание массива
  177.     rem call :array create имя_массива [размер=0] [начальные значения=0]
  178.     if /I "!__1!"=="create" (
  179.  
  180.         rem Имя массива
  181.         if "!__2!"=="" (
  182.             echo Не указано имя массива
  183.             goto :eof
  184.         )
  185.         set _name=array_!__2!
  186.        
  187.         rem Размер
  188.         set /a _count=0
  189.         if not "!__3!"=="" (
  190.             set /a _count = !__3!
  191.         )
  192.        
  193.         rem Начальные значения
  194.         set _defval=0
  195.         if not "!__4!"=="" (
  196.             set _defval=!__4!
  197.         )
  198.        
  199.         rem Удаление массива, если существует c таким же именем
  200.         rem Можно было не удалять все переменные, а только оставшиеся после перезаписи, но может быть как-нибудь потом
  201.         call :array_del_ifdef !__2!
  202.        
  203.         set /a __maxindex=!_count!-1
  204.        
  205.         for /l %%i in (0,1,!__maxindex!) do set !_name!_%%i=!_defval!
  206.         set /a !_name!_count = !_count!
  207.        
  208.         set _name=
  209.         set _count=
  210.         set _defval=
  211.        
  212.     rem == get ==
  213.     rem Получение элемента массива (сохранение в переменную)
  214.     rem call :array get имя_массива [index=0] [имя_целевой_переменной=_l]
  215.     rem Если индекс отрицательный, то он считается с конца (-1 - последний, -2 - предпоследний и т.д.)
  216.     ) else if /I "!__1!"=="get" (
  217.  
  218.         rem Имя массива
  219.         if "!__2!"=="" (
  220.             echo Не указано имя массива
  221.             goto :eof
  222.         )
  223.         set __name=array_!__2!
  224.        
  225.         rem Проверка существования массива
  226.         call :array_notdefined !__2! __errors
  227.        
  228.         rem Если есть ошибки, то выходим
  229.         if not !__errors!==0 goto :eof
  230.        
  231.         rem Индекс элемента
  232.         set /a __i = 0
  233.         if not "!__3!"=="" (
  234.             set /a __i = !__3!
  235.         )
  236.  
  237.         rem Если индекс отрицательный, то считаем с конца
  238.         if !__i! LSS 0 (
  239.             rem Получаем размер
  240.             call :set __count !__name!_count
  241.             set /a __i=!__count!+!__i!
  242.         )
  243.        
  244.  
  245.         rem Имя переменной, содержащей значение элемента
  246.         set __target=!__name!_!__i!
  247.        
  248.         rem Проверка существования элемента
  249.         if not defined !__target! (
  250.             echo В массиве !__2! нет элемента с индексом !__i!
  251.             goto :eof
  252.         )
  253.        
  254.         rem Записываем значение элемента во временную переменную
  255.         call :set __value !__target!
  256.         set __var=_l
  257.         if not "!__4!"=="" (
  258.             set __var=!__4!
  259.         )
  260.        
  261.         rem Записываем в целевую
  262.         call :set !__var! __value
  263.    
  264.     rem == list ==
  265.     rem Вывод значений списком. Может быть полезно при перенаправлении вывода
  266.     rem call :array list имя_массива
  267.     rem Пример: call :array list myArr > array.txt  - сохраняет текущий массив в файт array.txt
  268.     rem Для сохранения в кодировке cp1251 используйте save
  269.     ) else if /I "!__1!"=="list" (
  270.        
  271.         rem Имя массива
  272.         if "!__2!"=="" (
  273.             echo Не указано имя массива
  274.             goto :eof
  275.         )
  276.        
  277.        
  278.         rem Проверка существования массива
  279.         call :array_notdefined !__2! __errors
  280.        
  281.         rem Если есть ошибки, то выходим
  282.         if not !__errors!==0 goto :eof
  283.        
  284.         set __name=array_!__2!
  285.        
  286.         rem Получаем размер
  287.         call :set __count !__name!_count
  288.         set /a __maxindex=!__count!-1
  289.        
  290.         rem Вывод значений
  291.         for /l %%i in (0,1,!__maxindex!) do (
  292.             call :set __value !__name!_%%i
  293.             echo !__value!
  294.         )
  295.    
  296.    
  297.    
  298.     rem == save ==
  299.     rem Сохраняет массив в указанный файл в кодировке cp1251
  300.     rem call :array save имя_массива имя_файла
  301.     ) else if /i "!__1!"=="save" (
  302.    
  303.         rem Имя файла
  304.         if "!__3!"=="" (
  305.             echo Не указано имя файла
  306.             goto :eof
  307.         )
  308.        
  309.         rem Парсим вывод команды chcp, ищим номер кодовой страницы и запаминаем
  310.         for /f "usebackq tokens=2 delims=:" %%i in (`chcp`) do set /a _pageset=%%i
  311.        
  312.         rem Меняем кодовую страницу на 1251
  313.         chcp 1251>nul
  314.         rem Перенаправляем вывод list в файл
  315.         call :array list !__2! > !__3!
  316.         rem Возвращаем кодовую страницу
  317.         chcp !_pageset!>nul
  318.        
  319.        
  320.         set _pageset=
  321.        
  322.        
  323.     rem == set ==
  324.     rem Присвоение значения элементу
  325.     rem call :array set имя_массива индекс значение
  326.     ) else if /I "!__1!"=="set" (
  327.        
  328.         if "!__4!"=="" (
  329.             echo Не указано значение. Значение не может быть пустым
  330.             goto :eof
  331.         )
  332.         rem Сохраняем параметры, для того, чтобы после вызова get они не потерялись
  333.         set _name=array_!__2!
  334.         set /a _i=!__3!
  335.         set _value=!__4!
  336.            
  337.         rem Получение значения обеспечивает нам проверку параметров
  338.         rem Важно. После операции все локальные переменные (__*) очищаются
  339.         call :array get !__2! !__3! _localresult
  340.        
  341.  
  342.         rem Если результат get существует, то удаляем элемент
  343.         rem Сообщения об ошибках в противном случае покажет сам get
  344.         if defined _localresult (
  345.             set !_name!_!_i!=!_value!
  346.         )
  347.        
  348.         set _localresult=
  349.         set _name=
  350.         set _i=
  351.         set _value=
  352.        
  353.     )
  354.     call :clear_local
  355.  
  356. goto :eof
  357.  
  358.  
  359.  
  360. rem Копирует значение одной переменной в другую
  361. rem Плюс в том, что имя переменной, значение которой извлекается, может быть составным
  362. rem call :set имя_целевой_переменной имя_переменной_содержищее_значение
  363. :set
  364.     set %~1=!%~2!
  365. goto :eof
  366.  
  367. rem Удаление локальных переменных (начинаются с __)
  368. :clear_local
  369.     rem Устанавливаю переменную __, чтобы set __ не возвращал "Переменная среды __ не определена"
  370.     set __=0
  371.     for /F "usebackq delims==" %%i in (`set __`) do set %%i=
  372. goto :eof
  373.  
  374.  
  375. :array_del_ifdef
  376.     call :array_notdefined %1 __array_del_ifdef_result H
  377.     if !__array_del_ifdef_result!==0 call :array delete %1
  378. goto :eof
  379.  
  380. rem Проверка существования массива
  381. :array_notdefined
  382.     rem Устанавливаем имя целевой переменной
  383.     set __var=_l
  384.    
  385.     rem Тихая проверка - не выводить сообщение
  386.     set __hide=0
  387.    
  388.     if not "%2"=="" (
  389.         set __var=%2
  390.     )
  391.    
  392.     if /i "%3"=="h" (
  393.         set __hide=1
  394.     )
  395.    
  396.     if not defined !__var! set /a !__var!=0
  397.    
  398.     rem Проверка существования переменной, содержащей размер
  399.     if not defined array_%~1_count (
  400.         if not !__hide!==1 echo Массив %~1 не определен
  401.         set /a !__var!+=1
  402.     )
  403.    
  404. goto :eof
  405.  
  406.  
  407. :exit
  408. rem сохраняем дамп памяти
  409. call :array save mem memory.dmp
  410. echo.
  411. pause
  412. ENDLOCAL
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement