mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 17:50:22 +00:00
Merge branch 'master' into 1100-local
Conflicts: lib/linguist/languages.yml
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
||||
Gemfile.lock
|
||||
.bundle/
|
||||
vendor/
|
||||
|
||||
@@ -2,11 +2,8 @@ before_install:
|
||||
- sudo apt-get install libicu-dev -y
|
||||
- gem update --system 2.1.11
|
||||
rvm:
|
||||
- 1.8.7
|
||||
- 1.9.2
|
||||
- 1.9.3
|
||||
- 2.0.0
|
||||
- 2.1.1
|
||||
- ree
|
||||
notifications:
|
||||
disabled: true
|
||||
|
||||
5
Gemfile
5
Gemfile
@@ -1,7 +1,2 @@
|
||||
source 'https://rubygems.org'
|
||||
gemspec
|
||||
|
||||
if RUBY_VERSION < "1.9.3"
|
||||
# escape_utils 1.0.0 requires 1.9.3 and above
|
||||
gem "escape_utils", "0.3.2"
|
||||
end
|
||||
|
||||
42
README.md
42
README.md
@@ -106,8 +106,50 @@ To update the `samples.json` after adding new files to [`samples/`](https://gith
|
||||
|
||||
bundle exec rake samples
|
||||
|
||||
### A note on language extensions
|
||||
|
||||
Linguist has a number of methods available to it for identifying the language of a particular file. The initial lookup is based upon the extension of the file, possible file extensions are defined in an array called `extensions`. Take a look at this example for example for `Perl`:
|
||||
|
||||
```
|
||||
Perl:
|
||||
type: programming
|
||||
ace_mode: perl
|
||||
color: "#0298c3"
|
||||
extensions:
|
||||
- .pl
|
||||
- .PL
|
||||
- .perl
|
||||
- .ph
|
||||
- .plx
|
||||
- .pm
|
||||
- .pod
|
||||
- .psgi
|
||||
interpreters:
|
||||
- perl
|
||||
```
|
||||
Any of the extensions defined are valid but the first in this array should be the most popular.
|
||||
|
||||
### Testing
|
||||
|
||||
Sometimes getting the tests running can be too much work, especially if you don't have much Ruby experience. It's okay: be lazy and let our build bot [Travis](http://travis-ci.org/#!/github/linguist) run the tests for you. Just open a pull request and the bot will start cranking away.
|
||||
|
||||
Here's our current build status, which is hopefully green: [](http://travis-ci.org/github/linguist)
|
||||
|
||||
### Releasing
|
||||
|
||||
If you are the current maintainer of this gem:
|
||||
|
||||
0. Create a branch for the release: `git checkout -b cut-release-vxx.xx.xx`
|
||||
0. Make sure your local dependencies are up to date: `bundle install`
|
||||
0. Ensure that samples are updated: `bundle exec rake samples`
|
||||
0. Ensure that tests are green: `bundle exec rake test`
|
||||
0. Bump gem version in `lib/linguist/version.rb`. For example, [like this](https://github.com/github/linguist/commit/8d2ea90a5ba3b2fe6e1508b7155aa4632eea2985).
|
||||
0. Make a PR to github/linguist. For example, [#1238](https://github.com/github/linguist/pull/1238).
|
||||
0. Build a local gem: `gem build github-linguist.gemspec`
|
||||
0. Testing:
|
||||
0. Bump the Gemfile and Gemfile.lock versions for an app which relies on this gem
|
||||
0. Install the new gem locally
|
||||
0. Test behavior locally, branch deploy, whatever needs to happen
|
||||
0. Merge github/linguist PR
|
||||
0. Tag and push: `git tag vx.xx.xx; git push --tags`
|
||||
0. Push to rubygems.org -- `gem push github-linguist-2.10.12.gem`
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
require File.expand_path('../lib/linguist/version', __FILE__)
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = 'github-linguist'
|
||||
s.version = '2.10.12'
|
||||
s.version = Linguist::VERSION
|
||||
s.summary = "GitHub Language detection"
|
||||
s.description = 'We use this library at GitHub to detect blob languages, highlight code, ignore binary files, suppress generated files in diffs, and generate language breakdown graphs.'
|
||||
|
||||
@@ -11,10 +13,10 @@ Gem::Specification.new do |s|
|
||||
s.files = Dir['lib/**/*']
|
||||
s.executables << 'linguist'
|
||||
|
||||
s.add_dependency 'charlock_holmes', '~> 0.6.6'
|
||||
s.add_dependency 'escape_utils', '>= 0.3.1'
|
||||
s.add_dependency 'charlock_holmes', '~> 0.7.3'
|
||||
s.add_dependency 'escape_utils', '~> 1.0.1'
|
||||
s.add_dependency 'mime-types', '~> 1.19'
|
||||
s.add_dependency 'pygments.rb', '~> 0.5.4'
|
||||
s.add_dependency 'pygments.rb', '~> 0.6.0'
|
||||
|
||||
s.add_development_dependency 'json'
|
||||
s.add_development_dependency 'mocha'
|
||||
|
||||
@@ -4,3 +4,4 @@ require 'linguist/heuristics'
|
||||
require 'linguist/language'
|
||||
require 'linguist/repository'
|
||||
require 'linguist/samples'
|
||||
require 'linguist/version'
|
||||
|
||||
@@ -112,6 +112,12 @@ module Linguist
|
||||
end
|
||||
end
|
||||
|
||||
def ruby_encoding
|
||||
if hash = detect_encoding
|
||||
hash[:ruby_encoding]
|
||||
end
|
||||
end
|
||||
|
||||
# Try to guess the encoding
|
||||
#
|
||||
# Returns: a Hash, with :encoding, :confidence, :type
|
||||
@@ -241,7 +247,31 @@ module Linguist
|
||||
def lines
|
||||
@lines ||=
|
||||
if viewable? && data
|
||||
data.split(/\r\n|\r|\n/, -1)
|
||||
# `data` is usually encoded as ASCII-8BIT even when the content has
|
||||
# been detected as a different encoding. However, we are not allowed
|
||||
# to change the encoding of `data` because we've made the implicit
|
||||
# guarantee that each entry in `lines` is encoded the same way as
|
||||
# `data`.
|
||||
#
|
||||
# Instead, we re-encode each possible newline sequence as the
|
||||
# detected encoding, then force them back to the encoding of `data`
|
||||
# (usually a binary encoding like ASCII-8BIT). This means that the
|
||||
# byte sequence will match how newlines are likely encoded in the
|
||||
# file, but we don't have to change the encoding of `data` as far as
|
||||
# Ruby is concerned. This allows us to correctly parse out each line
|
||||
# without changing the encoding of `data`, and
|
||||
# also--importantly--without having to duplicate many (potentially
|
||||
# large) strings.
|
||||
begin
|
||||
encoded_newlines = ["\r\n", "\r", "\n"].
|
||||
map { |nl| nl.encode(ruby_encoding, "ASCII-8BIT").force_encoding(data.encoding) }
|
||||
|
||||
data.split(Regexp.union(encoded_newlines), -1)
|
||||
rescue Encoding::ConverterNotFoundError
|
||||
# The data is not splittable in the detected encoding. Assume it's
|
||||
# one big line.
|
||||
[data]
|
||||
end
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
@@ -63,7 +63,8 @@ module Linguist
|
||||
generated_jni_header? ||
|
||||
composer_lock? ||
|
||||
node_modules? ||
|
||||
vcr_cassette?
|
||||
vcr_cassette? ||
|
||||
generated_by_zephir?
|
||||
end
|
||||
|
||||
# Internal: Is the blob an XCode project file?
|
||||
@@ -237,6 +238,13 @@ module Linguist
|
||||
!!name.match(/composer.lock/)
|
||||
end
|
||||
|
||||
# Internal: Is the blob a generated by Zephir
|
||||
#
|
||||
# Returns true or false.
|
||||
def generated_by_zephir?
|
||||
!!name.match(/.\.zep\.(?:c|h|php)$/)
|
||||
end
|
||||
|
||||
# Is the blob a VCR Cassette file?
|
||||
#
|
||||
# Returns true or false
|
||||
|
||||
@@ -24,7 +24,6 @@ module Linguist
|
||||
@extension_index = Hash.new { |h,k| h[k] = [] }
|
||||
@interpreter_index = Hash.new { |h,k| h[k] = [] }
|
||||
@filename_index = Hash.new { |h,k| h[k] = [] }
|
||||
@primary_extension_index = {}
|
||||
|
||||
# Valid Languages types
|
||||
TYPES = [:data, :markup, :programming, :prose]
|
||||
@@ -80,12 +79,6 @@ module Linguist
|
||||
@extension_index[extension] << language
|
||||
end
|
||||
|
||||
if @primary_extension_index.key?(language.primary_extension)
|
||||
raise ArgumentError, "Duplicate primary extension: #{language.primary_extension}"
|
||||
end
|
||||
|
||||
@primary_extension_index[language.primary_extension] = language
|
||||
|
||||
language.interpreters.each do |interpreter|
|
||||
@interpreter_index[interpreter] << language
|
||||
end
|
||||
@@ -191,8 +184,7 @@ module Linguist
|
||||
# Returns all matching Languages or [] if none were found.
|
||||
def self.find_by_filename(filename)
|
||||
basename, extname = File.basename(filename), File.extname(filename)
|
||||
langs = [@primary_extension_index[extname]] +
|
||||
@filename_index[basename] +
|
||||
langs = @filename_index[basename] +
|
||||
@extension_index[extname]
|
||||
langs.compact.uniq
|
||||
end
|
||||
@@ -299,15 +291,6 @@ module Linguist
|
||||
@interpreters = attributes[:interpreters] || []
|
||||
@filenames = attributes[:filenames] || []
|
||||
|
||||
unless @primary_extension = attributes[:primary_extension]
|
||||
raise ArgumentError, "#{@name} is missing primary extension"
|
||||
end
|
||||
|
||||
# Prepend primary extension unless its already included
|
||||
if primary_extension && !extensions.include?(primary_extension)
|
||||
@extensions = [primary_extension] + extensions
|
||||
end
|
||||
|
||||
# Set popular, and searchable flags
|
||||
@popular = attributes.key?(:popular) ? attributes[:popular] : false
|
||||
@searchable = attributes.key?(:searchable) ? attributes[:searchable] : true
|
||||
@@ -395,20 +378,6 @@ module Linguist
|
||||
# Returns the extensions Array
|
||||
attr_reader :extensions
|
||||
|
||||
# Deprecated: Get primary extension
|
||||
#
|
||||
# Defaults to the first extension but can be overridden
|
||||
# in the languages.yml.
|
||||
#
|
||||
# The primary extension can not be nil. Tests should verify this.
|
||||
#
|
||||
# This attribute is only used by app/helpers/gists_helper.rb for
|
||||
# creating the language dropdown. It really should be using `name`
|
||||
# instead. Would like to drop primary extension.
|
||||
#
|
||||
# Returns the extension String.
|
||||
attr_reader :primary_extension
|
||||
|
||||
# Public: Get interpreters
|
||||
#
|
||||
# Examples
|
||||
@@ -426,6 +395,27 @@ module Linguist
|
||||
#
|
||||
# Returns the extensions Array
|
||||
attr_reader :filenames
|
||||
|
||||
# Public: Return all possible extensions for language
|
||||
def all_extensions
|
||||
(extensions + [primary_extension]).uniq
|
||||
end
|
||||
|
||||
# Deprecated: Get primary extension
|
||||
#
|
||||
# Defaults to the first extension but can be overridden
|
||||
# in the languages.yml.
|
||||
#
|
||||
# The primary extension can not be nil. Tests should verify this.
|
||||
#
|
||||
# This method is only used by app/helpers/gists_helper.rb for creating
|
||||
# the language dropdown. It really should be using `name` instead.
|
||||
# Would like to drop primary extension.
|
||||
#
|
||||
# Returns the extension String.
|
||||
def primary_extension
|
||||
extensions.first
|
||||
end
|
||||
|
||||
# Public: Get URL escaped name.
|
||||
#
|
||||
@@ -568,9 +558,8 @@ module Linguist
|
||||
:group_name => options['group'],
|
||||
:searchable => options.key?('searchable') ? options['searchable'] : true,
|
||||
:search_term => options['search_term'],
|
||||
:extensions => options['extensions'].sort,
|
||||
:extensions => [options['extensions'].first] + options['extensions'][1..-1].sort,
|
||||
:interpreters => options['interpreters'].sort,
|
||||
:primary_extension => options['primary_extension'],
|
||||
:filenames => options['filenames'],
|
||||
:popular => popular.include?(name)
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -98,9 +98,16 @@
|
||||
# AngularJS
|
||||
- (^|/)angular([^.]*)(\.min)?\.js$
|
||||
|
||||
# D3.js
|
||||
- (^|\/)d3(\.v\d+)?([^.]*)(\.min)?\.js$
|
||||
|
||||
# React
|
||||
- (^|/)react(-[^.]*)?(\.min)?\.js$
|
||||
|
||||
# Modernizr
|
||||
- (^|/)modernizr\-\d\.\d+(\.\d+)?(\.min)?\.js$
|
||||
- (^|/)modernizr\.custom\.\d+\.js$
|
||||
|
||||
## Python ##
|
||||
|
||||
# django
|
||||
@@ -141,7 +148,7 @@
|
||||
- (^|/)[Mm]icrosoft([Mm]vc)?([Aa]jax|[Vv]alidation)(\.debug)?\.js$
|
||||
|
||||
# NuGet
|
||||
- ^[Pp]ackages/
|
||||
- ^[Pp]ackages\/.+\.\d+\/
|
||||
|
||||
# ExtJS
|
||||
- (^|/)extjs/.*?\.js$
|
||||
@@ -161,6 +168,9 @@
|
||||
- (^|/)extjs/src/
|
||||
- (^|/)extjs/welcome/
|
||||
|
||||
# Html5shiv
|
||||
- (^|/)html5shiv(\.min)?\.js$
|
||||
|
||||
# Samples folders
|
||||
- ^[Ss]amples/
|
||||
|
||||
@@ -189,3 +199,12 @@
|
||||
|
||||
# Mercury --use-subdirs
|
||||
- Mercury/
|
||||
|
||||
# R packages
|
||||
- ^vignettes/
|
||||
- ^inst/extdata/
|
||||
|
||||
# Octicons
|
||||
- octicons.css
|
||||
- octicons.min.css
|
||||
- sprockets-octicons.scss
|
||||
|
||||
3
lib/linguist/version.rb
Normal file
3
lib/linguist/version.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
module Linguist
|
||||
VERSION = "2.12.0"
|
||||
end
|
||||
2048
samples/Assembly/ASSEMBLE.inc
Normal file
2048
samples/Assembly/ASSEMBLE.inc
Normal file
File diff suppressed because it is too large
Load Diff
350
samples/Assembly/FASM.asm
Normal file
350
samples/Assembly/FASM.asm
Normal file
@@ -0,0 +1,350 @@
|
||||
|
||||
; flat assembler interface for Win32
|
||||
; Copyright (c) 1999-2014, Tomasz Grysztar.
|
||||
; All rights reserved.
|
||||
|
||||
format PE console
|
||||
|
||||
section '.text' code readable executable
|
||||
|
||||
start:
|
||||
|
||||
mov [con_handle],STD_OUTPUT_HANDLE
|
||||
mov esi,_logo
|
||||
call display_string
|
||||
|
||||
call get_params
|
||||
jc information
|
||||
|
||||
call init_memory
|
||||
|
||||
mov esi,_memory_prefix
|
||||
call display_string
|
||||
mov eax,[memory_end]
|
||||
sub eax,[memory_start]
|
||||
add eax,[additional_memory_end]
|
||||
sub eax,[additional_memory]
|
||||
shr eax,10
|
||||
call display_number
|
||||
mov esi,_memory_suffix
|
||||
call display_string
|
||||
|
||||
call [GetTickCount]
|
||||
mov [start_time],eax
|
||||
|
||||
call preprocessor
|
||||
call parser
|
||||
call assembler
|
||||
call formatter
|
||||
|
||||
call display_user_messages
|
||||
movzx eax,[current_pass]
|
||||
inc eax
|
||||
call display_number
|
||||
mov esi,_passes_suffix
|
||||
call display_string
|
||||
call [GetTickCount]
|
||||
sub eax,[start_time]
|
||||
xor edx,edx
|
||||
mov ebx,100
|
||||
div ebx
|
||||
or eax,eax
|
||||
jz display_bytes_count
|
||||
xor edx,edx
|
||||
mov ebx,10
|
||||
div ebx
|
||||
push edx
|
||||
call display_number
|
||||
mov dl,'.'
|
||||
call display_character
|
||||
pop eax
|
||||
call display_number
|
||||
mov esi,_seconds_suffix
|
||||
call display_string
|
||||
display_bytes_count:
|
||||
mov eax,[written_size]
|
||||
call display_number
|
||||
mov esi,_bytes_suffix
|
||||
call display_string
|
||||
xor al,al
|
||||
jmp exit_program
|
||||
|
||||
information:
|
||||
mov esi,_usage
|
||||
call display_string
|
||||
mov al,1
|
||||
jmp exit_program
|
||||
|
||||
get_params:
|
||||
mov [input_file],0
|
||||
mov [output_file],0
|
||||
mov [symbols_file],0
|
||||
mov [memory_setting],0
|
||||
mov [passes_limit],100
|
||||
call [GetCommandLine]
|
||||
mov esi,eax
|
||||
mov edi,params
|
||||
find_command_start:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je find_command_start
|
||||
cmp al,22h
|
||||
je skip_quoted_name
|
||||
skip_name:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je find_param
|
||||
or al,al
|
||||
jz all_params
|
||||
jmp skip_name
|
||||
skip_quoted_name:
|
||||
lodsb
|
||||
cmp al,22h
|
||||
je find_param
|
||||
or al,al
|
||||
jz all_params
|
||||
jmp skip_quoted_name
|
||||
find_param:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je find_param
|
||||
cmp al,'-'
|
||||
je option_param
|
||||
cmp al,0Dh
|
||||
je all_params
|
||||
or al,al
|
||||
jz all_params
|
||||
cmp [input_file],0
|
||||
jne get_output_file
|
||||
mov [input_file],edi
|
||||
jmp process_param
|
||||
get_output_file:
|
||||
cmp [output_file],0
|
||||
jne bad_params
|
||||
mov [output_file],edi
|
||||
process_param:
|
||||
cmp al,22h
|
||||
je string_param
|
||||
copy_param:
|
||||
stosb
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je param_end
|
||||
cmp al,0Dh
|
||||
je param_end
|
||||
or al,al
|
||||
jz param_end
|
||||
jmp copy_param
|
||||
string_param:
|
||||
lodsb
|
||||
cmp al,22h
|
||||
je string_param_end
|
||||
cmp al,0Dh
|
||||
je param_end
|
||||
or al,al
|
||||
jz param_end
|
||||
stosb
|
||||
jmp string_param
|
||||
option_param:
|
||||
lodsb
|
||||
cmp al,'m'
|
||||
je memory_option
|
||||
cmp al,'M'
|
||||
je memory_option
|
||||
cmp al,'p'
|
||||
je passes_option
|
||||
cmp al,'P'
|
||||
je passes_option
|
||||
cmp al,'s'
|
||||
je symbols_option
|
||||
cmp al,'S'
|
||||
je symbols_option
|
||||
bad_params:
|
||||
stc
|
||||
ret
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
get_option_digit:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je option_value_ok
|
||||
cmp al,0Dh
|
||||
je option_value_ok
|
||||
or al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec esi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
memory_option:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je memory_option
|
||||
cmp al,0Dh
|
||||
je bad_params
|
||||
or al,al
|
||||
jz bad_params
|
||||
dec esi
|
||||
call get_option_value
|
||||
or edx,edx
|
||||
jz bad_params
|
||||
cmp edx,1 shl (32-10)
|
||||
jae bad_params
|
||||
mov [memory_setting],edx
|
||||
jmp find_param
|
||||
passes_option:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je passes_option
|
||||
cmp al,0Dh
|
||||
je bad_params
|
||||
or al,al
|
||||
jz bad_params
|
||||
dec esi
|
||||
call get_option_value
|
||||
or edx,edx
|
||||
jz bad_params
|
||||
cmp edx,10000h
|
||||
ja bad_params
|
||||
mov [passes_limit],dx
|
||||
jmp find_param
|
||||
symbols_option:
|
||||
mov [symbols_file],edi
|
||||
find_symbols_file_name:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
jne process_param
|
||||
jmp find_symbols_file_name
|
||||
param_end:
|
||||
dec esi
|
||||
string_param_end:
|
||||
xor al,al
|
||||
stosb
|
||||
jmp find_param
|
||||
all_params:
|
||||
cmp [input_file],0
|
||||
je bad_params
|
||||
clc
|
||||
ret
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
include '..\errors.inc'
|
||||
include '..\symbdump.inc'
|
||||
include '..\preproce.inc'
|
||||
include '..\parser.inc'
|
||||
include '..\exprpars.inc'
|
||||
include '..\assemble.inc'
|
||||
include '..\exprcalc.inc'
|
||||
include '..\formats.inc'
|
||||
include '..\x86_64.inc'
|
||||
include '..\avx.inc'
|
||||
|
||||
include '..\tables.inc'
|
||||
include '..\messages.inc'
|
||||
|
||||
section '.data' data readable writeable
|
||||
|
||||
include '..\version.inc'
|
||||
|
||||
_copyright db 'Copyright (c) 1999-2014, Tomasz Grysztar',0Dh,0Ah,0
|
||||
|
||||
_logo db 'flat assembler version ',VERSION_STRING,0
|
||||
_usage db 0Dh,0Ah
|
||||
db 'usage: fasm <source> [output]',0Dh,0Ah
|
||||
db 'optional settings:',0Dh,0Ah
|
||||
db ' -m <limit> set the limit in kilobytes for the available memory',0Dh,0Ah
|
||||
db ' -p <limit> set the maximum allowed number of passes',0Dh,0Ah
|
||||
db ' -s <file> dump symbolic information for debugging',0Dh,0Ah
|
||||
db 0
|
||||
_memory_prefix db ' (',0
|
||||
_memory_suffix db ' kilobytes memory)',0Dh,0Ah,0
|
||||
_passes_suffix db ' passes, ',0
|
||||
_seconds_suffix db ' seconds, ',0
|
||||
_bytes_suffix db ' bytes.',0Dh,0Ah,0
|
||||
|
||||
align 4
|
||||
|
||||
include '..\variable.inc'
|
||||
|
||||
con_handle dd ?
|
||||
memory_setting dd ?
|
||||
start_time dd ?
|
||||
bytes_count dd ?
|
||||
displayed_count dd ?
|
||||
character db ?
|
||||
last_displayed rb 2
|
||||
|
||||
params rb 1000h
|
||||
options rb 1000h
|
||||
buffer rb 4000h
|
||||
|
||||
stack 10000h
|
||||
|
||||
section '.idata' import data readable writeable
|
||||
|
||||
dd 0,0,0,rva kernel_name,rva kernel_table
|
||||
dd 0,0,0,0,0
|
||||
|
||||
kernel_table:
|
||||
ExitProcess dd rva _ExitProcess
|
||||
CreateFile dd rva _CreateFileA
|
||||
ReadFile dd rva _ReadFile
|
||||
WriteFile dd rva _WriteFile
|
||||
CloseHandle dd rva _CloseHandle
|
||||
SetFilePointer dd rva _SetFilePointer
|
||||
GetCommandLine dd rva _GetCommandLineA
|
||||
GetEnvironmentVariable dd rva _GetEnvironmentVariable
|
||||
GetStdHandle dd rva _GetStdHandle
|
||||
VirtualAlloc dd rva _VirtualAlloc
|
||||
VirtualFree dd rva _VirtualFree
|
||||
GetTickCount dd rva _GetTickCount
|
||||
GetSystemTime dd rva _GetSystemTime
|
||||
GlobalMemoryStatus dd rva _GlobalMemoryStatus
|
||||
dd 0
|
||||
|
||||
kernel_name db 'KERNEL32.DLL',0
|
||||
|
||||
_ExitProcess dw 0
|
||||
db 'ExitProcess',0
|
||||
_CreateFileA dw 0
|
||||
db 'CreateFileA',0
|
||||
_ReadFile dw 0
|
||||
db 'ReadFile',0
|
||||
_WriteFile dw 0
|
||||
db 'WriteFile',0
|
||||
_CloseHandle dw 0
|
||||
db 'CloseHandle',0
|
||||
_SetFilePointer dw 0
|
||||
db 'SetFilePointer',0
|
||||
_GetCommandLineA dw 0
|
||||
db 'GetCommandLineA',0
|
||||
_GetEnvironmentVariable dw 0
|
||||
db 'GetEnvironmentVariableA',0
|
||||
_GetStdHandle dw 0
|
||||
db 'GetStdHandle',0
|
||||
_VirtualAlloc dw 0
|
||||
db 'VirtualAlloc',0
|
||||
_VirtualFree dw 0
|
||||
db 'VirtualFree',0
|
||||
_GetTickCount dw 0
|
||||
db 'GetTickCount',0
|
||||
_GetSystemTime dw 0
|
||||
db 'GetSystemTime',0
|
||||
_GlobalMemoryStatus dw 0
|
||||
db 'GlobalMemoryStatus',0
|
||||
|
||||
section '.reloc' fixups data readable discardable
|
||||
503
samples/Assembly/SYSTEM.inc
Normal file
503
samples/Assembly/SYSTEM.inc
Normal file
@@ -0,0 +1,503 @@
|
||||
|
||||
; flat assembler interface for Win32
|
||||
; Copyright (c) 1999-2014, Tomasz Grysztar.
|
||||
; All rights reserved.
|
||||
|
||||
CREATE_NEW = 1
|
||||
CREATE_ALWAYS = 2
|
||||
OPEN_EXISTING = 3
|
||||
OPEN_ALWAYS = 4
|
||||
TRUNCATE_EXISTING = 5
|
||||
|
||||
FILE_SHARE_READ = 1
|
||||
FILE_SHARE_WRITE = 2
|
||||
FILE_SHARE_DELETE = 4
|
||||
|
||||
GENERIC_READ = 80000000h
|
||||
GENERIC_WRITE = 40000000h
|
||||
|
||||
STD_INPUT_HANDLE = 0FFFFFFF6h
|
||||
STD_OUTPUT_HANDLE = 0FFFFFFF5h
|
||||
STD_ERROR_HANDLE = 0FFFFFFF4h
|
||||
|
||||
MEM_COMMIT = 1000h
|
||||
MEM_RESERVE = 2000h
|
||||
MEM_DECOMMIT = 4000h
|
||||
MEM_RELEASE = 8000h
|
||||
MEM_FREE = 10000h
|
||||
MEM_PRIVATE = 20000h
|
||||
MEM_MAPPED = 40000h
|
||||
MEM_RESET = 80000h
|
||||
MEM_TOP_DOWN = 100000h
|
||||
|
||||
PAGE_NOACCESS = 1
|
||||
PAGE_READONLY = 2
|
||||
PAGE_READWRITE = 4
|
||||
PAGE_WRITECOPY = 8
|
||||
PAGE_EXECUTE = 10h
|
||||
PAGE_EXECUTE_READ = 20h
|
||||
PAGE_EXECUTE_READWRITE = 40h
|
||||
PAGE_EXECUTE_WRITECOPY = 80h
|
||||
PAGE_GUARD = 100h
|
||||
PAGE_NOCACHE = 200h
|
||||
|
||||
init_memory:
|
||||
xor eax,eax
|
||||
mov [memory_start],eax
|
||||
mov eax,esp
|
||||
and eax,not 0FFFh
|
||||
add eax,1000h-10000h
|
||||
mov [stack_limit],eax
|
||||
mov eax,[memory_setting]
|
||||
shl eax,10
|
||||
jnz allocate_memory
|
||||
push buffer
|
||||
call [GlobalMemoryStatus]
|
||||
mov eax,dword [buffer+20]
|
||||
mov edx,dword [buffer+12]
|
||||
cmp eax,0
|
||||
jl large_memory
|
||||
cmp edx,0
|
||||
jl large_memory
|
||||
shr eax,2
|
||||
add eax,edx
|
||||
jmp allocate_memory
|
||||
large_memory:
|
||||
mov eax,80000000h
|
||||
allocate_memory:
|
||||
mov edx,eax
|
||||
shr edx,2
|
||||
mov ecx,eax
|
||||
sub ecx,edx
|
||||
mov [memory_end],ecx
|
||||
mov [additional_memory_end],edx
|
||||
push PAGE_READWRITE
|
||||
push MEM_COMMIT
|
||||
push eax
|
||||
push 0
|
||||
call [VirtualAlloc]
|
||||
or eax,eax
|
||||
jz not_enough_memory
|
||||
mov [memory_start],eax
|
||||
add eax,[memory_end]
|
||||
mov [memory_end],eax
|
||||
mov [additional_memory],eax
|
||||
add [additional_memory_end],eax
|
||||
ret
|
||||
not_enough_memory:
|
||||
mov eax,[additional_memory_end]
|
||||
shl eax,1
|
||||
cmp eax,4000h
|
||||
jb out_of_memory
|
||||
jmp allocate_memory
|
||||
|
||||
exit_program:
|
||||
movzx eax,al
|
||||
push eax
|
||||
mov eax,[memory_start]
|
||||
test eax,eax
|
||||
jz do_exit
|
||||
push MEM_RELEASE
|
||||
push 0
|
||||
push eax
|
||||
call [VirtualFree]
|
||||
do_exit:
|
||||
call [ExitProcess]
|
||||
|
||||
get_environment_variable:
|
||||
mov ecx,[memory_end]
|
||||
sub ecx,edi
|
||||
cmp ecx,4000h
|
||||
jbe buffer_for_variable_ok
|
||||
mov ecx,4000h
|
||||
buffer_for_variable_ok:
|
||||
push ecx
|
||||
push edi
|
||||
push esi
|
||||
call [GetEnvironmentVariable]
|
||||
add edi,eax
|
||||
cmp edi,[memory_end]
|
||||
jae out_of_memory
|
||||
ret
|
||||
|
||||
open:
|
||||
push 0
|
||||
push 0
|
||||
push OPEN_EXISTING
|
||||
push 0
|
||||
push FILE_SHARE_READ
|
||||
push GENERIC_READ
|
||||
push edx
|
||||
call [CreateFile]
|
||||
cmp eax,-1
|
||||
je file_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
ret
|
||||
file_error:
|
||||
stc
|
||||
ret
|
||||
create:
|
||||
push 0
|
||||
push 0
|
||||
push CREATE_ALWAYS
|
||||
push 0
|
||||
push FILE_SHARE_READ
|
||||
push GENERIC_WRITE
|
||||
push edx
|
||||
call [CreateFile]
|
||||
cmp eax,-1
|
||||
je file_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
ret
|
||||
write:
|
||||
push 0
|
||||
push bytes_count
|
||||
push ecx
|
||||
push edx
|
||||
push ebx
|
||||
call [WriteFile]
|
||||
or eax,eax
|
||||
jz file_error
|
||||
clc
|
||||
ret
|
||||
read:
|
||||
mov ebp,ecx
|
||||
push 0
|
||||
push bytes_count
|
||||
push ecx
|
||||
push edx
|
||||
push ebx
|
||||
call [ReadFile]
|
||||
or eax,eax
|
||||
jz file_error
|
||||
cmp ebp,[bytes_count]
|
||||
jne file_error
|
||||
clc
|
||||
ret
|
||||
close:
|
||||
push ebx
|
||||
call [CloseHandle]
|
||||
ret
|
||||
lseek:
|
||||
movzx eax,al
|
||||
push eax
|
||||
push 0
|
||||
push edx
|
||||
push ebx
|
||||
call [SetFilePointer]
|
||||
ret
|
||||
|
||||
display_string:
|
||||
push [con_handle]
|
||||
call [GetStdHandle]
|
||||
mov ebp,eax
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
push 0
|
||||
push bytes_count
|
||||
push ecx
|
||||
push esi
|
||||
push ebp
|
||||
call [WriteFile]
|
||||
ret
|
||||
display_character:
|
||||
push ebx
|
||||
mov [character],dl
|
||||
push [con_handle]
|
||||
call [GetStdHandle]
|
||||
mov ebx,eax
|
||||
push 0
|
||||
push bytes_count
|
||||
push 1
|
||||
push character
|
||||
push ebx
|
||||
call [WriteFile]
|
||||
pop ebx
|
||||
ret
|
||||
display_number:
|
||||
push ebx
|
||||
mov ecx,1000000000
|
||||
xor edx,edx
|
||||
xor bl,bl
|
||||
display_loop:
|
||||
div ecx
|
||||
push edx
|
||||
cmp ecx,1
|
||||
je display_digit
|
||||
or bl,bl
|
||||
jnz display_digit
|
||||
or al,al
|
||||
jz digit_ok
|
||||
not bl
|
||||
display_digit:
|
||||
mov dl,al
|
||||
add dl,30h
|
||||
push ecx
|
||||
call display_character
|
||||
pop ecx
|
||||
digit_ok:
|
||||
mov eax,ecx
|
||||
xor edx,edx
|
||||
mov ecx,10
|
||||
div ecx
|
||||
mov ecx,eax
|
||||
pop eax
|
||||
or ecx,ecx
|
||||
jnz display_loop
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
display_user_messages:
|
||||
mov [displayed_count],0
|
||||
call show_display_buffer
|
||||
cmp [displayed_count],1
|
||||
jb line_break_ok
|
||||
je make_line_break
|
||||
mov ax,word [last_displayed]
|
||||
cmp ax,0A0Dh
|
||||
je line_break_ok
|
||||
cmp ax,0D0Ah
|
||||
je line_break_ok
|
||||
make_line_break:
|
||||
mov word [buffer],0A0Dh
|
||||
push [con_handle]
|
||||
call [GetStdHandle]
|
||||
push 0
|
||||
push bytes_count
|
||||
push 2
|
||||
push buffer
|
||||
push eax
|
||||
call [WriteFile]
|
||||
line_break_ok:
|
||||
ret
|
||||
display_block:
|
||||
add [displayed_count],ecx
|
||||
cmp ecx,1
|
||||
ja take_last_two_characters
|
||||
jb block_displayed
|
||||
mov al,[last_displayed+1]
|
||||
mov ah,[esi]
|
||||
mov word [last_displayed],ax
|
||||
jmp block_ok
|
||||
take_last_two_characters:
|
||||
mov ax,[esi+ecx-2]
|
||||
mov word [last_displayed],ax
|
||||
block_ok:
|
||||
push ecx
|
||||
push [con_handle]
|
||||
call [GetStdHandle]
|
||||
pop ecx
|
||||
push 0
|
||||
push bytes_count
|
||||
push ecx
|
||||
push esi
|
||||
push eax
|
||||
call [WriteFile]
|
||||
block_displayed:
|
||||
ret
|
||||
|
||||
fatal_error:
|
||||
mov [con_handle],STD_ERROR_HANDLE
|
||||
mov esi,error_prefix
|
||||
call display_string
|
||||
pop esi
|
||||
call display_string
|
||||
mov esi,error_suffix
|
||||
call display_string
|
||||
mov al,0FFh
|
||||
jmp exit_program
|
||||
assembler_error:
|
||||
mov [con_handle],STD_ERROR_HANDLE
|
||||
call display_user_messages
|
||||
push dword 0
|
||||
mov ebx,[current_line]
|
||||
get_error_lines:
|
||||
mov eax,[ebx]
|
||||
cmp byte [eax],0
|
||||
je get_next_error_line
|
||||
push ebx
|
||||
test byte [ebx+7],80h
|
||||
jz display_error_line
|
||||
mov edx,ebx
|
||||
find_definition_origin:
|
||||
mov edx,[edx+12]
|
||||
test byte [edx+7],80h
|
||||
jnz find_definition_origin
|
||||
push edx
|
||||
get_next_error_line:
|
||||
mov ebx,[ebx+8]
|
||||
jmp get_error_lines
|
||||
display_error_line:
|
||||
mov esi,[ebx]
|
||||
call display_string
|
||||
mov esi,line_number_start
|
||||
call display_string
|
||||
mov eax,[ebx+4]
|
||||
and eax,7FFFFFFFh
|
||||
call display_number
|
||||
mov dl,']'
|
||||
call display_character
|
||||
pop esi
|
||||
cmp ebx,esi
|
||||
je line_number_ok
|
||||
mov dl,20h
|
||||
call display_character
|
||||
push esi
|
||||
mov esi,[esi]
|
||||
movzx ecx,byte [esi]
|
||||
inc esi
|
||||
call display_block
|
||||
mov esi,line_number_start
|
||||
call display_string
|
||||
pop esi
|
||||
mov eax,[esi+4]
|
||||
and eax,7FFFFFFFh
|
||||
call display_number
|
||||
mov dl,']'
|
||||
call display_character
|
||||
line_number_ok:
|
||||
mov esi,line_data_start
|
||||
call display_string
|
||||
mov esi,ebx
|
||||
mov edx,[esi]
|
||||
call open
|
||||
mov al,2
|
||||
xor edx,edx
|
||||
call lseek
|
||||
mov edx,[esi+8]
|
||||
sub eax,edx
|
||||
jz line_data_displayed
|
||||
push eax
|
||||
xor al,al
|
||||
call lseek
|
||||
mov ecx,[esp]
|
||||
mov edx,[additional_memory]
|
||||
lea eax,[edx+ecx]
|
||||
cmp eax,[additional_memory_end]
|
||||
ja out_of_memory
|
||||
call read
|
||||
call close
|
||||
pop ecx
|
||||
mov esi,[additional_memory]
|
||||
get_line_data:
|
||||
mov al,[esi]
|
||||
cmp al,0Ah
|
||||
je display_line_data
|
||||
cmp al,0Dh
|
||||
je display_line_data
|
||||
cmp al,1Ah
|
||||
je display_line_data
|
||||
or al,al
|
||||
jz display_line_data
|
||||
inc esi
|
||||
loop get_line_data
|
||||
display_line_data:
|
||||
mov ecx,esi
|
||||
mov esi,[additional_memory]
|
||||
sub ecx,esi
|
||||
call display_block
|
||||
line_data_displayed:
|
||||
mov esi,cr_lf
|
||||
call display_string
|
||||
pop ebx
|
||||
or ebx,ebx
|
||||
jnz display_error_line
|
||||
mov esi,error_prefix
|
||||
call display_string
|
||||
pop esi
|
||||
call display_string
|
||||
mov esi,error_suffix
|
||||
call display_string
|
||||
mov al,2
|
||||
jmp exit_program
|
||||
|
||||
make_timestamp:
|
||||
push buffer
|
||||
call [GetSystemTime]
|
||||
movzx ecx,word [buffer]
|
||||
mov eax,ecx
|
||||
sub eax,1970
|
||||
mov ebx,365
|
||||
mul ebx
|
||||
mov ebp,eax
|
||||
mov eax,ecx
|
||||
sub eax,1969
|
||||
shr eax,2
|
||||
add ebp,eax
|
||||
mov eax,ecx
|
||||
sub eax,1901
|
||||
mov ebx,100
|
||||
div ebx
|
||||
sub ebp,eax
|
||||
mov eax,ecx
|
||||
xor edx,edx
|
||||
sub eax,1601
|
||||
mov ebx,400
|
||||
div ebx
|
||||
add ebp,eax
|
||||
movzx ecx,word [buffer+2]
|
||||
mov eax,ecx
|
||||
dec eax
|
||||
mov ebx,30
|
||||
mul ebx
|
||||
add ebp,eax
|
||||
cmp ecx,8
|
||||
jbe months_correction
|
||||
mov eax,ecx
|
||||
sub eax,7
|
||||
shr eax,1
|
||||
add ebp,eax
|
||||
mov ecx,8
|
||||
months_correction:
|
||||
mov eax,ecx
|
||||
shr eax,1
|
||||
add ebp,eax
|
||||
cmp ecx,2
|
||||
jbe day_correction_ok
|
||||
sub ebp,2
|
||||
movzx ecx,word [buffer]
|
||||
test ecx,11b
|
||||
jnz day_correction_ok
|
||||
xor edx,edx
|
||||
mov eax,ecx
|
||||
mov ebx,100
|
||||
div ebx
|
||||
or edx,edx
|
||||
jnz day_correction
|
||||
mov eax,ecx
|
||||
mov ebx,400
|
||||
div ebx
|
||||
or edx,edx
|
||||
jnz day_correction_ok
|
||||
day_correction:
|
||||
inc ebp
|
||||
day_correction_ok:
|
||||
movzx eax,word [buffer+6]
|
||||
dec eax
|
||||
add eax,ebp
|
||||
mov ebx,24
|
||||
mul ebx
|
||||
movzx ecx,word [buffer+8]
|
||||
add eax,ecx
|
||||
mov ebx,60
|
||||
mul ebx
|
||||
movzx ecx,word [buffer+10]
|
||||
add eax,ecx
|
||||
mov ebx,60
|
||||
mul ebx
|
||||
movzx ecx,word [buffer+12]
|
||||
add eax,ecx
|
||||
adc edx,0
|
||||
ret
|
||||
|
||||
error_prefix db 'error: ',0
|
||||
error_suffix db '.'
|
||||
cr_lf db 0Dh,0Ah,0
|
||||
line_number_start db ' [',0
|
||||
line_data_start db ':',0Dh,0Ah,0
|
||||
7060
samples/Assembly/X86_64.inc
Normal file
7060
samples/Assembly/X86_64.inc
Normal file
File diff suppressed because it is too large
Load Diff
664
samples/C++/epoll_reactor.ipp
Normal file
664
samples/C++/epoll_reactor.ipp
Normal file
@@ -0,0 +1,664 @@
|
||||
//
|
||||
// detail/impl/epoll_reactor.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_EPOLL)
|
||||
|
||||
#include <cstddef>
|
||||
#include <sys/epoll.h>
|
||||
#include <boost/asio/detail/epoll_reactor.hpp>
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
# include <sys/timerfd.h>
|
||||
#endif // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
epoll_reactor::epoll_reactor(boost::asio::io_service& io_service)
|
||||
: boost::asio::detail::service_base<epoll_reactor>(io_service),
|
||||
io_service_(use_service<io_service_impl>(io_service)),
|
||||
mutex_(),
|
||||
interrupter_(),
|
||||
epoll_fd_(do_epoll_create()),
|
||||
timer_fd_(do_timerfd_create()),
|
||||
shutdown_(false)
|
||||
{
|
||||
// Add the interrupter's descriptor to epoll.
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLET;
|
||||
ev.data.ptr = &interrupter_;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
|
||||
interrupter_.interrupt();
|
||||
|
||||
// Add the timer descriptor to epoll.
|
||||
if (timer_fd_ != -1)
|
||||
{
|
||||
ev.events = EPOLLIN | EPOLLERR;
|
||||
ev.data.ptr = &timer_fd_;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
|
||||
}
|
||||
}
|
||||
|
||||
epoll_reactor::~epoll_reactor()
|
||||
{
|
||||
if (epoll_fd_ != -1)
|
||||
close(epoll_fd_);
|
||||
if (timer_fd_ != -1)
|
||||
close(timer_fd_);
|
||||
}
|
||||
|
||||
void epoll_reactor::shutdown_service()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
lock.unlock();
|
||||
|
||||
op_queue<operation> ops;
|
||||
|
||||
while (descriptor_state* state = registered_descriptors_.first())
|
||||
{
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
ops.push(state->op_queue_[i]);
|
||||
state->shutdown_ = true;
|
||||
registered_descriptors_.free(state);
|
||||
}
|
||||
|
||||
timer_queues_.get_all_timers(ops);
|
||||
|
||||
io_service_.abandon_operations(ops);
|
||||
}
|
||||
|
||||
void epoll_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
|
||||
{
|
||||
if (fork_ev == boost::asio::io_service::fork_child)
|
||||
{
|
||||
if (epoll_fd_ != -1)
|
||||
::close(epoll_fd_);
|
||||
epoll_fd_ = -1;
|
||||
epoll_fd_ = do_epoll_create();
|
||||
|
||||
if (timer_fd_ != -1)
|
||||
::close(timer_fd_);
|
||||
timer_fd_ = -1;
|
||||
timer_fd_ = do_timerfd_create();
|
||||
|
||||
interrupter_.recreate();
|
||||
|
||||
// Add the interrupter's descriptor to epoll.
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLET;
|
||||
ev.data.ptr = &interrupter_;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
|
||||
interrupter_.interrupt();
|
||||
|
||||
// Add the timer descriptor to epoll.
|
||||
if (timer_fd_ != -1)
|
||||
{
|
||||
ev.events = EPOLLIN | EPOLLERR;
|
||||
ev.data.ptr = &timer_fd_;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
|
||||
}
|
||||
|
||||
update_timeout();
|
||||
|
||||
// Re-register all descriptors with epoll.
|
||||
mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
|
||||
for (descriptor_state* state = registered_descriptors_.first();
|
||||
state != 0; state = state->next_)
|
||||
{
|
||||
ev.events = state->registered_events_;
|
||||
ev.data.ptr = state;
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, state->descriptor_, &ev);
|
||||
if (result != 0)
|
||||
{
|
||||
boost::system::error_code ec(errno,
|
||||
boost::asio::error::get_system_category());
|
||||
boost::asio::detail::throw_error(ec, "epoll re-registration");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void epoll_reactor::init_task()
|
||||
{
|
||||
io_service_.init_task();
|
||||
}
|
||||
|
||||
int epoll_reactor::register_descriptor(socket_type descriptor,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data)
|
||||
{
|
||||
descriptor_data = allocate_descriptor_state();
|
||||
|
||||
{
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
descriptor_data->reactor_ = this;
|
||||
descriptor_data->descriptor_ = descriptor;
|
||||
descriptor_data->shutdown_ = false;
|
||||
}
|
||||
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;
|
||||
descriptor_data->registered_events_ = ev.events;
|
||||
ev.data.ptr = descriptor_data;
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
return errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int epoll_reactor::register_internal_descriptor(
|
||||
int op_type, socket_type descriptor,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op)
|
||||
{
|
||||
descriptor_data = allocate_descriptor_state();
|
||||
|
||||
{
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
descriptor_data->reactor_ = this;
|
||||
descriptor_data->descriptor_ = descriptor;
|
||||
descriptor_data->shutdown_ = false;
|
||||
descriptor_data->op_queue_[op_type].push(op);
|
||||
}
|
||||
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;
|
||||
descriptor_data->registered_events_ = ev.events;
|
||||
ev.data.ptr = descriptor_data;
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
return errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epoll_reactor::move_descriptor(socket_type,
|
||||
epoll_reactor::per_descriptor_data& target_descriptor_data,
|
||||
epoll_reactor::per_descriptor_data& source_descriptor_data)
|
||||
{
|
||||
target_descriptor_data = source_descriptor_data;
|
||||
source_descriptor_data = 0;
|
||||
}
|
||||
|
||||
void epoll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op,
|
||||
bool is_continuation, bool allow_speculative)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
{
|
||||
op->ec_ = boost::asio::error::bad_descriptor;
|
||||
post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
if (descriptor_data->shutdown_)
|
||||
{
|
||||
post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
if (descriptor_data->op_queue_[op_type].empty())
|
||||
{
|
||||
if (allow_speculative
|
||||
&& (op_type != read_op
|
||||
|| descriptor_data->op_queue_[except_op].empty()))
|
||||
{
|
||||
if (op->perform())
|
||||
{
|
||||
descriptor_lock.unlock();
|
||||
io_service_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
|
||||
if (op_type == write_op)
|
||||
{
|
||||
if ((descriptor_data->registered_events_ & EPOLLOUT) == 0)
|
||||
{
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = descriptor_data->registered_events_ | EPOLLOUT;
|
||||
ev.data.ptr = descriptor_data;
|
||||
if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev) == 0)
|
||||
{
|
||||
descriptor_data->registered_events_ |= ev.events;
|
||||
}
|
||||
else
|
||||
{
|
||||
op->ec_ = boost::system::error_code(errno,
|
||||
boost::asio::error::get_system_category());
|
||||
io_service_.post_immediate_completion(op, is_continuation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op_type == write_op)
|
||||
{
|
||||
descriptor_data->registered_events_ |= EPOLLOUT;
|
||||
}
|
||||
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = descriptor_data->registered_events_;
|
||||
ev.data.ptr = descriptor_data;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_data->op_queue_[op_type].push(op);
|
||||
io_service_.work_started();
|
||||
}
|
||||
|
||||
void epoll_reactor::cancel_ops(socket_type,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
op_queue<operation> ops;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
while (reactor_op* op = descriptor_data->op_queue_[i].front())
|
||||
{
|
||||
op->ec_ = boost::asio::error::operation_aborted;
|
||||
descriptor_data->op_queue_[i].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_lock.unlock();
|
||||
|
||||
io_service_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void epoll_reactor::deregister_descriptor(socket_type descriptor,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data, bool closing)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
if (!descriptor_data->shutdown_)
|
||||
{
|
||||
if (closing)
|
||||
{
|
||||
// The descriptor will be automatically removed from the epoll set when
|
||||
// it is closed.
|
||||
}
|
||||
else
|
||||
{
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
|
||||
}
|
||||
|
||||
op_queue<operation> ops;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
while (reactor_op* op = descriptor_data->op_queue_[i].front())
|
||||
{
|
||||
op->ec_ = boost::asio::error::operation_aborted;
|
||||
descriptor_data->op_queue_[i].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_data->descriptor_ = -1;
|
||||
descriptor_data->shutdown_ = true;
|
||||
|
||||
descriptor_lock.unlock();
|
||||
|
||||
free_descriptor_state(descriptor_data);
|
||||
descriptor_data = 0;
|
||||
|
||||
io_service_.post_deferred_completions(ops);
|
||||
}
|
||||
}
|
||||
|
||||
void epoll_reactor::deregister_internal_descriptor(socket_type descriptor,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
if (!descriptor_data->shutdown_)
|
||||
{
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
|
||||
|
||||
op_queue<operation> ops;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
ops.push(descriptor_data->op_queue_[i]);
|
||||
|
||||
descriptor_data->descriptor_ = -1;
|
||||
descriptor_data->shutdown_ = true;
|
||||
|
||||
descriptor_lock.unlock();
|
||||
|
||||
free_descriptor_state(descriptor_data);
|
||||
descriptor_data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void epoll_reactor::run(bool block, op_queue<operation>& ops)
|
||||
{
|
||||
// This code relies on the fact that the task_io_service queues the reactor
|
||||
// task behind all descriptor operations generated by this function. This
|
||||
// means, that by the time we reach this point, any previously returned
|
||||
// descriptor operations have already been dequeued. Therefore it is now safe
|
||||
// for us to reuse and return them for the task_io_service to queue again.
|
||||
|
||||
// Calculate a timeout only if timerfd is not used.
|
||||
int timeout;
|
||||
if (timer_fd_ != -1)
|
||||
timeout = block ? -1 : 0;
|
||||
else
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timeout = block ? get_timeout() : 0;
|
||||
}
|
||||
|
||||
// Block on the epoll descriptor.
|
||||
epoll_event events[128];
|
||||
int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
bool check_timers = (timer_fd_ == -1);
|
||||
#else // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
bool check_timers = true;
|
||||
#endif // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
|
||||
// Dispatch the waiting events.
|
||||
for (int i = 0; i < num_events; ++i)
|
||||
{
|
||||
void* ptr = events[i].data.ptr;
|
||||
if (ptr == &interrupter_)
|
||||
{
|
||||
// No need to reset the interrupter since we're leaving the descriptor
|
||||
// in a ready-to-read state and relying on edge-triggered notifications
|
||||
// to make it so that we only get woken up when the descriptor's epoll
|
||||
// registration is updated.
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
if (timer_fd_ == -1)
|
||||
check_timers = true;
|
||||
#else // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
check_timers = true;
|
||||
#endif // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
}
|
||||
#if defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
else if (ptr == &timer_fd_)
|
||||
{
|
||||
check_timers = true;
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
else
|
||||
{
|
||||
// The descriptor operation doesn't count as work in and of itself, so we
|
||||
// don't call work_started() here. This still allows the io_service to
|
||||
// stop if the only remaining operations are descriptor operations.
|
||||
descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
|
||||
descriptor_data->set_ready_events(events[i].events);
|
||||
ops.push(descriptor_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (check_timers)
|
||||
{
|
||||
mutex::scoped_lock common_lock(mutex_);
|
||||
timer_queues_.get_ready_timers(ops);
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
if (timer_fd_ != -1)
|
||||
{
|
||||
itimerspec new_timeout;
|
||||
itimerspec old_timeout;
|
||||
int flags = get_timeout(new_timeout);
|
||||
timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
}
|
||||
}
|
||||
|
||||
void epoll_reactor::interrupt()
|
||||
{
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLET;
|
||||
ev.data.ptr = &interrupter_;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);
|
||||
}
|
||||
|
||||
int epoll_reactor::do_epoll_create()
|
||||
{
|
||||
#if defined(EPOLL_CLOEXEC)
|
||||
int fd = epoll_create1(EPOLL_CLOEXEC);
|
||||
#else // defined(EPOLL_CLOEXEC)
|
||||
int fd = -1;
|
||||
errno = EINVAL;
|
||||
#endif // defined(EPOLL_CLOEXEC)
|
||||
|
||||
if (fd == -1 && (errno == EINVAL || errno == ENOSYS))
|
||||
{
|
||||
fd = epoll_create(epoll_size);
|
||||
if (fd != -1)
|
||||
::fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
boost::system::error_code ec(errno,
|
||||
boost::asio::error::get_system_category());
|
||||
boost::asio::detail::throw_error(ec, "epoll");
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int epoll_reactor::do_timerfd_create()
|
||||
{
|
||||
#if defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
# if defined(TFD_CLOEXEC)
|
||||
int fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
||||
# else // defined(TFD_CLOEXEC)
|
||||
int fd = -1;
|
||||
errno = EINVAL;
|
||||
# endif // defined(TFD_CLOEXEC)
|
||||
|
||||
if (fd == -1 && errno == EINVAL)
|
||||
{
|
||||
fd = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||
if (fd != -1)
|
||||
::fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
|
||||
return fd;
|
||||
#else // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
return -1;
|
||||
#endif // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
}
|
||||
|
||||
epoll_reactor::descriptor_state* epoll_reactor::allocate_descriptor_state()
|
||||
{
|
||||
mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
|
||||
return registered_descriptors_.alloc();
|
||||
}
|
||||
|
||||
void epoll_reactor::free_descriptor_state(epoll_reactor::descriptor_state* s)
|
||||
{
|
||||
mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
|
||||
registered_descriptors_.free(s);
|
||||
}
|
||||
|
||||
void epoll_reactor::do_add_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.insert(&queue);
|
||||
}
|
||||
|
||||
void epoll_reactor::do_remove_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.erase(&queue);
|
||||
}
|
||||
|
||||
void epoll_reactor::update_timeout()
|
||||
{
|
||||
#if defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
if (timer_fd_ != -1)
|
||||
{
|
||||
itimerspec new_timeout;
|
||||
itimerspec old_timeout;
|
||||
int flags = get_timeout(new_timeout);
|
||||
timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
|
||||
return;
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
interrupt();
|
||||
}
|
||||
|
||||
int epoll_reactor::get_timeout()
|
||||
{
|
||||
// By default we will wait no longer than 5 minutes. This will ensure that
|
||||
// any changes to the system clock are detected after no longer than this.
|
||||
return timer_queues_.wait_duration_msec(5 * 60 * 1000);
|
||||
}
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
int epoll_reactor::get_timeout(itimerspec& ts)
|
||||
{
|
||||
ts.it_interval.tv_sec = 0;
|
||||
ts.it_interval.tv_nsec = 0;
|
||||
|
||||
long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
|
||||
ts.it_value.tv_sec = usec / 1000000;
|
||||
ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
|
||||
|
||||
return usec ? 0 : TFD_TIMER_ABSTIME;
|
||||
}
|
||||
#endif // defined(BOOST_ASIO_HAS_TIMERFD)
|
||||
|
||||
struct epoll_reactor::perform_io_cleanup_on_block_exit
|
||||
{
|
||||
explicit perform_io_cleanup_on_block_exit(epoll_reactor* r)
|
||||
: reactor_(r), first_op_(0)
|
||||
{
|
||||
}
|
||||
|
||||
~perform_io_cleanup_on_block_exit()
|
||||
{
|
||||
if (first_op_)
|
||||
{
|
||||
// Post the remaining completed operations for invocation.
|
||||
if (!ops_.empty())
|
||||
reactor_->io_service_.post_deferred_completions(ops_);
|
||||
|
||||
// A user-initiated operation has completed, but there's no need to
|
||||
// explicitly call work_finished() here. Instead, we'll take advantage of
|
||||
// the fact that the task_io_service will call work_finished() once we
|
||||
// return.
|
||||
}
|
||||
else
|
||||
{
|
||||
// No user-initiated operations have completed, so we need to compensate
|
||||
// for the work_finished() call that the task_io_service will make once
|
||||
// this operation returns.
|
||||
reactor_->io_service_.work_started();
|
||||
}
|
||||
}
|
||||
|
||||
epoll_reactor* reactor_;
|
||||
op_queue<operation> ops_;
|
||||
operation* first_op_;
|
||||
};
|
||||
|
||||
epoll_reactor::descriptor_state::descriptor_state()
|
||||
: operation(&epoll_reactor::descriptor_state::do_complete)
|
||||
{
|
||||
}
|
||||
|
||||
operation* epoll_reactor::descriptor_state::perform_io(uint32_t events)
|
||||
{
|
||||
mutex_.lock();
|
||||
perform_io_cleanup_on_block_exit io_cleanup(reactor_);
|
||||
mutex::scoped_lock descriptor_lock(mutex_, mutex::scoped_lock::adopt_lock);
|
||||
|
||||
// Exception operations must be processed first to ensure that any
|
||||
// out-of-band data is read before normal data.
|
||||
static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
|
||||
for (int j = max_ops - 1; j >= 0; --j)
|
||||
{
|
||||
if (events & (flag[j] | EPOLLERR | EPOLLHUP))
|
||||
{
|
||||
while (reactor_op* op = op_queue_[j].front())
|
||||
{
|
||||
if (op->perform())
|
||||
{
|
||||
op_queue_[j].pop();
|
||||
io_cleanup.ops_.push(op);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The first operation will be returned for completion now. The others will
|
||||
// be posted for later by the io_cleanup object's destructor.
|
||||
io_cleanup.first_op_ = io_cleanup.ops_.front();
|
||||
io_cleanup.ops_.pop();
|
||||
return io_cleanup.first_op_;
|
||||
}
|
||||
|
||||
void epoll_reactor::descriptor_state::do_complete(
|
||||
io_service_impl* owner, operation* base,
|
||||
const boost::system::error_code& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (owner)
|
||||
{
|
||||
descriptor_state* descriptor_data = static_cast<descriptor_state*>(base);
|
||||
uint32_t events = static_cast<uint32_t>(bytes_transferred);
|
||||
if (operation* op = descriptor_data->perform_io(events))
|
||||
{
|
||||
op->complete(*owner, ec, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_EPOLL)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
|
||||
82
samples/Common Lisp/macros-advanced.cl
Normal file
82
samples/Common Lisp/macros-advanced.cl
Normal file
@@ -0,0 +1,82 @@
|
||||
;; @file macros-advanced.cl
|
||||
;;
|
||||
;; @breif Advanced macro practices - defining your own macros
|
||||
;;
|
||||
;; Macro definition skeleton:
|
||||
;; (defmacro name (parameter*)
|
||||
;; "Optional documentation string"
|
||||
;; body-form*)
|
||||
;;
|
||||
;; Note that backquote expression is most often used in the `body-form`
|
||||
;;
|
||||
|
||||
; `primep` test a number for prime
|
||||
(defun primep (n)
|
||||
"test a number for prime"
|
||||
(if (< n 2) (return-from primep))
|
||||
(do ((i 2 (1+ i)) (p t (not (zerop (mod n i)))))
|
||||
((> i (sqrt n)) p)
|
||||
(when (not p) (return))))
|
||||
; `next-prime` return the next prime bigger than the specified number
|
||||
(defun next-prime (n)
|
||||
"return the next prime bigger than the speicified number"
|
||||
(do ((i (1+ n) (1+ i)))
|
||||
((primep i) i)))
|
||||
;
|
||||
; The recommended procedures to writting a new macro are as follows:
|
||||
; 1. Write a sample call to the macro and the code it should expand into
|
||||
(do-primes (p 0 19)
|
||||
(format t "~d " p))
|
||||
; Expected expanded codes
|
||||
(do ((p (next-prime (- 0 1)) (next-prime p)))
|
||||
((> p 19))
|
||||
(format t "~d " p))
|
||||
; 2. Write code that generate the hardwritten expansion from the arguments in
|
||||
; the sample call
|
||||
(defmacro do-primes (var-and-range &rest body)
|
||||
(let ((var (first var-and-range))
|
||||
(start (second var-and-range))
|
||||
(end (third var-and-range)))
|
||||
`(do ((,var (next-prime (- ,start 1)) (next-prime ,var)))
|
||||
((> ,var ,end))
|
||||
,@body)))
|
||||
; 2-1. More concise implementations with the 'parameter list destructuring' and
|
||||
; '&body' synonym, it also emits more friendly messages on incorrent input.
|
||||
(defmacro do-primes ((var start end) &body body)
|
||||
`(do ((,var (next-prime (- ,start 1)) (next-prime ,var)))
|
||||
((> ,var ,end))
|
||||
,@body))
|
||||
; 2-2. Test the result of macro expansion with the `macroexpand-1` function
|
||||
(macroexpand-1 '(do-primes (p 0 19) (format t "~d " p)))
|
||||
; 3. Make sure the macro abstraction does not "leak"
|
||||
(defmacro do-primes ((var start end) &body body)
|
||||
(let ((end-value-name (gensym)))
|
||||
`(do ((,var (next-prime (- ,start 1)) (next-prime ,var))
|
||||
(,end-value-name ,end))
|
||||
((> ,var ,end-value-name))
|
||||
,@body)))
|
||||
; 3-1. Rules to observe to avoid common and possible leaks
|
||||
; a. include any subforms in the expansion in positions that will be evaluated
|
||||
; in the same order as the subforms appear in the macro call
|
||||
; b. make sure subforms are evaluated only once by creating a variable in the
|
||||
; expansion to hold the value of evaluating the argument form, and then
|
||||
; using that variable anywhere else the value is needed in the expansion
|
||||
; c. use `gensym` at macro expansion time to create variable names used in the
|
||||
; expansion
|
||||
;
|
||||
; Appendix I. Macro-writting macros, 'with-gensyms', to guranttee that rule c
|
||||
; gets observed.
|
||||
; Example usage of `with-gensyms`
|
||||
(defmacro do-primes-a ((var start end) &body body)
|
||||
"do-primes implementation with macro-writting macro 'with-gensyms'"
|
||||
(with-gensyms (end-value-name)
|
||||
`(do ((,var (next-prime (- ,start 1)) (next-prime ,var))
|
||||
(,end-value-name ,end))
|
||||
((> ,var ,end-value-name))
|
||||
,@body)))
|
||||
; Define the macro, note how comma is used to interpolate the value of the loop
|
||||
; expression
|
||||
(defmacro with-gensyms ((&rest names) &body body)
|
||||
`(let ,(loop for n in names collect `(,n (gensym)))
|
||||
,@body)
|
||||
)
|
||||
475
samples/Common Lisp/motor-inferencia.cl
Normal file
475
samples/Common Lisp/motor-inferencia.cl
Normal file
@@ -0,0 +1,475 @@
|
||||
#|
|
||||
ESCUELA POLITECNICA SUPERIOR - UNIVERSIDAD AUTONOMA DE MADRID
|
||||
INTELIGENCIA ARTIFICIAL
|
||||
|
||||
Motor de inferencia
|
||||
Basado en parte en "Paradigms of AI Programming: Case Studies
|
||||
in Common Lisp", de Peter Norvig, 1992
|
||||
|#
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;; Global variables
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(defvar *hypothesis-list*)
|
||||
(defvar *rule-list*)
|
||||
(defvar *fact-list*)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;; Constants
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defconstant +fail+ nil "Indicates unification failure")
|
||||
|
||||
(defconstant +no-bindings+ '((nil))
|
||||
"Indicates unification success, with no variables.")
|
||||
|
||||
(defconstant *mundo-abierto* nil)
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;; Functions for the user
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
;; Resets *fact-list* to NIL
|
||||
(defun erase-facts () (setq *fact-list* nil))
|
||||
|
||||
(defun set-hypothesis-list (h) (setq *hypothesis-list* h))
|
||||
|
||||
|
||||
;; Returns a list of solutions, each one satisfying all the hypothesis contained
|
||||
;; in *hypothesis-list*
|
||||
(defun motor-inferencia ()
|
||||
(consulta *hypothesis-list*))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;; Auxiliary functions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
#|____________________________________________________________________________
|
||||
FUNCTION: CONSULTA
|
||||
|
||||
COMMENTS:
|
||||
CONSULTA receives a list of hypothesis (variable <hypotheses>), and returns
|
||||
a list of binding lists (each binding list being a solution).
|
||||
|
||||
EXAMPLES:
|
||||
hypotheses is:
|
||||
((brothers ?x ?y) (neighbours juan ?x)).
|
||||
|
||||
That is, we are searching the brothers of the possible neighbors of Juan.
|
||||
|
||||
The function can return in this case:
|
||||
|
||||
(((?x . sergio) (?y . javier)) ((?x . julian) (?y . mario)) ((?x . julian) (?y . pedro))).
|
||||
That is, the neighbors of Juan (Sergio and Julian) have 3 brothers in total(Javier, Mario, Pedro)
|
||||
____________________________________________________________________________|#
|
||||
|
||||
(defun consulta (hypotheses)
|
||||
(if (null hypotheses) (list +no-bindings+)
|
||||
(mapcan #'(lambda (b)
|
||||
(mapcar #'(lambda (x) (une-bindings-con-bindings b x))
|
||||
(consulta (subst-bindings b (rest hypotheses)))))
|
||||
(find-hypothesis-value (first hypotheses)))))
|
||||
|
||||
|
||||
|
||||
#|____________________________________________________________________________
|
||||
FUNCTION: FIND-HYPOTHESIS-VALUE
|
||||
|
||||
COMMENTS:
|
||||
This function manages the query a single query (only one hypothesis) given a binding list.
|
||||
It tries (in the following order) to:
|
||||
- Answer the query from *fact-list*
|
||||
- Answer the query from the rules in *rule-list*
|
||||
- Ask the user
|
||||
|
||||
The function returns a list of solutions (list of binding lists).
|
||||
|
||||
EXAMPLES:
|
||||
If hypothesis is (brothers ?x ?y)
|
||||
and the function returns:
|
||||
(((?x . sergio) (?y . javier)) ((?x . julian) (?y . maria)) ((?x . alberto) (?y . pedro))).
|
||||
|
||||
Means that Sergio and Javier and brothers, Julian and Mario are brothers, and Alberto and Pedro are brothers.
|
||||
____________________________________________________________________________|#
|
||||
|
||||
(defun find-hypothesis-value (hypothesis)
|
||||
(let (rules)
|
||||
(cond
|
||||
((equality? hypothesis)
|
||||
(value-from-equality hypothesis))
|
||||
((value-from-facts hypothesis))
|
||||
((setq good-rules (find-rules hypothesis))
|
||||
(value-from-rules hypothesis good-rules))
|
||||
(t (ask-user hypothesis)))))
|
||||
|
||||
|
||||
|
||||
; une-bindings-con-bindings takes two binding lists and returns a binding list
|
||||
; Assumes that b1 and b2 are not +fail+
|
||||
(defun une-bindings-con-bindings (b1 b2)
|
||||
(cond
|
||||
((equal b1 +no-bindings+) b2)
|
||||
((equal b2 +no-bindings+) b1)
|
||||
(T (append b1 b2))))
|
||||
|
||||
|
||||
|
||||
#|____________________________________________________________________________
|
||||
FUNCTION: VALUE-FROM-FACTS
|
||||
|
||||
COMMENTS:
|
||||
Returns all the solutions of <hypothesis> obtained directly from *fact-list*
|
||||
|
||||
EXAMPLES:
|
||||
> (setf *fact-list* '((man luis) (man pedro)(woman mart)(man daniel)(woman laura)))
|
||||
|
||||
> (value-from-facts '(man ?x))
|
||||
returns:
|
||||
|
||||
(((?X . LUIS)) ((?X . PEDRO)) ((?X . DANIEL)))
|
||||
____________________________________________________________________________|#
|
||||
|
||||
(defun value-from-facts (hypothesis)
|
||||
(mapcan #'(lambda(x) (let ((aux (unify hypothesis x)))
|
||||
(when aux (list aux)))) *fact-list*))
|
||||
|
||||
|
||||
|
||||
|
||||
#|____________________________________________________________________________
|
||||
FUNCTION: FIND-RULES
|
||||
|
||||
COMMENTS:
|
||||
Returns the rules in *rule-list* whose THENs unify with the term given in <hypothesis>
|
||||
The variables in the rules that satisfy this requirement are renamed.
|
||||
|
||||
EXAMPLES:
|
||||
> (setq *rule-list*
|
||||
'((R1 (pertenece ?E (?E . ?_)))
|
||||
(R2 (pertenece ?E (?_ . ?Xs)) :- ((pertenece ?E ?Xs)))))
|
||||
|
||||
Then:
|
||||
> (FIND-RULES (PERTENECE 1 (2 5)))
|
||||
returns:
|
||||
((R2 (PERTENECE ?E.1 (?_ . ?XS.2)) :- ((PERTENECE ?E.1 ?XS.2))))
|
||||
That is, only the THEN of rule R2 unify with <hypothesis>
|
||||
|
||||
However,
|
||||
> (FIND-RULES (PERTENECE 1 (1 6 7)))
|
||||
|
||||
returns:
|
||||
((R1 (PERTENECE ?E.6 (?E.6 . ?_)))
|
||||
(R2 (PERTENECE ?E.7 (?_ . ?XS.8)) :- ((PERTENECE ?E.7 ?XS.8))))
|
||||
So the THEN of both rules unify with <hypothesis>
|
||||
____________________________________________________________________________|#
|
||||
|
||||
(defun find-rules (hypothesis)
|
||||
(mapcan #'(lambda(b) (let ((renamed-rule (rename-variables b)))
|
||||
(when (in-then? hypothesis renamed-rule)
|
||||
(list renamed-rule)))) *rule-list*))
|
||||
|
||||
(defun in-then? (hypothesis rule)
|
||||
(unless (null (rule-then rule))
|
||||
(not (equal +fail+ (unify hypothesis (rule-then rule))))))
|
||||
|
||||
|
||||
|
||||
#|____________________________________________________________________________
|
||||
FUNCTION: VALUE-FROM-RULES
|
||||
|
||||
COMMENTS:
|
||||
Returns all the solutions to <hypothesis> found using all the rules given in
|
||||
the list <rules>. Note that a single rule can have multiple solutions.
|
||||
____________________________________________________________________________|#
|
||||
(defun value-from-rules (hypothesis rules)
|
||||
(mapcan #'(lambda (r) (eval-rule hypothesis r)) rules))
|
||||
|
||||
(defun limpia-vinculos (termino bindings)
|
||||
(unify termino (subst-bindings bindings termino)))
|
||||
|
||||
|
||||
#|____________________________________________________________________________
|
||||
FUNCTION: EVAL-RULE
|
||||
|
||||
COMMENTS:
|
||||
Returns all the solutions found using the rule given as input argument.
|
||||
|
||||
EXAMPLES:
|
||||
> (setq *rule-list*
|
||||
'((R1 (pertenece ?E (?E . ?_)))
|
||||
(R2 (pertenece ?E (?_ . ?Xs)) :- ((pertenece ?E ?Xs)))))
|
||||
Then:
|
||||
> (EVAL-RULE
|
||||
(PERTENECE 1 (1 6 7))
|
||||
(R1 (PERTENECE ?E.42 (?E.42 . ?_))))
|
||||
returns:
|
||||
(((NIL)))
|
||||
That is, the query (PERTENECE 1 (1 6 7)) can be proven from the given rule, and
|
||||
no binding in the variables in the query is necessary (in fact, the query has no variables).
|
||||
On the other hand:
|
||||
> (EVAL-RULE
|
||||
(PERTENECE 1 (7))
|
||||
(R2 (PERTENECE ?E.49 (?_ . ?XS.50)) :- ((PERTENECE ?E.49 ?XS.50))))
|
||||
returns:
|
||||
NIL
|
||||
That is, the query can not be proven from the rule R2.
|
||||
____________________________________________________________________________|#
|
||||
|
||||
(defun eval-rule (hypothesis rule)
|
||||
(let ((bindings-then
|
||||
(unify (rule-then rule) hypothesis)))
|
||||
(unless (equal +fail+ bindings-then)
|
||||
(if (rule-ifs rule)
|
||||
(mapcar #'(lambda(b) (limpia-vinculos hypothesis (append bindings-then b)))
|
||||
(consulta (subst-bindings bindings-then (rule-ifs rule))))
|
||||
(list (limpia-vinculos hypothesis bindings-then))))))
|
||||
|
||||
|
||||
(defun ask-user (hypothesis)
|
||||
(let ((question hypothesis))
|
||||
(cond
|
||||
((variables-in question) +fail+)
|
||||
((not-in-fact-list? question) +fail+)
|
||||
(*mundo-abierto*
|
||||
(format t "~%Es cierto el hecho ~S? (T/nil)" question)
|
||||
(cond
|
||||
((read) (add-fact question) +no-bindings+)
|
||||
(T (add-fact (list 'NOT question)) +fail+)))
|
||||
(T +fail+))))
|
||||
|
||||
|
||||
; value-from-equality:
|
||||
(defun value-from-equality (hypothesis)
|
||||
(let ((new-bindings (unify (second hypothesis) (third hypothesis))))
|
||||
(if (not (equal +fail+ new-bindings))
|
||||
(list new-bindings))))
|
||||
|
||||
|
||||
|
||||
#|____________________________________________________________________________
|
||||
FUNCTION: UNIFY
|
||||
|
||||
COMMENTS:
|
||||
Finds the most general unifier of two input expressions, taking into account the
|
||||
bindings specified in the input <bingings>
|
||||
In case the two expressions can unify, the function returns the total bindings necessary
|
||||
for that unification. Otherwise, returns +fail+
|
||||
|
||||
EXAMPLES:
|
||||
> (unify '1 '1)
|
||||
((NIL)) ;; which is the constant +no-bindings+
|
||||
> (unify 1 '2)
|
||||
nil ;; which is the constant +fail+
|
||||
> (unify '?x 1)
|
||||
((?x . 1))
|
||||
> (unify '(1 1) ?x)
|
||||
((? x 1 1))
|
||||
> (unify '?_ '?x)
|
||||
((NIL))
|
||||
> (unify '(p ?x 1 2) '(p ?y ?_ ?_))
|
||||
((?x . ?y))
|
||||
> (unify '(?a . ?_) '(1 2 3))
|
||||
((?a . 1))
|
||||
> (unify '(?_ ?_) '(1 2))
|
||||
((nil))
|
||||
> (unify '(?a . ?b) '(1 2 3))
|
||||
((?b 2 3) (?a . 1))
|
||||
> (unify '(?a . ?b) '(?v . ?d))
|
||||
((?b . ?d) (?a . ?v))
|
||||
> (unify '(?eval (+ 1 1)) '1)
|
||||
nil
|
||||
> (unify '(?eval (+ 1 1)) '2)
|
||||
(nil))
|
||||
____________________________________________________________________________|#
|
||||
|
||||
(defun unify (x y &optional (bindings +no-bindings+))
|
||||
"See if x and y match with given bindings. If they do,
|
||||
return a binding list that would make them equal [p 303]."
|
||||
(cond ((eq bindings +fail+) +fail+)
|
||||
((eql x y) bindings)
|
||||
((eval? x) (unify-eval x y bindings))
|
||||
((eval? y) (unify-eval y x bindings))
|
||||
((variable? x) (unify-var x y bindings))
|
||||
((variable? y) (unify-var y x bindings))
|
||||
((and (consp x) (consp y))
|
||||
(unify (rest x) (rest y)
|
||||
(unify (first x) (first y) bindings)))
|
||||
(t +fail+)))
|
||||
|
||||
|
||||
;; rename-variables: renombra ?X por ?X.1, ?Y por ?Y.2 etc. salvo ?_ que no se renombra
|
||||
(defun rename-variables (x)
|
||||
"Replace all variables in x with new ones. Excepto ?_"
|
||||
(sublis (mapcar #'(lambda (var)
|
||||
(if (anonymous-var? var)
|
||||
(make-binding var var)
|
||||
(make-binding var (new-variable var))))
|
||||
(variables-in x))
|
||||
x))
|
||||
|
||||
|
||||
|
||||
;;;; Auxiliary Functions
|
||||
|
||||
(defun unify-var (var x bindings)
|
||||
"Unify var with x, using (and maybe extending) bindings [p 303]."
|
||||
(cond ((or (anonymous-var? var)(anonymous-var? x)) bindings)
|
||||
((get-binding var bindings)
|
||||
(unify (lookup var bindings) x bindings))
|
||||
((and (variable? x) (get-binding x bindings))
|
||||
(unify var (lookup x bindings) bindings))
|
||||
((occurs-in? var x bindings)
|
||||
+fail+)
|
||||
(t (extend-bindings var x bindings))))
|
||||
|
||||
(defun variable? (x)
|
||||
"Is x a variable (a symbol starting with ?)?"
|
||||
(and (symbolp x) (eql (char (symbol-name x) 0) #\?)))
|
||||
|
||||
(defun get-binding (var bindings)
|
||||
"Find a (variable . value) pair in a binding list."
|
||||
(assoc var bindings))
|
||||
|
||||
(defun binding-var (binding)
|
||||
"Get the variable part of a single binding."
|
||||
(car binding))
|
||||
|
||||
(defun binding-val (binding)
|
||||
"Get the value part of a single binding."
|
||||
(cdr binding))
|
||||
|
||||
(defun make-binding (var val) (cons var val))
|
||||
|
||||
(defun lookup (var bindings)
|
||||
"Get the value part (for var) from a binding list."
|
||||
(binding-val (get-binding var bindings)))
|
||||
|
||||
(defun extend-bindings (var val bindings)
|
||||
"Add a (var . value) pair to a binding list."
|
||||
(append
|
||||
(unless (eq bindings +no-bindings+) bindings)
|
||||
(list (make-binding var val))))
|
||||
|
||||
(defun occurs-in? (var x bindings)
|
||||
"Does var occur anywhere inside x?"
|
||||
(cond ((eq var x) t)
|
||||
((and (variable? x) (get-binding x bindings))
|
||||
(occurs-in? var (lookup x bindings) bindings))
|
||||
((consp x) (or (occurs-in? var (first x) bindings)
|
||||
(occurs-in? var (rest x) bindings)))
|
||||
(t nil)))
|
||||
|
||||
(defun subst-bindings (bindings x)
|
||||
"Substitute the value of variables in bindings into x,
|
||||
taking recursively bound variables into account."
|
||||
(cond ((eq bindings +fail+) +fail+)
|
||||
((eq bindings +no-bindings+) x)
|
||||
((and (listp x) (eq '?eval (car x)))
|
||||
(subst-bindings-quote bindings x))
|
||||
((and (variable? x) (get-binding x bindings))
|
||||
(subst-bindings bindings (lookup x bindings)))
|
||||
((atom x) x)
|
||||
(t (cons (subst-bindings bindings (car x)) ;; s/reuse-cons/cons
|
||||
(subst-bindings bindings (cdr x))))))
|
||||
|
||||
(defun unifier (x y)
|
||||
"Return something that unifies with both x and y (or fail)."
|
||||
(subst-bindings (unify x y) x))
|
||||
|
||||
(defun variables-in (exp)
|
||||
"Return a list of all the variables in EXP."
|
||||
(unique-find-anywhere-if #'variable? exp))
|
||||
|
||||
(defun unique-find-anywhere-if (predicate tree &optional found-so-far)
|
||||
"Return a list of leaves of tree satisfying predicate,
|
||||
with duplicates removed."
|
||||
(if (atom tree)
|
||||
(if (funcall predicate tree)
|
||||
(pushnew tree found-so-far)
|
||||
found-so-far)
|
||||
(unique-find-anywhere-if
|
||||
predicate
|
||||
(first tree)
|
||||
(unique-find-anywhere-if predicate (rest tree)
|
||||
found-so-far))))
|
||||
|
||||
(defun find-anywhere-if (predicate tree)
|
||||
"Does predicate apply to any atom in the tree?"
|
||||
(if (atom tree)
|
||||
(funcall predicate tree)
|
||||
(or (find-anywhere-if predicate (first tree))
|
||||
(find-anywhere-if predicate (rest tree)))))
|
||||
|
||||
(defun new-variable (var)
|
||||
"Create a new variable. Assumes user never types variables of form ?X.9"
|
||||
(gentemp (format nil "~S." var)))
|
||||
; (gentemp "?") )
|
||||
;;;
|
||||
|
||||
(defun anonymous-var? (x)
|
||||
(eq x '?_))
|
||||
|
||||
(defun subst-bindings-quote (bindings x)
|
||||
"Substitute the value of variables in bindings into x,
|
||||
taking recursively bound variables into account."
|
||||
(cond ((eq bindings +fail+) +fail+)
|
||||
((eq bindings +no-bindings+) x)
|
||||
((and (variable? x) (get-binding x bindings))
|
||||
(if (variable? (lookup x bindings))
|
||||
(subst-bindings-quote bindings (lookup x bindings))
|
||||
(subst-bindings-quote bindings (list 'quote (lookup x bindings)))
|
||||
)
|
||||
)
|
||||
((atom x) x)
|
||||
(t (cons (subst-bindings-quote bindings (car x)) ;; s/reuse-cons/cons
|
||||
(subst-bindings-quote bindings (cdr x))))))
|
||||
|
||||
(defun eval? (x)
|
||||
(and (consp x) (eq (first x) '?eval)))
|
||||
|
||||
(defun unify-eval (x y bindings)
|
||||
(let ((exp (subst-bindings-quote bindings (second x))))
|
||||
(if (variables-in exp)
|
||||
+fail+
|
||||
(unify (eval exp) y bindings))))
|
||||
|
||||
|
||||
|
||||
(defun rule-ifs (rule) (fourth rule))
|
||||
(defun rule-then (rule) (second rule))
|
||||
|
||||
|
||||
(defun equality? (term)
|
||||
(and (consp term) (eql (first term) '?=)))
|
||||
|
||||
|
||||
(defun in-fact-list? (expresion)
|
||||
(some #'(lambda(x) (equal x expresion)) *fact-list*))
|
||||
|
||||
(defun not-in-fact-list? (expresion)
|
||||
(if (eq (car expresion) 'NOT)
|
||||
(in-fact-list? (second expresion))
|
||||
(in-fact-list? (list 'NOT expresion))))
|
||||
|
||||
|
||||
;; add-fact:
|
||||
|
||||
(defun add-fact (fact)
|
||||
(setq *fact-list* (cons fact *fact-list*)))
|
||||
|
||||
|
||||
(defun variable? (x)
|
||||
"Is x a variable (a symbol starting with ?) except ?eval and ?="
|
||||
(and (not (equal x '?eval)) (not (equal x '?=))
|
||||
(symbolp x) (eql (char (symbol-name x) 0) #\?)))
|
||||
|
||||
|
||||
;; EOF
|
||||
130
samples/Component Pascal/Example.cp
Normal file
130
samples/Component Pascal/Example.cp
Normal file
@@ -0,0 +1,130 @@
|
||||
MODULE ObxControls;
|
||||
(**
|
||||
project = "BlackBox"
|
||||
organization = "www.oberon.ch"
|
||||
contributors = "Oberon microsystems"
|
||||
version = "System/Rsrc/About"
|
||||
copyright = "System/Rsrc/About"
|
||||
license = "Docu/BB-License"
|
||||
changes = ""
|
||||
issues = ""
|
||||
|
||||
**)
|
||||
|
||||
IMPORT Dialog, Ports, Properties, Views;
|
||||
|
||||
CONST beginner = 0; advanced = 1; expert = 2; guru = 3; (* user classes *)
|
||||
|
||||
TYPE
|
||||
View = POINTER TO RECORD (Views.View)
|
||||
size: INTEGER (* border size in mm *)
|
||||
END;
|
||||
|
||||
VAR
|
||||
data*: RECORD
|
||||
class*: INTEGER; (* current user class *)
|
||||
list*: Dialog.List; (* list of currently available sizes, derived from class *)
|
||||
width*: INTEGER (* width of next view to be opened. Derived from
|
||||
class, or entered through a text entry field *)
|
||||
END;
|
||||
|
||||
predef: ARRAY 6 OF INTEGER; (* table of predefined sizes *)
|
||||
|
||||
|
||||
PROCEDURE SetList;
|
||||
BEGIN
|
||||
IF data.class = beginner THEN
|
||||
data.list.SetLen(1);
|
||||
data.list.SetItem(0, "default")
|
||||
ELSIF data.class = advanced THEN
|
||||
data.list.SetLen(4);
|
||||
data.list.SetItem(0, "default");
|
||||
data.list.SetItem(1, "small");
|
||||
data.list.SetItem(2, "medium");
|
||||
data.list.SetItem(3, "large");
|
||||
ELSE
|
||||
data.list.SetLen(6);
|
||||
data.list.SetItem(0, "default");
|
||||
data.list.SetItem(1, "small");
|
||||
data.list.SetItem(2, "medium");
|
||||
data.list.SetItem(3, "large");
|
||||
data.list.SetItem(4, "tiny");
|
||||
data.list.SetItem(5, "huge");
|
||||
END
|
||||
END SetList;
|
||||
|
||||
(* View *)
|
||||
|
||||
PROCEDURE (v: View) CopyFromSimpleView (source: Views.View);
|
||||
BEGIN
|
||||
v.size := source(View).size
|
||||
END CopyFromSimpleView;
|
||||
|
||||
PROCEDURE (v: View) Restore (f: Views.Frame; l, t, r, b: INTEGER);
|
||||
BEGIN (* fill view with a red square of size v.size *)
|
||||
IF v.size = 0 THEN v.size := predef[0] END; (* lazy initialization of size *)
|
||||
f.DrawRect(0, 0, v.size, v.size, Ports.fill, Ports.red)
|
||||
END Restore;
|
||||
|
||||
PROCEDURE (v: View) HandlePropMsg (VAR msg: Views.PropMessage);
|
||||
BEGIN
|
||||
WITH msg: Properties.SizePref DO
|
||||
IF v.size = 0 THEN v.size := predef[0] END; (* lazy initialization of size *)
|
||||
msg.w := v.size; msg.h := v.size (* tell environment about desired width and height *)
|
||||
ELSE (* ignore other messages *)
|
||||
END
|
||||
END HandlePropMsg;
|
||||
|
||||
(* notifiers *)
|
||||
|
||||
PROCEDURE ClassNotify* (op, from, to: INTEGER);
|
||||
BEGIN (* react to change in data.class *)
|
||||
IF op = Dialog.changed THEN
|
||||
IF (to = beginner) OR (to = advanced) & (data.list.index > 3) THEN
|
||||
(* if class is reduced, make sure that selection contains legal elements *)
|
||||
data.list.index := 0; data.width := predef[0]; (* modify interactor *)
|
||||
Dialog.Update(data) (* redraw controls where necessary *)
|
||||
END;
|
||||
SetList;
|
||||
Dialog.UpdateList(data.list) (* reconstruct list box contents *)
|
||||
END
|
||||
END ClassNotify;
|
||||
|
||||
PROCEDURE ListNotify* (op, from, to: INTEGER);
|
||||
BEGIN (* reacto to change in data.list (index to was selected) *)
|
||||
IF op = Dialog.changed THEN
|
||||
data.width := predef[to]; (* modify interactor *)
|
||||
Dialog.Update(data) (* redraw controls where necessary *)
|
||||
END
|
||||
END ListNotify;
|
||||
|
||||
(* guards *)
|
||||
|
||||
PROCEDURE ListGuard* (VAR par: Dialog.Par);
|
||||
BEGIN (* disable list box for a beginner *)
|
||||
par.disabled := data.class = beginner
|
||||
END ListGuard;
|
||||
|
||||
PROCEDURE WidthGuard* (VAR par: Dialog.Par);
|
||||
BEGIN (* make text entry field read-only if user is not guru *)
|
||||
par.readOnly := data.class # guru
|
||||
END WidthGuard;
|
||||
|
||||
(* commands *)
|
||||
|
||||
PROCEDURE Open*;
|
||||
VAR v: View;
|
||||
BEGIN
|
||||
NEW(v); (* create and initialize a new view *)
|
||||
v.size := data.width * Ports.mm; (* define view's size in function of class *)
|
||||
Views.OpenAux(v, "Example") (* open the view in a window *)
|
||||
END Open;
|
||||
|
||||
BEGIN (* initialization of global variables *)
|
||||
predef[0] := 40; predef[1] := 30; predef[2] := 50; (* predefined sizes *)
|
||||
predef[3] := 70; predef[4] := 20; predef[5] := 100;
|
||||
data.class := beginner; (* default values *)
|
||||
data.list.index := 0;
|
||||
data.width := predef[0];
|
||||
SetList
|
||||
END ObxControls.
|
||||
71
samples/Component Pascal/Example2.cps
Normal file
71
samples/Component Pascal/Example2.cps
Normal file
@@ -0,0 +1,71 @@
|
||||
MODULE ObxFact;
|
||||
(**
|
||||
project = "BlackBox"
|
||||
organization = "www.oberon.ch"
|
||||
contributors = "Oberon microsystems"
|
||||
version = "System/Rsrc/About"
|
||||
copyright = "System/Rsrc/About"
|
||||
license = "Docu/BB-License"
|
||||
changes = ""
|
||||
issues = ""
|
||||
|
||||
**)
|
||||
|
||||
IMPORT
|
||||
Stores, Models, TextModels, TextControllers, Integers;
|
||||
|
||||
PROCEDURE Read(r: TextModels.Reader; VAR x: Integers.Integer);
|
||||
VAR i, len, beg: INTEGER; ch: CHAR; buf: POINTER TO ARRAY OF CHAR;
|
||||
BEGIN
|
||||
r.ReadChar(ch);
|
||||
WHILE ~r.eot & (ch <= " ") DO r.ReadChar(ch) END;
|
||||
ASSERT(~r.eot & (((ch >= "0") & (ch <= "9")) OR (ch = "-")));
|
||||
beg := r.Pos() - 1; len := 0;
|
||||
REPEAT INC(len); r.ReadChar(ch) UNTIL r.eot OR (ch < "0") OR (ch > "9");
|
||||
NEW(buf, len + 1);
|
||||
i := 0; r.SetPos(beg);
|
||||
REPEAT r.ReadChar(buf[i]); INC(i) UNTIL i = len;
|
||||
buf[i] := 0X;
|
||||
Integers.ConvertFromString(buf^, x)
|
||||
END Read;
|
||||
|
||||
PROCEDURE Write(w: TextModels.Writer; x: Integers.Integer);
|
||||
VAR i: INTEGER;
|
||||
BEGIN
|
||||
IF Integers.Sign(x) < 0 THEN w.WriteChar("-") END;
|
||||
i := Integers.Digits10Of(x);
|
||||
IF i # 0 THEN
|
||||
REPEAT DEC(i); w.WriteChar(Integers.ThisDigit10(x, i)) UNTIL i = 0
|
||||
ELSE w.WriteChar("0")
|
||||
END
|
||||
END Write;
|
||||
|
||||
PROCEDURE Compute*;
|
||||
VAR beg, end, i, n: INTEGER; ch: CHAR;
|
||||
s: Stores.Operation;
|
||||
r: TextModels.Reader; w: TextModels.Writer; attr: TextModels.Attributes;
|
||||
c: TextControllers.Controller;
|
||||
x: Integers.Integer;
|
||||
BEGIN
|
||||
c := TextControllers.Focus();
|
||||
IF (c # NIL) & c.HasSelection() THEN
|
||||
c.GetSelection(beg, end);
|
||||
r := c.text.NewReader(NIL); r.SetPos(beg); r.ReadChar(ch);
|
||||
WHILE ~r.eot & (beg < end) & (ch <= " ") DO r.ReadChar(ch); INC(beg) END;
|
||||
IF ~r.eot & (beg < end) THEN
|
||||
r.ReadPrev; Read(r, x);
|
||||
end := r.Pos(); r.ReadPrev; attr :=r.attr;
|
||||
IF (Integers.Sign(x) > 0) & (Integers.Compare(x, Integers.Long(MAX(LONGINT))) <= 0) THEN
|
||||
n := SHORT(Integers.Short(x)); i := 2; x := Integers.Long(1);
|
||||
WHILE i <= n DO x := Integers.Product(x, Integers.Long(i)); INC(i) END;
|
||||
Models.BeginScript(c.text, "computation", s);
|
||||
c.text.Delete(beg, end);
|
||||
w := c.text.NewWriter(NIL); w.SetPos(beg); w.SetAttr(attr);
|
||||
Write(w, x);
|
||||
Models.EndScript(c.text, s)
|
||||
END
|
||||
END
|
||||
END
|
||||
END Compute;
|
||||
|
||||
END ObxFact.
|
||||
169
samples/Crystal/const_spec.cr
Normal file
169
samples/Crystal/const_spec.cr
Normal file
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env bin/crystal --run
|
||||
require "../../spec_helper"
|
||||
|
||||
describe "Codegen: const" do
|
||||
it "define a constant" do
|
||||
run("A = 1; A").to_i.should eq(1)
|
||||
end
|
||||
|
||||
it "support nested constant" do
|
||||
run("class B; A = 1; end; B::A").to_i.should eq(1)
|
||||
end
|
||||
|
||||
it "support constant inside a def" do
|
||||
run("
|
||||
class Foo
|
||||
A = 1
|
||||
|
||||
def foo
|
||||
A
|
||||
end
|
||||
end
|
||||
|
||||
Foo.new.foo
|
||||
").to_i.should eq(1)
|
||||
end
|
||||
|
||||
it "finds nearest constant first" do
|
||||
run("
|
||||
A = 1
|
||||
|
||||
class Foo
|
||||
A = 2.5_f32
|
||||
|
||||
def foo
|
||||
A
|
||||
end
|
||||
end
|
||||
|
||||
Foo.new.foo
|
||||
").to_f32.should eq(2.5)
|
||||
end
|
||||
|
||||
it "allows constants with same name" do
|
||||
run("
|
||||
A = 1
|
||||
|
||||
class Foo
|
||||
A = 2.5_f32
|
||||
|
||||
def foo
|
||||
A
|
||||
end
|
||||
end
|
||||
|
||||
A
|
||||
Foo.new.foo
|
||||
").to_f32.should eq(2.5)
|
||||
end
|
||||
|
||||
it "constants with expression" do
|
||||
run("
|
||||
A = 1 + 1
|
||||
A
|
||||
").to_i.should eq(2)
|
||||
end
|
||||
|
||||
it "finds global constant" do
|
||||
run("
|
||||
A = 1
|
||||
|
||||
class Foo
|
||||
def foo
|
||||
A
|
||||
end
|
||||
end
|
||||
|
||||
Foo.new.foo
|
||||
").to_i.should eq(1)
|
||||
end
|
||||
|
||||
it "define a constant in lib" do
|
||||
run("lib Foo; A = 1; end; Foo::A").to_i.should eq(1)
|
||||
end
|
||||
|
||||
it "invokes block in const" do
|
||||
run("require \"prelude\"; A = [\"1\"].map { |x| x.to_i }; A[0]").to_i.should eq(1)
|
||||
end
|
||||
|
||||
it "declare constants in right order" do
|
||||
run("A = 1 + 1; B = true ? A : 0; B").to_i.should eq(2)
|
||||
end
|
||||
|
||||
it "uses correct types lookup" do
|
||||
run("
|
||||
module A
|
||||
class B
|
||||
def foo
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
C = B.new;
|
||||
end
|
||||
|
||||
def foo
|
||||
A::C.foo
|
||||
end
|
||||
|
||||
foo
|
||||
").to_i.should eq(1)
|
||||
end
|
||||
|
||||
it "codegens variable assignment in const" do
|
||||
run("
|
||||
class Foo
|
||||
def initialize(@x)
|
||||
end
|
||||
|
||||
def x
|
||||
@x
|
||||
end
|
||||
end
|
||||
|
||||
A = begin
|
||||
f = Foo.new(1)
|
||||
f
|
||||
end
|
||||
|
||||
def foo
|
||||
A.x
|
||||
end
|
||||
|
||||
foo
|
||||
").to_i.should eq(1)
|
||||
end
|
||||
|
||||
it "declaring var" do
|
||||
run("
|
||||
BAR = begin
|
||||
a = 1
|
||||
while 1 == 2
|
||||
b = 2
|
||||
end
|
||||
a
|
||||
end
|
||||
class Foo
|
||||
def compile
|
||||
BAR
|
||||
end
|
||||
end
|
||||
|
||||
Foo.new.compile
|
||||
").to_i.should eq(1)
|
||||
end
|
||||
|
||||
it "initialize const that might raise an exception" do
|
||||
run("
|
||||
require \"prelude\"
|
||||
CONST = (raise \"OH NO\" if 1 == 2)
|
||||
|
||||
def doit
|
||||
CONST
|
||||
rescue
|
||||
end
|
||||
|
||||
doit.nil?
|
||||
").to_b.should be_true
|
||||
end
|
||||
end
|
||||
79
samples/Crystal/declare_var_spec.cr
Normal file
79
samples/Crystal/declare_var_spec.cr
Normal file
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env bin/crystal --run
|
||||
require "../../spec_helper"
|
||||
|
||||
describe "Type inference: declare var" do
|
||||
it "types declare var" do
|
||||
assert_type("a :: Int32") { int32 }
|
||||
end
|
||||
|
||||
it "types declare var and reads it" do
|
||||
assert_type("a :: Int32; a") { int32 }
|
||||
end
|
||||
|
||||
it "types declare var and changes its type" do
|
||||
assert_type("a :: Int32; while 1 == 2; a = 'a'; end; a") { union_of(int32, char) }
|
||||
end
|
||||
|
||||
it "declares instance var which appears in initialize" do
|
||||
result = assert_type("
|
||||
class Foo
|
||||
@x :: Int32
|
||||
end
|
||||
|
||||
Foo.new") { types["Foo"] }
|
||||
|
||||
mod = result.program
|
||||
|
||||
foo = mod.types["Foo"] as NonGenericClassType
|
||||
foo.instance_vars["@x"].type.should eq(mod.int32)
|
||||
end
|
||||
|
||||
it "declares instance var of generic class" do
|
||||
result = assert_type("
|
||||
class Foo(T)
|
||||
@x :: T
|
||||
end
|
||||
|
||||
Foo(Int32).new") do
|
||||
foo = types["Foo"] as GenericClassType
|
||||
foo_i32 = foo.instantiate([int32] of Type | ASTNode)
|
||||
foo_i32.lookup_instance_var("@x").type.should eq(int32)
|
||||
foo_i32
|
||||
end
|
||||
end
|
||||
|
||||
it "declares instance var of generic class after reopen" do
|
||||
result = assert_type("
|
||||
class Foo(T)
|
||||
end
|
||||
|
||||
f = Foo(Int32).new
|
||||
|
||||
class Foo(T)
|
||||
@x :: T
|
||||
end
|
||||
|
||||
f") do
|
||||
foo = types["Foo"] as GenericClassType
|
||||
foo_i32 = foo.instantiate([int32] of Type | ASTNode)
|
||||
foo_i32.lookup_instance_var("@x").type.should eq(int32)
|
||||
foo_i32
|
||||
end
|
||||
end
|
||||
|
||||
it "declares an instance variable in initialize" do
|
||||
assert_type("
|
||||
class Foo
|
||||
def initialize
|
||||
@x :: Int32
|
||||
end
|
||||
|
||||
def x
|
||||
@x
|
||||
end
|
||||
end
|
||||
|
||||
Foo.new.x
|
||||
") { int32 }
|
||||
end
|
||||
end
|
||||
515
samples/Crystal/transformer.cr
Normal file
515
samples/Crystal/transformer.cr
Normal file
@@ -0,0 +1,515 @@
|
||||
module Crystal
|
||||
class ASTNode
|
||||
def transform(transformer)
|
||||
transformer.before_transform self
|
||||
node = transformer.transform self
|
||||
transformer.after_transform self
|
||||
node
|
||||
end
|
||||
end
|
||||
|
||||
class Transformer
|
||||
def before_transform(node)
|
||||
end
|
||||
|
||||
def after_transform(node)
|
||||
end
|
||||
|
||||
def transform(node : Expressions)
|
||||
exps = [] of ASTNode
|
||||
node.expressions.each do |exp|
|
||||
new_exp = exp.transform(self)
|
||||
if new_exp
|
||||
if new_exp.is_a?(Expressions)
|
||||
exps.concat new_exp.expressions
|
||||
else
|
||||
exps << new_exp
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if exps.length == 1
|
||||
exps[0]
|
||||
else
|
||||
node.expressions = exps
|
||||
node
|
||||
end
|
||||
end
|
||||
|
||||
def transform(node : Call)
|
||||
if node_obj = node.obj
|
||||
node.obj = node_obj.transform(self)
|
||||
end
|
||||
transform_many node.args
|
||||
|
||||
if node_block = node.block
|
||||
node.block = node_block.transform(self)
|
||||
end
|
||||
|
||||
if node_block_arg = node.block_arg
|
||||
node.block_arg = node_block_arg.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : And)
|
||||
node.left = node.left.transform(self)
|
||||
node.right = node.right.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Or)
|
||||
node.left = node.left.transform(self)
|
||||
node.right = node.right.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : StringInterpolation)
|
||||
transform_many node.expressions
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : ArrayLiteral)
|
||||
transform_many node.elements
|
||||
|
||||
if node_of = node.of
|
||||
node.of = node_of.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : HashLiteral)
|
||||
transform_many node.keys
|
||||
transform_many node.values
|
||||
|
||||
if of_key = node.of_key
|
||||
node.of_key = of_key.transform(self)
|
||||
end
|
||||
|
||||
if of_value = node.of_value
|
||||
node.of_value = of_value.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : If)
|
||||
node.cond = node.cond.transform(self)
|
||||
node.then = node.then.transform(self)
|
||||
node.else = node.else.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Unless)
|
||||
node.cond = node.cond.transform(self)
|
||||
node.then = node.then.transform(self)
|
||||
node.else = node.else.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : IfDef)
|
||||
node.cond = node.cond.transform(self)
|
||||
node.then = node.then.transform(self)
|
||||
node.else = node.else.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : MultiAssign)
|
||||
transform_many node.targets
|
||||
transform_many node.values
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : SimpleOr)
|
||||
node.left = node.left.transform(self)
|
||||
node.right = node.right.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Def)
|
||||
transform_many node.args
|
||||
node.body = node.body.transform(self)
|
||||
|
||||
if receiver = node.receiver
|
||||
node.receiver = receiver.transform(self)
|
||||
end
|
||||
|
||||
if block_arg = node.block_arg
|
||||
node.block_arg = block_arg.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Macro)
|
||||
transform_many node.args
|
||||
node.body = node.body.transform(self)
|
||||
|
||||
if receiver = node.receiver
|
||||
node.receiver = receiver.transform(self)
|
||||
end
|
||||
|
||||
if block_arg = node.block_arg
|
||||
node.block_arg = block_arg.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : PointerOf)
|
||||
node.exp = node.exp.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : SizeOf)
|
||||
node.exp = node.exp.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : InstanceSizeOf)
|
||||
node.exp = node.exp.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : IsA)
|
||||
node.obj = node.obj.transform(self)
|
||||
node.const = node.const.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : RespondsTo)
|
||||
node.obj = node.obj.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Case)
|
||||
node.cond = node.cond.transform(self)
|
||||
transform_many node.whens
|
||||
|
||||
if node_else = node.else
|
||||
node.else = node_else.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : When)
|
||||
transform_many node.conds
|
||||
node.body = node.body.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : ImplicitObj)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : ClassDef)
|
||||
node.body = node.body.transform(self)
|
||||
|
||||
if superclass = node.superclass
|
||||
node.superclass = superclass.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : ModuleDef)
|
||||
node.body = node.body.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : While)
|
||||
node.cond = node.cond.transform(self)
|
||||
node.body = node.body.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Generic)
|
||||
node.name = node.name.transform(self)
|
||||
transform_many node.type_vars
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : ExceptionHandler)
|
||||
node.body = node.body.transform(self)
|
||||
transform_many node.rescues
|
||||
|
||||
if node_ensure = node.ensure
|
||||
node.ensure = node_ensure.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Rescue)
|
||||
node.body = node.body.transform(self)
|
||||
transform_many node.types
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Union)
|
||||
transform_many node.types
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Hierarchy)
|
||||
node.name = node.name.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Metaclass)
|
||||
node.name = node.name.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Arg)
|
||||
if default_value = node.default_value
|
||||
node.default_value = default_value.transform(self)
|
||||
end
|
||||
|
||||
if restriction = node.restriction
|
||||
node.restriction = restriction.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : BlockArg)
|
||||
node.fun = node.fun.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Fun)
|
||||
transform_many node.inputs
|
||||
|
||||
if output = node.output
|
||||
node.output = output.transform(self)
|
||||
end
|
||||
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Block)
|
||||
node.args.map! { |exp| exp.transform(self) as Var }
|
||||
node.body = node.body.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : FunLiteral)
|
||||
node.def.body = node.def.body.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : FunPointer)
|
||||
if obj = node.obj
|
||||
node.obj = obj.transform(self)
|
||||
end
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Return)
|
||||
transform_many node.exps
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Break)
|
||||
transform_many node.exps
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Next)
|
||||
transform_many node.exps
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Yield)
|
||||
if scope = node.scope
|
||||
node.scope = scope.transform(self)
|
||||
end
|
||||
transform_many node.exps
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Include)
|
||||
node.name = node.name.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Extend)
|
||||
node.name = node.name.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : RangeLiteral)
|
||||
node.from = node.from.transform(self)
|
||||
node.to = node.to.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Assign)
|
||||
node.target = node.target.transform(self)
|
||||
node.value = node.value.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Nop)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : NilLiteral)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : BoolLiteral)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : NumberLiteral)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : CharLiteral)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : StringLiteral)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : SymbolLiteral)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : RegexLiteral)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Var)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : MetaVar)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : InstanceVar)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : ClassVar)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Global)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Require)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Path)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : LibDef)
|
||||
node.body = node.body.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : FunDef)
|
||||
if body = node.body
|
||||
node.body = body.transform(self)
|
||||
end
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : TypeDef)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : StructDef)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : UnionDef)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : EnumDef)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : ExternalVar)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : IndirectRead)
|
||||
node.obj = node.obj.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : IndirectWrite)
|
||||
node.obj = node.obj.transform(self)
|
||||
node.value = node.value.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : TypeOf)
|
||||
transform_many node.expressions
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Primitive)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Not)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : TypeFilteredNode)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : TupleLiteral)
|
||||
transform_many node.exps
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Cast)
|
||||
node.obj = node.obj.transform(self)
|
||||
node.to = node.to.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : DeclareVar)
|
||||
node.var = node.var.transform(self)
|
||||
node.declared_type = node.declared_type.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Alias)
|
||||
node.value = node.value.transform(self)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : TupleIndexer)
|
||||
node
|
||||
end
|
||||
|
||||
def transform(node : Attribute)
|
||||
node
|
||||
end
|
||||
|
||||
def transform_many(exps)
|
||||
exps.map! { |exp| exp.transform(self) } if exps
|
||||
end
|
||||
end
|
||||
end
|
||||
31
samples/E/Extends.E
Normal file
31
samples/E/Extends.E
Normal file
@@ -0,0 +1,31 @@
|
||||
# from
|
||||
# http://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Objects_and_Functions
|
||||
def makeVehicle(self) {
|
||||
def vehicle {
|
||||
to milesTillEmpty() {
|
||||
return self.milesPerGallon() * self.getFuelRemaining()
|
||||
}
|
||||
}
|
||||
return vehicle
|
||||
}
|
||||
|
||||
def makeCar() {
|
||||
var fuelRemaining := 20
|
||||
def car extends makeVehicle(car) {
|
||||
to milesPerGallon() {return 19}
|
||||
to getFuelRemaining() {return fuelRemaining}
|
||||
}
|
||||
return car
|
||||
}
|
||||
|
||||
def makeJet() {
|
||||
var fuelRemaining := 2000
|
||||
def jet extends makeVehicle(jet) {
|
||||
to milesPerGallon() {return 2}
|
||||
to getFuelRemaining() {return fuelRemaining}
|
||||
}
|
||||
return jet
|
||||
}
|
||||
|
||||
def car := makeCar()
|
||||
println(`The car can go ${car.milesTillEmpty()} miles.`)
|
||||
21
samples/E/Functions.E
Normal file
21
samples/E/Functions.E
Normal file
@@ -0,0 +1,21 @@
|
||||
# from
|
||||
# http://wiki.erights.org/wiki/Walnut/Ordinary_Programming/Objects_and_Functions
|
||||
def makeCar(var name) {
|
||||
var x := 0
|
||||
var y := 0
|
||||
def car {
|
||||
to moveTo(newX,newY) {
|
||||
x := newX
|
||||
y := newY
|
||||
}
|
||||
to getX() {return x}
|
||||
to getY() {return y}
|
||||
to setName(newName) {name := newName}
|
||||
to getName() {return name}
|
||||
}
|
||||
return car
|
||||
}
|
||||
# Now use the makeCar function to make a car, which we will move and print
|
||||
def sportsCar := makeCar("Ferrari")
|
||||
sportsCar.moveTo(10,20)
|
||||
println(`The car ${sportsCar.getName()} is at X location ${sportsCar.getX()}`)
|
||||
69
samples/E/Guards.E
Normal file
69
samples/E/Guards.E
Normal file
@@ -0,0 +1,69 @@
|
||||
# from
|
||||
# http://wiki.erights.org/wiki/Walnut/Advanced_Topics/Build_your_Own_Guards
|
||||
def makeVOCPair(brandName :String) :near {
|
||||
|
||||
var myTempContents := def none {}
|
||||
|
||||
def brand {
|
||||
to __printOn(out :TextWriter) :void {
|
||||
out.print(brandName)
|
||||
}
|
||||
}
|
||||
|
||||
def ProveAuth {
|
||||
to __printOn(out :TextWriter) :void {
|
||||
out.print(`<$brandName prover>`)
|
||||
}
|
||||
to getBrand() :near { return brand }
|
||||
to coerce(specimen, optEjector) :near {
|
||||
def sealedBox {
|
||||
to getBrand() :near { return brand }
|
||||
to offerContent() :void {
|
||||
myTempContents := specimen
|
||||
}
|
||||
}
|
||||
return sealedBox
|
||||
}
|
||||
}
|
||||
def CheckAuth {
|
||||
to __printOn(out :TextWriter) :void {
|
||||
out.print(`<$brandName checker template>`)
|
||||
}
|
||||
to getBrand() :near { return brand }
|
||||
match [`get`, authList :any[]] {
|
||||
def checker {
|
||||
to __printOn(out :TextWriter) :void {
|
||||
out.print(`<$brandName checker>`)
|
||||
}
|
||||
to getBrand() :near { return brand }
|
||||
to coerce(specimenBox, optEjector) :any {
|
||||
myTempContents := null
|
||||
if (specimenBox.__respondsTo("offerContent", 0)) {
|
||||
# XXX Using __respondsTo/2 here is a kludge
|
||||
specimenBox.offerContent()
|
||||
} else {
|
||||
myTempContents := specimenBox
|
||||
}
|
||||
for auth in authList {
|
||||
if (auth == myTempContents) {
|
||||
return auth
|
||||
}
|
||||
}
|
||||
myTempContents := none
|
||||
throw.eject(optEjector,
|
||||
`Unmatched $brandName authorization`)
|
||||
}
|
||||
}
|
||||
}
|
||||
match [`__respondsTo`, [`get`, _]] {
|
||||
true
|
||||
}
|
||||
match [`__respondsTo`, [_, _]] {
|
||||
false
|
||||
}
|
||||
match [`__getAllegedType`, []] {
|
||||
null.__getAllegedType()
|
||||
}
|
||||
}
|
||||
return [ProveAuth, CheckAuth]
|
||||
}
|
||||
14
samples/E/IO.E
Normal file
14
samples/E/IO.E
Normal file
@@ -0,0 +1,14 @@
|
||||
# E sample from
|
||||
# http://wiki.erights.org/wiki/Walnut/Ordinary_Programming/InputOutput
|
||||
#File objects for hardwired files:
|
||||
def file1 := <file:myFile.txt>
|
||||
def file2 := <file:/home/marcs/myFile.txt>
|
||||
|
||||
#Using a variable for a file name:
|
||||
def filePath := "c:\\docs\\myFile.txt"
|
||||
def file3 := <file>[filePath]
|
||||
|
||||
#Using a single character to specify a Windows drive
|
||||
def file4 := <file:c:/docs/myFile.txt>
|
||||
def file5 := <c:/docs/myFile.txt>
|
||||
def file6 := <c:\docs\myFile.txt>
|
||||
9
samples/E/Promises.E
Normal file
9
samples/E/Promises.E
Normal file
@@ -0,0 +1,9 @@
|
||||
# E snippet from
|
||||
# http://wiki.erights.org/wiki/Walnut/Distributed_Computing/Promises
|
||||
when (tempVow) -> {
|
||||
#...use tempVow
|
||||
} catch prob {
|
||||
#.... report problem
|
||||
} finally {
|
||||
#....log event
|
||||
}
|
||||
18
samples/E/minChat.E
Normal file
18
samples/E/minChat.E
Normal file
@@ -0,0 +1,18 @@
|
||||
# from
|
||||
# http://wiki.erights.org/wiki/Walnut/Secure_Distributed_Computing/Auditing_minChat
|
||||
pragma.syntax("0.9")
|
||||
to send(message) {
|
||||
when (friend<-receive(message)) -> {
|
||||
chatUI.showMessage("self", message)
|
||||
} catch prob {chatUI.showMessage("system", "connection lost")}
|
||||
}
|
||||
to receive(message) {chatUI.showMessage("friend", message)}
|
||||
to receiveFriend(friendRcvr) {
|
||||
bind friend := friendRcvr
|
||||
chatUI.showMessage("system", "friend has arrived")
|
||||
}
|
||||
to save(file) {file.setText(makeURIFromObject(chatController))}
|
||||
to load(file) {
|
||||
bind friend := getObjectFromURI(file.getText())
|
||||
friend <- receiveFriend(chatController)
|
||||
}
|
||||
76
samples/GAMS/transport.gms
Normal file
76
samples/GAMS/transport.gms
Normal file
@@ -0,0 +1,76 @@
|
||||
*Basic example of transport model from GAMS model library
|
||||
|
||||
$Title A Transportation Problem (TRNSPORT,SEQ=1)
|
||||
$Ontext
|
||||
|
||||
This problem finds a least cost shipping schedule that meets
|
||||
requirements at markets and supplies at factories.
|
||||
|
||||
|
||||
Dantzig, G B, Chapter 3.3. In Linear Programming and Extensions.
|
||||
Princeton University Press, Princeton, New Jersey, 1963.
|
||||
|
||||
This formulation is described in detail in:
|
||||
Rosenthal, R E, Chapter 2: A GAMS Tutorial. In GAMS: A User's Guide.
|
||||
The Scientific Press, Redwood City, California, 1988.
|
||||
|
||||
The line numbers will not match those in the book because of these
|
||||
comments.
|
||||
|
||||
$Offtext
|
||||
|
||||
|
||||
Sets
|
||||
i canning plants / seattle, san-diego /
|
||||
j markets / new-york, chicago, topeka / ;
|
||||
Parameters
|
||||
a(i) capacity of plant i in cases
|
||||
/ seattle 350
|
||||
san-diego 600 /
|
||||
b(j) demand at market j in cases
|
||||
/ new-york 325
|
||||
chicago 300
|
||||
topeka 275 / ;
|
||||
Table d(i,j) distance in thousands of miles
|
||||
new-york chicago topeka
|
||||
seattle 2.5 1.7 1.8
|
||||
san-diego 2.5 1.8 1.4 ;
|
||||
Scalar f freight in dollars per case per thousand miles /90/ ;
|
||||
Parameter c(i,j) transport cost in thousands of dollars per case ;
|
||||
c(i,j) = f * d(i,j) / 1000 ;
|
||||
Variables
|
||||
x(i,j) shipment quantities in cases
|
||||
z total transportation costs in thousands of dollars ;
|
||||
|
||||
Positive Variable x ;
|
||||
|
||||
Equations
|
||||
cost define objective function
|
||||
supply(i) observe supply limit at plant i
|
||||
demand(j) satisfy demand at market j ;
|
||||
|
||||
cost .. z =e= sum((i,j), c(i,j)*x(i,j)) ;
|
||||
|
||||
supply(i) .. sum(j, x(i,j)) =l= a(i) ;
|
||||
|
||||
demand(j) .. sum(i, x(i,j)) =g= b(j) ;
|
||||
|
||||
Model transport /all/ ;
|
||||
|
||||
Solve transport using lp minimizing z ;
|
||||
|
||||
Display x.l, x.m ;
|
||||
|
||||
$ontext
|
||||
#user model library stuff
|
||||
Main topic Basic GAMS
|
||||
Featured item 1 Trnsport model
|
||||
Featured item 2
|
||||
Featured item 3
|
||||
Featured item 4
|
||||
Description
|
||||
Basic example of transport model from GAMS model library
|
||||
|
||||
|
||||
|
||||
$offtext
|
||||
9
samples/GLSL/SimpleLighting.gl2.frag
Normal file
9
samples/GLSL/SimpleLighting.gl2.frag
Normal file
@@ -0,0 +1,9 @@
|
||||
static const char* SimpleFragmentShader = STRINGIFY(
|
||||
|
||||
varying vec4 FrontColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_FragColor = FrontColor;
|
||||
}
|
||||
);
|
||||
48
samples/GLSL/recurse1.frag
Normal file
48
samples/GLSL/recurse1.frag
Normal file
@@ -0,0 +1,48 @@
|
||||
#version 330 core
|
||||
|
||||
// cross-unit recursion
|
||||
|
||||
void main() {}
|
||||
|
||||
// two-level recursion
|
||||
|
||||
float cbar(int);
|
||||
|
||||
void cfoo(float)
|
||||
{
|
||||
cbar(2);
|
||||
}
|
||||
|
||||
// four-level, out of order
|
||||
|
||||
void CB();
|
||||
void CD();
|
||||
void CA() { CB(); }
|
||||
void CC() { CD(); }
|
||||
|
||||
// high degree
|
||||
|
||||
void CBT();
|
||||
void CDT();
|
||||
void CAT() { CBT(); CBT(); CBT(); }
|
||||
void CCT() { CDT(); CDT(); CBT(); }
|
||||
|
||||
// not recursive
|
||||
|
||||
void norA() {}
|
||||
void norB() { norA(); }
|
||||
void norC() { norA(); }
|
||||
void norD() { norA(); }
|
||||
void norE() { norB(); }
|
||||
void norF() { norB(); }
|
||||
void norG() { norE(); }
|
||||
void norH() { norE(); }
|
||||
void norI() { norE(); }
|
||||
|
||||
// not recursive, but with a call leading into a cycle if ignoring direction
|
||||
|
||||
void norcA() { }
|
||||
void norcB() { norcA(); }
|
||||
void norcC() { norcB(); }
|
||||
void norcD() { norcC(); norcB(); } // head of cycle
|
||||
void norcE() { norcD(); } // lead into cycle
|
||||
2
samples/Groovy/script.gvy
Normal file
2
samples/Groovy/script.gvy
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env groovy
|
||||
println "Hello World"
|
||||
9
samples/Groovy/template.grt
Normal file
9
samples/Groovy/template.grt
Normal file
@@ -0,0 +1,9 @@
|
||||
html {
|
||||
head {
|
||||
component "bootstrap"
|
||||
title "Bootstrap Template"
|
||||
}
|
||||
|
||||
html {
|
||||
}
|
||||
}
|
||||
9
samples/Groovy/template.gtpl
Normal file
9
samples/Groovy/template.gtpl
Normal file
@@ -0,0 +1,9 @@
|
||||
html {
|
||||
head {
|
||||
title "Example Template"
|
||||
}
|
||||
|
||||
body {
|
||||
p "This is a quick template example"
|
||||
}
|
||||
}
|
||||
60
samples/HTML/ApiOverviewPage.st
Normal file
60
samples/HTML/ApiOverviewPage.st
Normal file
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd">
|
||||
<html>
|
||||
<head>
|
||||
$Common_meta()$
|
||||
<title>
|
||||
Android API Differences Report
|
||||
</title>
|
||||
<body>
|
||||
<div class="body">
|
||||
|
||||
$Header()$
|
||||
|
||||
|
||||
<div class="content">
|
||||
<h2>Android API Differences Report</h2>
|
||||
<p>This document details the changes in the Android framework API. It shows
|
||||
additions, modifications, and removals for packages, classes, methods, and
|
||||
fields. Each reference to an API change includes a brief description of the
|
||||
API and an explanation of the change and suggested workaround, where available.</p>
|
||||
|
||||
<p>The differences described in this report are based a comparison of the APIs
|
||||
whose versions are specified in the upper-right corner of this page. It compares a
|
||||
newer "to" API to an older "from" version, noting any changes relative to the
|
||||
older API. So, for example, indicated API removals are no longer present in the "to"
|
||||
API.</p>
|
||||
<p>For more information about the Android framework API and SDK,
|
||||
see the <a href="http://code.google.com/android/index.html" target="_top">Android product site</a>.</p>
|
||||
|
||||
$if(no_delta)$
|
||||
<h3>Congratulation!</h3>
|
||||
No differences were detected between the two provided APIs.
|
||||
$endif$
|
||||
|
||||
|
||||
$if(removed_packages)$
|
||||
$Table(name="Removed Packages", rows=removed_packages:{$it.from:ModelElementRow()$})$
|
||||
<br/>
|
||||
$endif$
|
||||
|
||||
|
||||
$if(added_packages)$
|
||||
$Table(name="Added Packages", rows=added_packages:{$it.to:PackageAddedLink()$}:SimpleTableRow())$
|
||||
<br/>
|
||||
$endif$
|
||||
|
||||
$if(changed_packages)$
|
||||
$Table(name="Changed Packages", rows=changed_packages:{$it.to:PackageChangedLink()$}:SimpleTableRow())$
|
||||
<br/>
|
||||
$endif$
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
31
samples/HTML/pages.html
Normal file
31
samples/HTML/pages.html
Normal file
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<title>Related Pages</title>
|
||||
<link href="qt.css" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class=header>
|
||||
<a class=headerLink href="index.html">Main Page</a> ·
|
||||
<a class=headerLink href="classoverview.html">Class Overview</a> ·
|
||||
<a class=headerLink href="hierarchy.html">Hierarchy</a> ·
|
||||
<a class=headerLink href="annotated.html">All Classes</a>
|
||||
</div>
|
||||
<!-- Generated by Doxygen 1.8.1.2 -->
|
||||
</div><!-- top -->
|
||||
<div class="header">
|
||||
<div class="headertitle">
|
||||
<div class="title">Related Pages</div> </div>
|
||||
</div><!--header-->
|
||||
<div class="contents">
|
||||
<div class="textblock">Here is a list of all related documentation pages:</div><div class="directory">
|
||||
<table class="directory">
|
||||
<tr id="row_0_" class="even"><td class="entry"><img src="ftv2node.png" alt="o" width="16" height="22" /><a class="el" href="classoverview.html" target="_self">Class Overview</a></td><td class="desc"></td></tr>
|
||||
<tr id="row_1_"><td class="entry"><img src="ftv2lastnode.png" alt="\" width="16" height="22" /><a class="el" href="thelayoutsystem.html" target="_self">The Layout System</a></td><td class="desc"></td></tr>
|
||||
</table>
|
||||
</div><!-- directory -->
|
||||
</div><!-- contents -->
|
||||
<div class="footer" />Generated with <a href="http://www.doxygen.org/index.html">Doxygen</a> 1.8.1.2</div>
|
||||
</body>
|
||||
</html>
|
||||
6
samples/Haskell/Hello.hs
Normal file
6
samples/Haskell/Hello.hs
Normal file
@@ -0,0 +1,6 @@
|
||||
import Data.Char
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
let hello = "hello world"
|
||||
putStrLn $ map toUpper hello
|
||||
33
samples/Haskell/Main.hs
Normal file
33
samples/Haskell/Main.hs
Normal file
@@ -0,0 +1,33 @@
|
||||
module Main where
|
||||
|
||||
import Sudoku
|
||||
import Data.Maybe
|
||||
|
||||
|
||||
sudoku :: Sudoku
|
||||
sudoku = [8, 0, 1, 3, 4, 0, 0, 0, 0,
|
||||
4, 3, 0, 8, 0, 0, 1, 0, 7,
|
||||
0, 0, 0, 0, 6, 0, 0, 0, 3,
|
||||
2, 0, 8, 0, 5, 0, 0, 0, 9,
|
||||
0, 0, 9, 0, 0, 0, 7, 0, 0,
|
||||
6, 0, 0, 0, 7, 0, 8, 0, 4,
|
||||
3, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||
1, 0, 5, 0, 0, 6, 0, 4, 2,
|
||||
0, 0, 0, 0, 2, 4, 3, 0, 8]
|
||||
|
||||
{-
|
||||
sudoku :: Sudoku
|
||||
sudoku = [8, 6, 1, 3, 4, 7, 2, 9, 5,
|
||||
4, 3, 2, 8, 9, 5, 1, 6, 7,
|
||||
9, 5, 7, 1, 6, 2, 4, 8, 3,
|
||||
2, 7, 8, 4, 5, 1, 6, 3, 9,
|
||||
5, 4, 9, 6, 8, 3, 7, 2, 1,
|
||||
6, 1, 3, 2, 7, 9, 8, 5, 4,
|
||||
3, 2, 4, 9, 1, 8, 5, 7, 6,
|
||||
1, 8, 5, 7, 3, 6, 9, 4, 2,
|
||||
7, 9, 6, 5, 2, 4, 3, 1, 8]
|
||||
-}
|
||||
main :: IO ()
|
||||
main = do
|
||||
putStrLn $ pPrint sudoku ++ "\n\n"
|
||||
putStrLn $ pPrint $ fromMaybe [] $ solve sudoku
|
||||
46
samples/Haskell/Sudoku.hs
Normal file
46
samples/Haskell/Sudoku.hs
Normal file
@@ -0,0 +1,46 @@
|
||||
module Sudoku
|
||||
(
|
||||
Sudoku,
|
||||
solve,
|
||||
isSolved,
|
||||
pPrint
|
||||
) where
|
||||
|
||||
import Data.Maybe
|
||||
import Data.List
|
||||
import Data.List.Split
|
||||
|
||||
type Sudoku = [Int]
|
||||
|
||||
solve :: Sudoku -> Maybe Sudoku
|
||||
solve sudoku
|
||||
| isSolved sudoku = Just sudoku
|
||||
| otherwise = do
|
||||
index <- elemIndex 0 sudoku
|
||||
let sudokus = [nextTest sudoku index i | i <- [1..9],
|
||||
checkRow (nextTest sudoku index i) index,
|
||||
checkColumn (nextTest sudoku index i) index,
|
||||
checkBox (nextTest sudoku index i) index]
|
||||
listToMaybe $ mapMaybe solve sudokus
|
||||
where nextTest sudoku index i = take index sudoku ++ [i] ++ drop (index+1) sudoku
|
||||
checkRow sudoku index = (length $ getRow sudoku index) == (length $ nub $ getRow sudoku index)
|
||||
checkColumn sudoku index = (length $ getColumn sudoku index) == (length $ nub $ getColumn sudoku index)
|
||||
checkBox sudoku index = (length $ getBox sudoku index) == (length $ nub $ getBox sudoku index)
|
||||
getRow sudoku index = filter (/=0) $ (chunksOf 9 sudoku) !! (quot index 9)
|
||||
getColumn sudoku index = filter (/=0) $ (transpose $ chunksOf 9 sudoku) !! (mod index 9)
|
||||
getBox sudoku index = filter (/=0) $ (map concat $ concatMap transpose $ chunksOf 3 $ map (chunksOf 3) $ chunksOf 9 sudoku)
|
||||
!! (3 * (quot index 27) + (quot (mod index 9) 3))
|
||||
|
||||
isSolved :: Sudoku -> Bool
|
||||
isSolved sudoku
|
||||
| product sudoku == 0 = False
|
||||
| map (length . nub) sudokuRows /= map length sudokuRows = False
|
||||
| map (length . nub) sudokuColumns /= map length sudokuColumns = False
|
||||
| map (length . nub) sudokuBoxes /= map length sudokuBoxes = False
|
||||
| otherwise = True
|
||||
where sudokuRows = chunksOf 9 sudoku
|
||||
sudokuColumns = transpose sudokuRows
|
||||
sudokuBoxes = map concat $ concatMap transpose $ chunksOf 3 $ map (chunksOf 3) $ chunksOf 9 sudoku
|
||||
|
||||
pPrint :: Sudoku -> String
|
||||
pPrint sudoku = intercalate "\n" $ map (intercalate " " . map show) $ chunksOf 9 sudoku
|
||||
6
samples/Inform 7/Trivial Extension.i7x
Normal file
6
samples/Inform 7/Trivial Extension.i7x
Normal file
@@ -0,0 +1,6 @@
|
||||
Version 1 of Trivial Extension by Andrew Plotkin begins here.
|
||||
|
||||
A cow is a kind of animal. A cow can be purple.
|
||||
|
||||
Trivial Extension ends here.
|
||||
|
||||
12
samples/Inform 7/story.ni
Normal file
12
samples/Inform 7/story.ni
Normal file
@@ -0,0 +1,12 @@
|
||||
"Test Case" by Andrew Plotkin.
|
||||
|
||||
Include Trivial Extension by Andrew Plotkin.
|
||||
|
||||
The Kitchen is a room.
|
||||
|
||||
[This kitchen is modelled after the one in Zork, although it lacks the detail to establish this to the player.]
|
||||
|
||||
A purple cow called Gelett is in the Kitchen.
|
||||
|
||||
Instead of examining Gelett:
|
||||
say "You'd rather see than be one."
|
||||
46
samples/Isabelle/HelloWorld.thy
Normal file
46
samples/Isabelle/HelloWorld.thy
Normal file
@@ -0,0 +1,46 @@
|
||||
theory HelloWorld
|
||||
imports Main
|
||||
begin
|
||||
|
||||
section{*Playing around with Isabelle*}
|
||||
|
||||
text{* creating a lemma with the name hello_world*}
|
||||
lemma hello_world: "True" by simp
|
||||
|
||||
(*inspecting it*)
|
||||
thm hello_world
|
||||
|
||||
text{* defining a string constant HelloWorld *}
|
||||
|
||||
definition HelloWorld :: "string" where
|
||||
"HelloWorld \<equiv> ''Hello World!''"
|
||||
|
||||
(*reversing HelloWorld twice yilds HelloWorld again*)
|
||||
theorem "rev (rev HelloWorld) = HelloWorld"
|
||||
by (fact List.rev_rev_ident)
|
||||
|
||||
text{*now we delete the already proven List.rev_rev_ident lema and show it by hand*}
|
||||
declare List.rev_rev_ident[simp del]
|
||||
hide_fact List.rev_rev_ident
|
||||
|
||||
(*It's trivial since we can just 'execute' it*)
|
||||
corollary "rev (rev HelloWorld) = HelloWorld"
|
||||
apply(simp add: HelloWorld_def)
|
||||
done
|
||||
|
||||
text{*does it hold in general?*}
|
||||
theorem rev_rev_ident:"rev (rev l) = l"
|
||||
proof(induction l)
|
||||
case Nil thus ?case by simp
|
||||
next
|
||||
case (Cons l ls)
|
||||
assume IH: "rev (rev ls) = ls"
|
||||
have "rev (l#ls) = (rev ls) @ [l]" by simp
|
||||
hence "rev (rev (l#ls)) = rev ((rev ls) @ [l])" by simp
|
||||
also have "\<dots> = [l] @ rev (rev ls)" by simp
|
||||
finally show "rev (rev (l#ls)) = l#ls" using IH by simp
|
||||
qed
|
||||
|
||||
corollary "\<forall>(l::string). rev (rev l) = l" by(fastforce intro: rev_rev_ident)
|
||||
|
||||
end
|
||||
24
samples/JavaScript/helloHanaEndpoint.xsjs
Normal file
24
samples/JavaScript/helloHanaEndpoint.xsjs
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
invoke endpoint by calling in a browser:
|
||||
http://<hanaserveradress>:<xsengineport(usually 8000)>/<path>/<to>/<endpoint>/helloHanaMath.xsjslib?x=4&y=2
|
||||
e.g.:
|
||||
http://192.168.178.20:8000/geekflyer/linguist/helloHanaEndpoint.xsjs?x=4&y=2
|
||||
*/
|
||||
|
||||
var hanaMath = $.import("./helloHanaMath.xsjslib");
|
||||
|
||||
var x = parseFloat($.request.parameters.get("x"));
|
||||
var y = parseFloat($.request.parameters.get("y"));
|
||||
|
||||
|
||||
var result = hanaMath.multiply(x, y);
|
||||
|
||||
var output = {
|
||||
title: "Hello HANA XS - do some simple math",
|
||||
input: {x: x, y: y},
|
||||
result: result
|
||||
};
|
||||
|
||||
$.response.contentType = "application/json";
|
||||
$.response.statusCode = $.net.http.OK;
|
||||
$.response.setBody(JSON.stringify(output));
|
||||
9
samples/JavaScript/helloHanaMath.xsjslib
Normal file
9
samples/JavaScript/helloHanaMath.xsjslib
Normal file
@@ -0,0 +1,9 @@
|
||||
/* simple hana xs demo library, which can be used by multiple endpoints */
|
||||
|
||||
function multiply(x, y) {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
function add(x, y) {
|
||||
return x + y;
|
||||
}
|
||||
7
samples/JavaScript/intro.js.frag
Normal file
7
samples/JavaScript/intro.js.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
(function(window, angular) {
|
||||
|
||||
Array.prototype.last = function() {
|
||||
return this[this.length-1];
|
||||
};
|
||||
|
||||
var app = angular.module('ConwayGameOfLife', []);
|
||||
3
samples/JavaScript/outro.js.frag
Normal file
3
samples/JavaScript/outro.js.frag
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
})(window, window.angular);
|
||||
|
||||
8
samples/Kit/demo.kit
Normal file
8
samples/Kit/demo.kit
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- $pageTitle: The Kit Language -->
|
||||
|
||||
<section>
|
||||
<h1><!-- $pageTitle --></h1>
|
||||
<p>
|
||||
<!-- @include "loremipsum" -->
|
||||
</p>
|
||||
</section>
|
||||
59
samples/Latte/layout.latte
Normal file
59
samples/Latte/layout.latte
Normal file
@@ -0,0 +1,59 @@
|
||||
{**
|
||||
* @param string $basePath web base path
|
||||
* @param string $robots tell robots how to index the content of a page (optional)
|
||||
* @param array $flashes flash messages
|
||||
*}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<meta name="robots" content="{$robots}" n:ifset="$robots">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>{ifset $title}{$title} › {/ifset}Translation report</title>
|
||||
|
||||
<link rel="stylesheet" media="screen,projection,tv" href="{$cdnUrl}/css/style.css?v={$cssHash}">
|
||||
<link rel="shortcut icon" href="{$cdnUrl}/favicon.png">
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
<script n:syntax="off">
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-33892654-4', 'khanovaskola.cz');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{block #head}{/block}
|
||||
</head>
|
||||
|
||||
<body class="amara-guest history-empty">
|
||||
<script> document.documentElement.className+=' js' </script>
|
||||
|
||||
{block #navbar}
|
||||
{include _navbar.latte}
|
||||
{/block}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2" n:inner-foreach="$flashes as $flash">
|
||||
{include _flash.latte, flash => $flash}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{include #content}
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
</footer>
|
||||
|
||||
<script src="{$cdnUrl}/js/compiled.js?v={$jsHash}"></script>
|
||||
{block #scripts}{/block}
|
||||
</body>
|
||||
</html>
|
||||
243
samples/Latte/template.latte
Normal file
243
samples/Latte/template.latte
Normal file
@@ -0,0 +1,243 @@
|
||||
{var $title => "⚐ {$new->title}"}
|
||||
{define author}
|
||||
<a n:href="Author: authorId => $author->id" class="black">
|
||||
<img src="{$author->avatar}" width="32" height="32" class="img-rounded">
|
||||
<span class="{$class}">{$author->name|trim}</span>
|
||||
</a>
|
||||
<span data-toggle="tooltip" title="Total time {$author->shortName} translated on all videos.">
|
||||
{$author->estimatedTimeTranslated|secondsToTime}{*
|
||||
*}</span>{if $author->joined}, {/if}
|
||||
{if $author->joined}joined {$author->joined|timeAgo}{/if}{*
|
||||
*}{ifset $postfix}, {$postfix}{/ifset}
|
||||
{/define}
|
||||
{block #scripts}
|
||||
<script src="{$amaraCallbackLink}"></script>
|
||||
{/block}
|
||||
{block #content}
|
||||
|
||||
{if isset($old)}
|
||||
<h1>Diffing revision #{$old->revision} and #{$new->revision}</h1>
|
||||
{else}
|
||||
<h1>First revision</h1>
|
||||
{/if}
|
||||
|
||||
{var $editor = $user->loggedIn && $new->language === 'cs'}
|
||||
{var $rev = $new->video->siteRevision}
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<p>
|
||||
published <b>{$new->publishedAt|timeAgo}</b>{*
|
||||
*}{ifset $old},
|
||||
<span>
|
||||
{$new->textChange * 100|number} % text change{*
|
||||
*}</span>{*
|
||||
*}{if $new->timeChange},
|
||||
<span>
|
||||
{$new->timeChange * 100|number} % timing change
|
||||
</span>
|
||||
{/if}
|
||||
{/ifset}
|
||||
</p>
|
||||
{cache $new->id, expires => '+4 hours'}
|
||||
<p>
|
||||
{if isset($old) && $old->author->name !== $new->author->name}
|
||||
{include author, author => $old->author, class => 'author-old'}
|
||||
—
|
||||
{include author, author => $new->author, class => 'author-new'}
|
||||
{elseif isset($old)}
|
||||
{include author, author => $new->author, class => 'author-new', postfix => 'authored both revisions'}
|
||||
{else}
|
||||
{include author, author => $new->author, class => 'author-new'}
|
||||
{/if}
|
||||
</p>
|
||||
{/cache}
|
||||
|
||||
{var $threshold = 10}
|
||||
{cache $new->id}
|
||||
{var $done = $new->timeTranslated}
|
||||
{var $outOf = $new->video->canonicalTimeTranslated}
|
||||
{if $outOf}
|
||||
<p n:if="$outOf > $done + $threshold" class="alert alert-warning">
|
||||
Only {$done|time} translated out of {$outOf|time},
|
||||
{(1-$done/$outOf) * 100|number} % ({$outOf - $done|time}) left
|
||||
</p>
|
||||
<p n:if="$outOf <= $done + $threshold" class="alert alert-success">
|
||||
Seems complete: {$done|time} translated out of {$outOf|time}
|
||||
</p>
|
||||
{elseif $done}
|
||||
<p n:if="$outOf <= $done + $threshold" class="alert alert-info">
|
||||
Although {$done|time} is translated, there are no English subtitles for comparison.
|
||||
</p>
|
||||
{/if}
|
||||
{/cache}
|
||||
|
||||
{if $editor}
|
||||
{var $ksid = $new->video->siteId}
|
||||
{if $ksid}
|
||||
<a href="https://khanovaskola.cz/watch/default/?vid={$ksid}">
|
||||
Video on khanovaskola.cz
|
||||
{if $new->revision === $rev}
|
||||
(on this revision)
|
||||
{elseif $new->revision > $rev}
|
||||
(on older revision #{$rev})
|
||||
{else}
|
||||
(on newer revision #{$rev})
|
||||
{/if}
|
||||
</a>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<h3 class="diff">{$diffs->title|noescape}</h3>
|
||||
<div class="lead diff">{$diffs->description|noescape}</div>
|
||||
<div class="diff subtitles">
|
||||
<div n:foreach="$diffs->text as $line" class="line" data-context="{$line->context}">
|
||||
{$line->text|noescape}
|
||||
</div>
|
||||
<div class="splitter template">
|
||||
<span data-toggle="tooltip" data-placement="bottom" title="Expand">
|
||||
<i class="fa fa-sort"></i> <i class="fa fa-ellipsis-h"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{if $editor}
|
||||
{if $new->approved}
|
||||
<span class="text-success">
|
||||
Revision has been approved{if $new->editor} by {$new->editor->name}{/if}.
|
||||
</span>
|
||||
<a n:href="amaraEdit, amaraId => $new->video->amaraId" n:block="editButton" class="btn btn-default">
|
||||
<i class="fa fa-edit"></i>
|
||||
Edit on Amara
|
||||
</a>
|
||||
<a n:href="khanAcademy" n:block="kaButton" class="btn btn-link">
|
||||
on Khan Academy
|
||||
</a>
|
||||
|
||||
{elseif $new->incomplete}
|
||||
<span class="text-info">
|
||||
Revision has been marked as incomplete by {if $new->editor}{$new->editor->name}{/if}.
|
||||
</span>
|
||||
{include editButton}
|
||||
{include kaButton}
|
||||
|
||||
{* else $new->status === UNSET: *}
|
||||
{elseif $new->video->siteId}
|
||||
<div class="btn-group">
|
||||
<a n:href="approve!" class="btn btn-default">
|
||||
<i class="fa fa-thumbs-o-up"></i>
|
||||
Approve (update kš)
|
||||
</a>
|
||||
<a n:href="markIncomplete!" class="btn btn-default">
|
||||
<i class="fa fa-thumbs-o-down"></i>
|
||||
Mark as incomplete
|
||||
</a>
|
||||
{include editButton}
|
||||
</div>
|
||||
{include kaButton}
|
||||
|
||||
{else}
|
||||
<div class="btn-group">
|
||||
<a n:href="redirectToAdd!" class="btn btn-default">
|
||||
<i class="fa fa-plus-square-o"></i>
|
||||
Approve (add to kš)
|
||||
</a>
|
||||
<a n:href="markIncomplete!" class="btn btn-default">
|
||||
<i class="fa fa-thumbs-o-down"></i>
|
||||
Mark as incomplete
|
||||
</a>
|
||||
{include editButton}
|
||||
</div>
|
||||
{include kaButton}
|
||||
<div>
|
||||
<h5>Filed under category:</h5>
|
||||
{foreach $new->video->categories as $list}
|
||||
— {$list|implode:' › '}{sep}<br>{/sep}
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<h4>All revisions:</h4>
|
||||
<table class="table table-condensed revisions">
|
||||
{foreach $new->video->getRevisionsIn($new->language) as $revision}
|
||||
<tr n:class="$revision->revision === $new->revision ? 'active'">
|
||||
<td class="revision">
|
||||
<a n:href="this, revId => $revision->id">#{$revision->revision}</a>
|
||||
</td>
|
||||
<td>
|
||||
<a n:href="Author: authorId => $revision->author->id" class="black">
|
||||
<img src="{$revision->author->avatar}" width="32" height="32" class="img-rounded">
|
||||
{$revision->author->name}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="secondary">
|
||||
{$revision->publishedAt|timeAgo}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
{* vars $outOf, $threshold already set *}
|
||||
{default $outOf = $new->video->canonicalTimeTranslated}
|
||||
{if $outOf} {* ignore if canonical time not set *}
|
||||
{var $done = $revision->timeTranslated}
|
||||
<span n:if="$outOf > $done + $threshold" class="text-warning"
|
||||
data-toggle="tooltip" title="Percent of lines translated">
|
||||
{$done/$outOf * 100|number} %
|
||||
</span>
|
||||
<span n:if="$outOf <= $done + $threshold" class="text-success">
|
||||
~100 %
|
||||
</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
{if $revision->incomplete || $revision->approved}
|
||||
{var $i = $revision->incomplete}
|
||||
<span n:class="$i ? 'text-warning' : 'text-success'">
|
||||
{if $i}incomplete{else}approved{/if}
|
||||
</span>
|
||||
{/if}
|
||||
</td>
|
||||
{if $user->loggedIn && $revision->comments->count()}
|
||||
</tr>
|
||||
<tr class="row-noborder">
|
||||
<td colspan="99">
|
||||
<table class="comments">
|
||||
<tr n:foreach="$revision->comments as $comment">
|
||||
<td class="col-comment-author">
|
||||
<span class="secondary" data-toggle="tooltip" data-placement="left"
|
||||
title="{$comment->createdAt|timeAgo}">
|
||||
{$comment->user->name}:
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>
|
||||
{$comment->text}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
{/if}
|
||||
{if $user->loggedIn && $new->id === $revision->id}
|
||||
</tr>
|
||||
<tr class="row-noborder">
|
||||
<td colspan="99">
|
||||
{form commentForm}
|
||||
<div class="input-group comment-input">
|
||||
{input text, class => "form-control", placeholder => "Comment this revision (only visible to other editors)"}
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" n:name="save">
|
||||
<i class="fa fa-share"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
{/form}
|
||||
</td>
|
||||
{/if}
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
104
samples/Liquid/layout.liquid
Normal file
104
samples/Liquid/layout.liquid
Normal file
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>{{shop.name}} - {{page_title}}</title>
|
||||
|
||||
{{ 'textile.css' | global_asset_url | stylesheet_tag }}
|
||||
{{ 'lightbox/v204/lightbox.css' | global_asset_url | stylesheet_tag }}
|
||||
|
||||
{{ 'prototype/1.6/prototype.js' | global_asset_url | script_tag }}
|
||||
{{ 'scriptaculous/1.8.2/scriptaculous.js' | global_asset_url | script_tag }}
|
||||
{{ 'lightbox/v204/lightbox.js' | global_asset_url | script_tag }}
|
||||
{{ 'option_selection.js' | shopify_asset_url | script_tag }}
|
||||
|
||||
{{ 'layout.css' | asset_url | stylesheet_tag }}
|
||||
{{ 'shop.js' | asset_url | script_tag }}
|
||||
|
||||
{{ content_for_header }}
|
||||
</head>
|
||||
|
||||
<body id="page-{{template}}">
|
||||
|
||||
<p class="hide"><a href="#rightsiders">Skip to navigation.</a></p>
|
||||
<!-- mini cart -->
|
||||
{% if cart.item_count > 0 %}
|
||||
<div id="minicart" style="display:none;"><div id="minicart-inner">
|
||||
<div id="minicart-items">
|
||||
<h2>There {{ cart.item_count | pluralize: 'is', 'are' }} {{ cart.item_count }} {{ cart.item_count | pluralize: 'item', 'items' }} in <a href="/cart" title="View your cart">your cart</a>!</h2><h4 style="font-size: 16px; margin: 0 0 10px 0; padding: 0;">Your subtotal is {{ cart.total_price | money }}.</h4>
|
||||
{% for item in cart.items %}
|
||||
<div class="thumb">
|
||||
<div class="prodimage"><a href="{{item.product.url}}" onMouseover="tooltip('{{ item.quantity }} x {{ item.title }} ({{ item.variant.title }})', 200)"; onMouseout="hidetooltip()"><img src="{{ item.product.featured_image | product_img_url: 'thumb' }}" /></a></div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<br style="clear:both;" />
|
||||
</div></div>
|
||||
{% endif %}
|
||||
|
||||
<div id="container">
|
||||
<div id="header">
|
||||
<!-- Begin Header -->
|
||||
<h1 id="logo"><a href="/" title="Go Home">{{shop.name}}</a></h1>
|
||||
<div id="cartlinks">
|
||||
{% if cart.item_count > 0 %}
|
||||
<h2 id="cartcount"><a href="/cart" onMouseover="tooltip('There {{ cart.item_count | pluralize: 'is', 'are' }} {{ cart.item_count }} {{ cart.item_count | pluralize: 'item', 'items' }} in your cart!', 200)"; onMouseout="hidetooltip()">{{ cart.item_count }} {{ cart.item_count | pluralize: 'thing', 'things' }}!</a></h2>
|
||||
<a href="/cart" id="minicartswitch" onclick="superSwitch(this, 'minicart', 'Close Mini Cart'); return false;" id="cartswitch">View Mini Cart ({{ cart.total_price | money }})</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<!-- End Header -->
|
||||
|
||||
</div>
|
||||
<hr />
|
||||
<div id="main">
|
||||
|
||||
<div id="content">
|
||||
<div id="innercontent">
|
||||
{{ content_for_layout }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div id="rightsiders">
|
||||
|
||||
<ul class="rightlinks">
|
||||
{% for link in linklists.main-menu.links %}
|
||||
<li>{{ link.title | link_to: link.url }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% if tags %}
|
||||
<ul class="rightlinks">
|
||||
{% for tag in collection.tags %}
|
||||
<li><span class="add-link">{{ '+' | link_to_add_tag: tag }}</span>{{ tag | highlight_active_tag | link_to_tag: tag }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<ul class="rightlinks">
|
||||
{% for link in linklists.footer.links %}
|
||||
<li>{{ link.title | link_to: link.url }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<hr /><br style="clear:both;" />
|
||||
|
||||
<div id="footer">
|
||||
<div class="footerinner">
|
||||
All prices are in {{ shop.currency }}.
|
||||
Powered by <a href="http://www.shopify.com" title="Shopify, Hosted E-Commerce">Shopify</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tooltip"></div>
|
||||
<img id="pointer" src="{{ 'arrow2.gif' | asset_url }}" />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
70
samples/Liquid/template.liquid
Normal file
70
samples/Liquid/template.liquid
Normal file
@@ -0,0 +1,70 @@
|
||||
<h3>We have wonderful products!</h3>
|
||||
<ul id="products">
|
||||
<div id="productpage">
|
||||
<div id="productimages"><div id="productimages-top"><div id="productimages-bottom">
|
||||
{% for image in product.images %}
|
||||
{% if forloop.first %}
|
||||
<a href="{{ image | product_img_url: 'large' }}" class="productimage" rel="lightbox">
|
||||
<img src="{{ image | product_img_url: 'medium'}}" alt="{{product.title | escape }}" />
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ image | product_img_url: 'large' }}" class="productimage-small" rel="lightbox">
|
||||
<img src="{{ image | product_img_url: 'small'}}" alt="{{product.title | escape }}" />
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div></div></div>
|
||||
|
||||
<h2>{{ product.title }}</h2>
|
||||
|
||||
<ul id="details" class="hlist">
|
||||
<li>Vendor: {{ product.vendor | link_to_vendor }}</li>
|
||||
<li>Type: {{ product.type | link_to_type }}</li>
|
||||
</ul>
|
||||
|
||||
<small>{{ product.price_min | money }}{% if product.price_varies %} - {{ product.price_max | money }}{% endif %}</small>
|
||||
|
||||
<div id="variant-add">
|
||||
<form action="/cart/add" method="post">
|
||||
|
||||
<select id="variant-select" name="id" class="product-info-options">
|
||||
{% for variant in product.variants %}
|
||||
<option value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<div id="price-field" class="price"></div>
|
||||
|
||||
<div style="text-align:center;"><input type="image" name="add" value="Add to Cart" id="add" src="{{ 'addtocart.gif' | asset_url }}" /></div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="description textile">
|
||||
{{ product.description }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
<!--
|
||||
// prototype callback for multi variants dropdown selector
|
||||
var selectCallback = function(variant, selector) {
|
||||
if (variant && variant.available == true) {
|
||||
// selected a valid variant
|
||||
$('add').removeClassName('disabled'); // remove unavailable class from add-to-cart button
|
||||
$('add').disabled = false; // reenable add-to-cart button
|
||||
$('price-field').innerHTML = Shopify.formatMoney(variant.price, "{{shop.money_with_currency_format}}"); // update price field
|
||||
} else {
|
||||
// variant doesn't exist
|
||||
$('add').addClassName('disabled'); // set add-to-cart button to unavailable class
|
||||
$('add').disabled = true; // disable add-to-cart button
|
||||
$('price-field').innerHTML = (variant) ? "Sold Out" : "Unavailable"; // update price-field message
|
||||
}
|
||||
};
|
||||
|
||||
// initialize multi selector for product
|
||||
Event.observe(document, 'dom:loaded', function() {
|
||||
new Shopify.OptionSelectors("variant-select", { product: {{ product | json }}, onVariantSelected: selectCallback });
|
||||
});
|
||||
-->
|
||||
</script>
|
||||
</ul>
|
||||
35
samples/MTML/categories_to_columns.mtml
Normal file
35
samples/MTML/categories_to_columns.mtml
Normal file
@@ -0,0 +1,35 @@
|
||||
<$mt:Var name="num_cols" value="6"$>
|
||||
<$mt:Var name="index" value="0"$>
|
||||
<mt:Categories>
|
||||
<$mt:Var name="index" op="++" setvar="index"$>
|
||||
<mt:SetVarBlock name="categories{$index}">
|
||||
<a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel remove_html="1"$></a>
|
||||
</mt:SetVarBlock>
|
||||
</mt:Categories>
|
||||
<$mt:Var name="categories" function="count" setvar="cat_count"$>
|
||||
<$mt:Var name="cat_count" op="%" value="$num_cols" setvar="modulus"$>
|
||||
<mt:If name="modulus" gt="0">
|
||||
<$mt:Var name="cat_count" op="-" value="$modulus" setvar="cat_count_minus_mod"$>
|
||||
<$mt:Var name="cat_count_minus_mod" op="/" value="$num_cols" setvar="cats_per_col"$>
|
||||
<$mt:Var name="cats_per_col" op="+" value="1" setvar="cats_per_col"$>
|
||||
<mt:Else>
|
||||
<$mt:Var name="cat_count" op="/" value="$num_cols" setvar="cats_per_col"$>
|
||||
</mt:If>
|
||||
<mt:SetVarTemplate name="for_inner">
|
||||
<$mt:Var name="index" op="++" setvar="index"$>
|
||||
<mt:Unless name="index" gt="$cat_count">
|
||||
<$mt:Var name="categories{$index}"$>
|
||||
</mt:Unless>
|
||||
</mt:SetVarTemplate>
|
||||
|
||||
<$mt:Var name="index" value="0"$>
|
||||
<$mt:Var name="col_num" value="1"$>
|
||||
<mt:For from="1" to="$num_cols">
|
||||
<div class="col<$mt:Var name="col_num"$>">
|
||||
<mt:For from="1" to="$cats_per_col">
|
||||
<$mt:Var name="for_inner"$>
|
||||
</mt:For>
|
||||
</div>
|
||||
<$mt:Var name="col_num" op="++" setvar="col_num"$>
|
||||
</mt:For>
|
||||
|
||||
232
samples/Mathematica/MiscCalculations.nb
Normal file
232
samples/Mathematica/MiscCalculations.nb
Normal file
@@ -0,0 +1,232 @@
|
||||
(* Content-type: application/vnd.wolfram.mathematica *)
|
||||
|
||||
(*** Wolfram Notebook File ***)
|
||||
(* http://www.wolfram.com/nb *)
|
||||
|
||||
(* CreatedBy='Mathematica 9.0' *)
|
||||
|
||||
(*CacheID: 234*)
|
||||
(* Internal cache information:
|
||||
NotebookFileLineBreakTest
|
||||
NotebookFileLineBreakTest
|
||||
NotebookDataPosition[ 157, 7]
|
||||
NotebookDataLength[ 7164, 223]
|
||||
NotebookOptionsPosition[ 6163, 182]
|
||||
NotebookOutlinePosition[ 6508, 197]
|
||||
CellTagsIndexPosition[ 6465, 194]
|
||||
WindowFrame->Normal*)
|
||||
|
||||
(* Beginning of Notebook Content *)
|
||||
Notebook[{
|
||||
|
||||
Cell[CellGroupData[{
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"Solve", "[",
|
||||
RowBox[{
|
||||
RowBox[{"y", "'"}], "\[Equal]", " ", "xy"}], "]"}],
|
||||
"\[IndentingNewLine]"}]], "Input",
|
||||
CellChangeTimes->{{3.6112716342092056`*^9, 3.6112716549793935`*^9}}],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{"{",
|
||||
RowBox[{"xy", "\[Rule]",
|
||||
SuperscriptBox["y", "\[Prime]",
|
||||
MultilineFunction->None]}], "}"}], "}"}]], "Output",
|
||||
CellChangeTimes->{3.6112716579295626`*^9}]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Log", "[",
|
||||
RowBox[{"Sin", "[", "38", "]"}], "]"}]], "Input",
|
||||
CellChangeTimes->{{3.611271663920905*^9, 3.6112716759275913`*^9}}],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Log", "[",
|
||||
RowBox[{"Sin", "[", "38", "]"}], "]"}]], "Output",
|
||||
CellChangeTimes->{3.611271678256725*^9}]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"N", "[",
|
||||
RowBox[{"Log", "[",
|
||||
RowBox[{"Sin", "[", "38", "]"}], "]"}], "]"}]], "Input",
|
||||
NumberMarks->False],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"-", "1.2161514009320473`"}]], "Output",
|
||||
CellChangeTimes->{3.611271682061942*^9}]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Abs", "[",
|
||||
RowBox[{"-", "1.2161514009320473`"}], "]"}]], "Input",
|
||||
NumberMarks->False],
|
||||
|
||||
Cell[BoxData["1.2161514009320473`"], "Output",
|
||||
CellChangeTimes->{3.6112716842780695`*^9}]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"RealDigits", "[", "1.2161514009320473`", "]"}]], "Input",
|
||||
NumberMarks->False],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
"1", ",", "2", ",", "1", ",", "6", ",", "1", ",", "5", ",", "1", ",", "4",
|
||||
",", "0", ",", "0", ",", "9", ",", "3", ",", "2", ",", "0", ",", "4",
|
||||
",", "7"}], "}"}], ",", "1"}], "}"}]], "Output",
|
||||
CellChangeTimes->{3.611271685319129*^9}]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"Graph", "[",
|
||||
RowBox[{"Log", "[", "x", "]"}], "]"}], "\[IndentingNewLine]"}]], "Input",
|
||||
CellChangeTimes->{{3.611271689258354*^9, 3.611271702038085*^9}}],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"Graph", "[",
|
||||
RowBox[{"Log", "[", "x", "]"}], "]"}]], "Output",
|
||||
CellChangeTimes->{3.611271704295214*^9}]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[""], "Input",
|
||||
CellChangeTimes->{{3.611271712769699*^9, 3.6112717423153887`*^9}}],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"Plot", "[",
|
||||
RowBox[{
|
||||
RowBox[{"Log", "[", "x", "]"}], ",", " ",
|
||||
RowBox[{"{",
|
||||
RowBox[{"x", ",", " ", "0", ",", " ", "10"}], "}"}]}], "]"}],
|
||||
"\[IndentingNewLine]"}]], "Input",
|
||||
CellChangeTimes->{{3.6112717573482485`*^9, 3.6112717747822456`*^9}}],
|
||||
|
||||
Cell[BoxData[
|
||||
GraphicsBox[{{}, {},
|
||||
{Hue[0.67, 0.6, 0.6], LineBox[CompressedData["
|
||||
1:eJwVzXs81Pkex/GZH7XlsutSQprwqxTSZVfJGp9P6UYqlyxHUhTaLrq4JpVK
|
||||
0SHRisGWjYiEbHSvb+Q27rllmYwaY6JpwxgZTI7zx/vxejz/eht4H3PyoRgM
|
||||
Rsj0/t+1MEPjP1Zc8O6L0tCYkJERTokxP5YLLR+MQy2qZWSzX62gWcaFn9s7
|
||||
5sVFyohY4ZvLs5Ya6AheLQxnyIgFe4fllag6yH4zayhMcYw0FU5SRl8bweS/
|
||||
wyVFa0aJBsz2VDVrAl8V299DGKPk1yWJllEHmqD42vuI4RopiRvJlYS9bYLZ
|
||||
a2c4j3pJyS8JbT7eeW/By6ht44vkEXKuxtRu1d4WOB5QmStjSUhO0eMleTda
|
||||
4EZtHmU5PEyaORsUFte1QFHRg6WjFcNkkZ/bC+11rVC0s8n9nf8wqVGINGNo
|
||||
tkFRzD3HsYohosXu0misbAdxXml1VdQgKSi80nXErBNo/oP47aliMqAxEGvn
|
||||
1QlVgoRvezzExCjYznppYifkn+K6CVli8peV8m2BrBNM20LljlmfyXVurK97
|
||||
RRfcVCpPCXg8QIIF14a2eLyHn6Y4909//UTSlWsvqm/qge1fVjduzhISa/Zp
|
||||
jwjPHvCM6ZD7BQgJz9/E/GtIDyRsSj3Svl5ItJtj+uru9cBdE2PXZH4vSeDY
|
||||
20arfYAT6Z3e8axecnFxw49TXR/gU5X5vDu5H4kfvE0RnxSAsqvDMcduPmFk
|
||||
jD7rihGA7RmZ5qlYPuEo6vFq7gigR67QPetXPqnm+rJy2wUA0hVVHindZOmu
|
||||
yQwfy17Y4OU185n7e/LpoNH9bqYQPPrPvwn+2kkOXT/zqim+DzJ72WEzdrcT
|
||||
SprBJ7l9UD/Fag2c005SXasZhWV9kH51Z/aqhjZSo6dpc3WkD4L1tqolbGgj
|
||||
JndzqmzdRPD67PLxVrNWIn7e0lS28BMs6Ba9FM1pJv7CZYLign6IeWFYmrqk
|
||||
jvR4/jOrlNsPoqNsieZftcS5I9qsvrcf8tnmIzq6tcSiVnRKqDsALqbKTVU/
|
||||
1RCFoiw1ragBULG3LYphVhNOuIF1yN7PkFMpYVXI35BSTZ2UdWpfgMls07e/
|
||||
84QoGUQa8S0GgVn/55MIdixUWyWsOLtpEAIiTazYlglw2e3W2gVOg5BMOVFO
|
||||
zolAxT/ZsvvwIJAvj7SczqbC+Hex37ubgxD8udJ0tkcmfOa55DRSQ8DwsFzc
|
||||
6lkIdRyjZa/rhsAywLBSze45xKnVGt/eJwFLB1UN7sVq8O7aRRTqRsFbq7Mr
|
||||
JqcdTlREeh8zGoeOsKZ1bgF8KDqu4qxtK4c/T0q26boJ4PbpwwMrXRn4N9vd
|
||||
qamzDy6kTzqOiJmo6OOuteZtPzBaevBFmALy6nNqfwkTw5JA39BdxjPwSH3B
|
||||
vlWGX6FXmvyb8suZeCtkhRV5NAh2wkNnrp+YhaOXrkQMdg/Bjt54ExZLCdti
|
||||
v+y2+XcYBt54R1TnKyOH4R+txpOAmXr7Apu9quiaByGbG0dACaRePMmPmLmw
|
||||
vX84Swpbvrh/M3RRQziRFnP5wih0lB1gupuqY0FCbZyewzcoiS731JeqY4Zj
|
||||
3+qZP4yB74ygnoYGDcz5GOJ8uXwM9p88XaKSqonn9R26+EdlsMLPpMHeaw4K
|
||||
rc1neaqOQ6OGqXLQurmYKexKyno4Ds8LLqSZKmhhhvxW6cjWCTjNNHaoe6+F
|
||||
pidKHHi9E6DEC9vqXzwPGaH7eO6hkyDMNkhMD9fGsUD+Knv5JCQu1VF86qKD
|
||||
h3vll15HyyE+1bfKS18XbTje/KqZ38E9cU+DikgXNYxUk++f/Q5jG7Nk6a/m
|
||||
49yHih6fJ7+DQLghtCxKD9We/pFtf2wKMtir5td7LcDHFdUyrmgK8i8Fqfst
|
||||
Z2H5rdC2ZGMGRrns36YgZWHfc/sj7Z4MNOfdzo2qX4jaWiITpSQGcpal5ddv
|
||||
08c4nrYPVjPw3OurnG1P9ZGdfship5yB2+e7ZNUsMsAzD/MLtFcycb1/1W71
|
||||
Kwb4qn7LsIcnE9P1vBfVSQ1QUbd5z75rTFz05m7Sjt2GeHJ9UIrOCybGLy8z
|
||||
bn5liLETFcsURUz0lSi+5RrTGL/GlX1jDoXeRcP6V67R6DRvQNHcmsIjF5wn
|
||||
7RJoPPVD0ph42kHOxe9U/qDR/97LrjtAYbQ0KC4+iUa6N+b4nPUUFqyTTSTf
|
||||
pDFTFtw6bEOhrHSqPTuPRo1786Pv21IY36xytbyKxo0v5z7UdKEwNfPowctc
|
||||
GuUeojTutDMDG2y21tIYpHQ98NxvFD7Sih+vbaBRfeZZ6YArhTx3zYMtbTRC
|
||||
CmNNqTuFRgIdm48CGveGmxUf2kfhyuIw1h0hjasPiNIWelFoealL5iOiMZKf
|
||||
HdA6bXujmw/6B2gk7zZK2PspPHlYnzU0RGN40raf1XwpDLc6L/tbMv0vikor
|
||||
n/Yl1Y+tgVIayzZ/kIT6UcgpzIwZG6Px0d7RwA8HKcyIUPR7Nk7j8sLHN2/8
|
||||
TmGeo8+G8Ekab1ncfmR7iMJiw8oF1t9pnF9RQuTTfiVZIpuaonFCb+xJ0WEK
|
||||
/wc13qzo
|
||||
"]]}},
|
||||
AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
|
||||
Axes->True,
|
||||
AxesLabel->{None, None},
|
||||
AxesOrigin->{0, 0},
|
||||
Method->{},
|
||||
PlotRange->{{0, 10}, {-1.623796532045525, 2.3025850725858823`}},
|
||||
PlotRangeClipping->True,
|
||||
PlotRangePadding->{
|
||||
Scaled[0.02],
|
||||
Scaled[0.02]}]], "Output",
|
||||
CellChangeTimes->{3.6112717778594217`*^9}]
|
||||
}, Open ]]
|
||||
},
|
||||
WindowSize->{716, 833},
|
||||
WindowMargins->{{Automatic, 214}, {Automatic, 26}},
|
||||
FrontEndVersion->"9.0 for Microsoft Windows (64-bit) (January 25, 2013)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
(* End of Notebook Content *)
|
||||
|
||||
(* Internal cache information *)
|
||||
(*CellTagsOutline
|
||||
CellTagsIndex->{}
|
||||
*)
|
||||
(*CellTagsIndex
|
||||
CellTagsIndex->{}
|
||||
*)
|
||||
(*NotebookFileOutline
|
||||
Notebook[{
|
||||
Cell[CellGroupData[{
|
||||
Cell[579, 22, 224, 6, 52, "Input"],
|
||||
Cell[806, 30, 211, 6, 31, "Output"]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[1054, 41, 155, 3, 31, "Input"],
|
||||
Cell[1212, 46, 130, 3, 31, "Output"]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[1379, 54, 137, 4, 31, "Input"],
|
||||
Cell[1519, 60, 105, 2, 31, "Output"]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[1661, 67, 113, 3, 31, "Input"],
|
||||
Cell[1777, 72, 90, 1, 31, "Output"]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[1904, 78, 102, 2, 31, "Input"],
|
||||
Cell[2009, 82, 321, 8, 31, "Output"]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[2367, 95, 191, 4, 52, "Input"],
|
||||
Cell[2561, 101, 131, 3, 31, "Output"]
|
||||
}, Open ]],
|
||||
Cell[2707, 107, 94, 1, 31, "Input"],
|
||||
Cell[CellGroupData[{
|
||||
Cell[2826, 112, 299, 8, 52, "Input"],
|
||||
Cell[3128, 122, 3019, 57, 265, "Output"]
|
||||
}, Open ]]
|
||||
}
|
||||
]
|
||||
*)
|
||||
|
||||
(* End of internal cache information *)
|
||||
3666
samples/Mathematica/MiscCalculations2.nb
Normal file
3666
samples/Mathematica/MiscCalculations2.nb
Normal file
File diff suppressed because it is too large
Load Diff
8
samples/Mathematica/Problem12.m
Normal file
8
samples/Mathematica/Problem12.m
Normal file
@@ -0,0 +1,8 @@
|
||||
(* ::Package:: *)
|
||||
|
||||
(* Problem12.m *)
|
||||
(* Author: William Woodruff *)
|
||||
(* Problem: What is the value of the first triangle number to have over five hundred divisors? *)
|
||||
|
||||
Do[If[Length[Divisors[Binomial[i + 1, 2]]] > 500,
|
||||
Print[Binomial[i + 1, 2]]; Break[]], {i, 1000000}]
|
||||
2196
samples/Moocode/moocode_toolkit.moo
Normal file
2196
samples/Moocode/moocode_toolkit.moo
Normal file
File diff suppressed because it is too large
Load Diff
80
samples/Nix/nginx.nix
Normal file
80
samples/Nix/nginx.nix
Normal file
@@ -0,0 +1,80 @@
|
||||
{ stdenv, fetchurl, fetchgit, openssl, zlib, pcre, libxml2, libxslt, expat
|
||||
, rtmp ? false
|
||||
, fullWebDAV ? false
|
||||
, syslog ? false
|
||||
, moreheaders ? false, ...}:
|
||||
|
||||
let
|
||||
version = "1.4.4";
|
||||
mainSrc = fetchurl {
|
||||
url = "http://nginx.org/download/nginx-${version}.tar.gz";
|
||||
sha256 = "1f82845mpgmhvm151fhn2cnqjggw9w7cvsqbva9rb320wmc9m63w";
|
||||
};
|
||||
|
||||
rtmp-ext = fetchgit {
|
||||
url = git://github.com/arut/nginx-rtmp-module.git;
|
||||
rev = "1cfb7aeb582789f3b15a03da5b662d1811e2a3f1";
|
||||
sha256 = "03ikfd2l8mzsjwx896l07rdrw5jn7jjfdiyl572yb9jfrnk48fwi";
|
||||
};
|
||||
|
||||
dav-ext = fetchgit {
|
||||
url = git://github.com/arut/nginx-dav-ext-module.git;
|
||||
rev = "54cebc1f21fc13391aae692c6cce672fa7986f9d";
|
||||
sha256 = "1dvpq1fg5rslnl05z8jc39sgnvh3akam9qxfl033akpczq1bh8nq";
|
||||
};
|
||||
|
||||
syslog-ext = fetchgit {
|
||||
url = https://github.com/yaoweibin/nginx_syslog_patch.git;
|
||||
rev = "165affd9741f0e30c4c8225da5e487d33832aca3";
|
||||
sha256 = "14dkkafjnbapp6jnvrjg9ip46j00cr8pqc2g7374z9aj7hrvdvhs";
|
||||
};
|
||||
|
||||
moreheaders-ext = fetchgit {
|
||||
url = https://github.com/agentzh/headers-more-nginx-module.git;
|
||||
rev = "refs/tags/v0.23";
|
||||
sha256 = "12pbjgsxnvcf2ff2i2qdn39q4cm5czlgrng96j8ml4cgxvnbdh39";
|
||||
};
|
||||
in
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
name = "nginx-${version}";
|
||||
src = mainSrc;
|
||||
|
||||
buildInputs = [ openssl zlib pcre libxml2 libxslt
|
||||
] ++ stdenv.lib.optional fullWebDAV expat;
|
||||
|
||||
patches = if syslog then [ "${syslog-ext}/syslog_1.4.0.patch" ] else [];
|
||||
|
||||
configureFlags = [
|
||||
"--with-http_ssl_module"
|
||||
"--with-http_spdy_module"
|
||||
"--with-http_xslt_module"
|
||||
"--with-http_sub_module"
|
||||
"--with-http_dav_module"
|
||||
"--with-http_gzip_static_module"
|
||||
"--with-http_secure_link_module"
|
||||
"--with-ipv6"
|
||||
# Install destination problems
|
||||
# "--with-http_perl_module"
|
||||
] ++ stdenv.lib.optional rtmp "--add-module=${rtmp-ext}"
|
||||
++ stdenv.lib.optional fullWebDAV "--add-module=${dav-ext}"
|
||||
++ stdenv.lib.optional syslog "--add-module=${syslog-ext}"
|
||||
++ stdenv.lib.optional moreheaders "--add-module=${moreheaders-ext}";
|
||||
|
||||
preConfigure = ''
|
||||
export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -I${libxml2 }/include/libxml2"
|
||||
'';
|
||||
|
||||
# escape example
|
||||
postInstall = ''
|
||||
mv $out/sbin $out/bin ''' ''${
|
||||
${ if true then ${ "" } else false }
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "A reverse proxy and lightweight webserver";
|
||||
maintainers = [ stdenv.lib.maintainers.raskin];
|
||||
platforms = stdenv.lib.platforms.all;
|
||||
inherit version;
|
||||
};
|
||||
}
|
||||
72
samples/Ox/IJCEmet2009.oxh
Normal file
72
samples/Ox/IJCEmet2009.oxh
Normal file
@@ -0,0 +1,72 @@
|
||||
/** Replicate Imai, Jain and Ching Econometrica 2009 (incomplete).
|
||||
|
||||
**/
|
||||
#include "IJCEmet2009.h"
|
||||
|
||||
Kapital::Kapital(L,const N,const entrant,const exit,const KP){
|
||||
StateVariable(L,N);
|
||||
this.entrant = entrant;
|
||||
this.exit = exit;
|
||||
this.KP = KP;
|
||||
actual = Kbar*vals/(N-1);
|
||||
upper = log(actual~.Inf);
|
||||
}
|
||||
|
||||
Kapital::Transit(FeasA) {
|
||||
decl ent =CV(entrant), stayout = FeasA[][exit.pos], tprob, sigu = CV(KP[SigU]);
|
||||
if (!v && !ent) return { <0>, ones(stayout) };
|
||||
tprob = ent ? probn( (upper-CV(KP[Kbe]))/sigu )
|
||||
: probn( (upper-(CV(KP[Kb0])+CV(KP[Kb2])*upper[v])) / sigu );
|
||||
tprob = tprob[1:] - tprob[:N-1];
|
||||
return { vals, tprob.*(1-stayout)+(1.0~zeros(1,N-1)).*stayout };
|
||||
}
|
||||
|
||||
FirmEntry::Run() {
|
||||
Initialize();
|
||||
GenerateSample();
|
||||
BDP->BayesianDP();
|
||||
}
|
||||
|
||||
FirmEntry::Initialize() {
|
||||
Rust::Initialize(Reachable,0);
|
||||
sige = new StDeviations("sige",<0.3,0.3>,0);
|
||||
entrant = new LaggedAction("entrant",d);
|
||||
KP = new array[Kparams];
|
||||
KP[Kbe] = new Positive("be",0.5);
|
||||
KP[Kb0] = new Free("b0",0.0);
|
||||
KP[Kb1] = new Determined("b1",0.0);
|
||||
KP[Kb2] = new Positive("b2",0.4);
|
||||
KP[SigU] = new Positive("sigu",0.4);
|
||||
EndogenousStates(K = new Kapital("K",KN,entrant,d,KP),entrant);
|
||||
SetDelta(new Probability("delta",0.85));
|
||||
kcoef = new Positive("kcoef",0.1);
|
||||
ecost = new Negative("ec",-0.4);
|
||||
CreateSpaces();
|
||||
}
|
||||
|
||||
FirmEntry::GenerateSample() {
|
||||
Volume = LOUD;
|
||||
EM = new ValueIteration(0);
|
||||
// EM -> Solve(0,0);
|
||||
data = new DataSet(0,EM);
|
||||
data->Simulate(DataN,DataT,0,FALSE);
|
||||
data->Print("firmentry.xls");
|
||||
BDP = new ImaiJainChing("FMH",data,EM,ecost,sige,kcoef,KP,delta);
|
||||
}
|
||||
|
||||
/** Capital stock can be positive only for incumbents.
|
||||
**/
|
||||
FirmEntry::Reachable() { return CV(entrant)*CV(K) ? 0 : new FirmEntry() ; }
|
||||
|
||||
/** The one period return.
|
||||
<DD>
|
||||
<pre>U = </pre>
|
||||
</DD>
|
||||
**/
|
||||
FirmEntry::Utility() {
|
||||
decl ent = CV(entrant),
|
||||
u =
|
||||
ent*CV(ecost)+(1-ent)*CV(kcoef)*AV(K)
|
||||
| 0.0;
|
||||
return u;
|
||||
}
|
||||
63
samples/Ox/ParallelObjective.ox
Normal file
63
samples/Ox/ParallelObjective.ox
Normal file
@@ -0,0 +1,63 @@
|
||||
/** Client and Server classes for parallel optimization using CFMPI.**/
|
||||
#include "ParallelObjective.h"
|
||||
|
||||
/** Set up MPI Client-Server support for objective optimization.
|
||||
@param obj `Objective' to parallelize
|
||||
@param DONOTUSECLIENT TRUE (default): client node does no object evaluation<br>FALSE after putting servers to work Client node does one evaluation.
|
||||
**/
|
||||
ParallelObjective(obj,DONOTUSECLIENT) {
|
||||
if (isclass(obj.p2p)) {oxwarning("P2P object already exists for "+obj.L+". Nothing changed"); return;}
|
||||
obj.p2p = new P2P(DONOTUSECLIENT,new ObjClient(obj),new ObjServer(obj));
|
||||
}
|
||||
|
||||
ObjClient::ObjClient(obj) { this.obj = obj; }
|
||||
|
||||
ObjClient::Execute() { }
|
||||
|
||||
ObjServer::ObjServer(obj) {
|
||||
this.obj = obj;
|
||||
basetag = P2P::STOP_TAG+1;
|
||||
iml = obj.NvfuncTerms;
|
||||
Nparams = obj.nstruct;
|
||||
}
|
||||
|
||||
/** Wait on the objective client.
|
||||
**/
|
||||
ObjServer::Loop(nxtmsgsz) {
|
||||
Nparams = nxtmsgsz; //free param length is no greater than Nparams
|
||||
if (Volume>QUIET) println("ObjServer server ",ID," Nparams ",Nparams);
|
||||
Server::Loop(Nparams);
|
||||
Recv(ANY_TAG); //receive the ending parameter vector
|
||||
obj->Encode(Buffer[:Nparams-1]); //encode it.
|
||||
}
|
||||
|
||||
/** Do the objective evaluation.
|
||||
Receive structural parameter vector and `Objective::Encode`() it.
|
||||
Call `Objective::vfunc`().
|
||||
@return Nparams (max. length of next expected message);
|
||||
**/
|
||||
ObjServer::Execute() {
|
||||
obj->Decode(Buffer[:obj.nfree-1]);
|
||||
Buffer = obj.cur.V[] = obj->vfunc();
|
||||
if (Volume>QUIET) println("Server Executive: ",ID," vfunc[0]= ",Buffer[0]);
|
||||
return obj.nstruct;
|
||||
}
|
||||
|
||||
CstrServer::CstrServer(obj) { ObjServer(obj); }
|
||||
|
||||
SepServer::SepServer(obj) { ObjServer(obj); }
|
||||
|
||||
CstrServer::Execute() {
|
||||
obj->Encode(Buffer);
|
||||
obj->Lagrangian(0);
|
||||
return rows(Buffer = obj.cur->Vec());
|
||||
}
|
||||
|
||||
/** Separable objective evaluations.
|
||||
**/
|
||||
SepServer::Execute() {
|
||||
obj.Kvar.v = imod(Tag-basetag,obj.K);
|
||||
obj->Encode(Buffer,TRUE);
|
||||
Buffer = obj.Kvar->PDF() * obj->vfunc();
|
||||
return obj.NvfuncTerms;
|
||||
}
|
||||
38
samples/Ox/particle.oxo
Normal file
38
samples/Ox/particle.oxo
Normal file
@@ -0,0 +1,38 @@
|
||||
nldge::ParticleLogLikeli()
|
||||
{ decl it, ip,
|
||||
mss, mbas, ms, my, mx, vw, vwi, dws,
|
||||
mhi, mhdet, loglikeli, mData,
|
||||
vxm, vxs, mxm=<>, mxsu=<>, mxsl=<>,
|
||||
time, timeall, timeran=0, timelik=0, timefun=0, timeint=0, timeres=0;
|
||||
|
||||
mData = GetData(m_asY);
|
||||
mhdet = sqrt((2*M_PI)^m_cY * determinant(m_mMSbE.^2)); // covariance determinant
|
||||
mhi = invert(m_mMSbE.^2); // invert covariance of measurement shocks
|
||||
|
||||
ms = m_vSss + zeros(m_cPar, m_cS); // start particles
|
||||
mx = m_vXss + zeros(m_cPar, m_cX); // steady state of state and policy
|
||||
|
||||
loglikeli = 0; // init likelihood
|
||||
//timeall=timer();
|
||||
for(it = 0; it < sizer(mData); it++)
|
||||
{
|
||||
mss = rann(m_cPar, m_cSS) * m_mSSbE; // state noise
|
||||
fg(&ms, ms, mx, mss); // transition prior as proposal
|
||||
mx = m_oApprox.FastInterpolate(ms); // interpolate
|
||||
fy(&my, ms, mx, zeros(m_cPar, m_cMS)); // evaluate importance weights
|
||||
my -= mData[it][]; // observation error
|
||||
|
||||
vw = exp(-0.5 * outer(my,mhi,'d')' )/mhdet; // vw = exp(-0.5 * sumr(my*mhi .*my ) )/mhdet;
|
||||
|
||||
vw = vw .== .NaN .? 0 .: vw; // no policy can happen for extrem particles
|
||||
dws = sumc(vw);
|
||||
if(dws==0) return -.Inf; // or extremely wrong parameters
|
||||
loglikeli += log(dws/m_cPar) ; // loglikelihood contribution
|
||||
//timelik += (timer()-time)/100;
|
||||
//time=timer();
|
||||
vwi = resample(vw/dws)-1; // selection step in c++
|
||||
ms = ms[vwi][]; // on normalized weights
|
||||
mx = mx[vwi][];
|
||||
}
|
||||
return loglikeli;
|
||||
}
|
||||
54
samples/Pan/test.pan
Normal file
54
samples/Pan/test.pan
Normal file
@@ -0,0 +1,54 @@
|
||||
object template pantest;
|
||||
|
||||
# Very simple pan test file
|
||||
"/long/decimal" = 123;
|
||||
"/long/octal" = 0755;
|
||||
"/long/hexadecimal" = 0xFF;
|
||||
|
||||
"/double/simple" = 0.01;
|
||||
"/double/pi" = 3.14159;
|
||||
"/double/exponent" = 1e-8;
|
||||
"/double/scientific" = 1.3E10;
|
||||
|
||||
"/string/single" = 'Faster, but escapes like \t, \n and \x3d don''t work, but '' should work.';
|
||||
"/string/double" = "Slower, but escapes like \t, \n and \x3d do work";
|
||||
|
||||
variable TEST = 2;
|
||||
|
||||
"/x2" = to_string(TEST);
|
||||
"/x2" ?= 'Default value';
|
||||
|
||||
"/x3" = 1 + 2 + value("/long/decimal");
|
||||
|
||||
"/x4" = undef;
|
||||
|
||||
"/x5" = null;
|
||||
|
||||
variable e ?= error("Test error message");
|
||||
|
||||
# include gmond config for services-monitoring
|
||||
include { 'site/ganglia/gmond/services-monitoring' };
|
||||
|
||||
"/software/packages"=pkg_repl("httpd","2.2.3-43.sl5.3",PKG_ARCH_DEFAULT);
|
||||
"/software/packages"=pkg_repl("php");
|
||||
|
||||
# Example function
|
||||
function show_things_view_for_stuff = {
|
||||
thing = ARGV[0];
|
||||
foreach( i; mything; STUFF ) {
|
||||
if ( thing == mything ) {
|
||||
return( true );
|
||||
} else {
|
||||
return SELF;
|
||||
};
|
||||
};
|
||||
false;
|
||||
};
|
||||
|
||||
variable HERE = <<EOF;
|
||||
; This example demonstrates an in-line heredoc style config file
|
||||
[main]
|
||||
awesome = true
|
||||
EOF
|
||||
|
||||
variable small = false;#This should be highlighted normally again.
|
||||
111
samples/Perl/PSGI.pod
Normal file
111
samples/Perl/PSGI.pod
Normal file
@@ -0,0 +1,111 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Catalyst::PSGI - How Catalyst and PSGI work together
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
The L<PSGI> specification defines an interface between web servers and
|
||||
Perl-based web applications and frameworks. It supports the writing of
|
||||
portable applications that can be run using various methods (as a
|
||||
standalone server, or using mod_perl, FastCGI, etc.). L<Plack> is an
|
||||
implementation of the PSGI specification for running Perl applications.
|
||||
|
||||
Catalyst used to contain an entire set of C<< Catalyst::Engine::XXXX >>
|
||||
classes to handle various web servers and environments (e.g. CGI,
|
||||
FastCGI, mod_perl) etc.
|
||||
|
||||
This has been changed in Catalyst 5.9 so that all of that work is done
|
||||
by Catalyst implementing the L<PSGI> specification, using L<Plack>'s
|
||||
adaptors to implement that functionality.
|
||||
|
||||
This means that we can share common code, and share fixes for specific
|
||||
web servers.
|
||||
|
||||
=head1 I already have an application
|
||||
|
||||
If you already have a Catalyst application, then you should be able to
|
||||
upgrade to the latest release with little or no trouble (see the notes
|
||||
in L<Catalyst::Upgrading> for specifics about your web server
|
||||
deployment).
|
||||
|
||||
=head1 Writing your own PSGI file.
|
||||
|
||||
=head2 What is a .psgi file?
|
||||
|
||||
A C<< .psgi >> file lets you control how your application code reference
|
||||
is built. Catalyst will automatically handle this for you, but it's
|
||||
possible to do it manually by creating a C<myapp.psgi> file in the root
|
||||
of your application.
|
||||
|
||||
=head2 Why would I want to write my own .psgi file?
|
||||
|
||||
Writing your own .psgi file allows you to use the alternate L<plackup> command
|
||||
to start your application, and allows you to add classes and extensions
|
||||
that implement L<Plack::Middleware>, such as L<Plack::Middleware::ErrorDocument>
|
||||
or L<Plack::Middleware::AccessLog>.
|
||||
|
||||
The simplest C<.psgi> file for an application called C<TestApp> would be:
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use TestApp;
|
||||
|
||||
my $app = TestApp->psgi_app(@_);
|
||||
|
||||
Note that Catalyst will apply a number of middleware components for you
|
||||
automatically, and these B<will not> be applied if you manually create a
|
||||
psgi file yourself. Details of these components can be found below.
|
||||
|
||||
Additional information about psgi files can be found at:
|
||||
L<http://search.cpan.org/dist/Plack/lib/Plack.pm#.psgi_files>
|
||||
|
||||
=head2 What is in the .psgi file Catalyst generates by default?
|
||||
|
||||
Catalyst generates an application which, if the C<using_frontend_proxy>
|
||||
setting is on, is wrapped in L<Plack::Middleware::ReverseProxy>, and
|
||||
contains some engine-specific fixes for uniform behaviour, as contained
|
||||
in:
|
||||
|
||||
=over
|
||||
|
||||
=item L<Plack::Middleware::LighttpdScriptNameFix>
|
||||
|
||||
=item L<Plack::Middleware::IIS6ScriptNameFix>
|
||||
|
||||
=back
|
||||
|
||||
If you override the default by providing your own C<< .psgi >> file,
|
||||
then none of these things will be done automatically for you by the PSGI
|
||||
application returned when you call C<< MyApp->psgi_app >>. Thus, if you
|
||||
need any of this functionality, you'll need to implement this in your
|
||||
C<< .psgi >> file yourself.
|
||||
|
||||
An apply_default_middlewares method is supplied to wrap your application
|
||||
in the default middlewares if you want this behaviour and you are providing
|
||||
your own .psgi file.
|
||||
|
||||
This means that the auto-generated (no .psgi file) code looks something
|
||||
like this:
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use TestApp;
|
||||
|
||||
my $app = TestApp->apply_default_middlewares(TestApp->psgi_app(@_));
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Catalyst::Upgrading>, L<Plack>, L<PSGI::FAQ>, L<PSGI>.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Catalyst Contributors, see Catalyst.pm
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
This library is free software. You can redistribute it and/or modify
|
||||
it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
38
samples/Pike/Error.pmod
Normal file
38
samples/Pike/Error.pmod
Normal file
@@ -0,0 +1,38 @@
|
||||
#pike __REAL_VERSION__
|
||||
|
||||
constant Generic = __builtin.GenericError;
|
||||
|
||||
constant Index = __builtin.IndexError;
|
||||
|
||||
constant BadArgument = __builtin.BadArgumentError;
|
||||
|
||||
constant Math = __builtin.MathError;
|
||||
|
||||
constant Resource = __builtin.ResourceError;
|
||||
|
||||
constant Permission = __builtin.PermissionError;
|
||||
|
||||
constant Decode = __builtin.DecodeError;
|
||||
|
||||
constant Cpp = __builtin.CppError;
|
||||
|
||||
constant Compilation = __builtin.CompilationError;
|
||||
|
||||
constant MasterLoad = __builtin.MasterLoadError;
|
||||
|
||||
constant ModuleLoad = __builtin.ModuleLoadError;
|
||||
|
||||
//! Returns an Error object for any argument it receives. If the
|
||||
//! argument already is an Error object or is empty, it does nothing.
|
||||
object mkerror(mixed error)
|
||||
{
|
||||
if (error == UNDEFINED)
|
||||
return error;
|
||||
if (objectp(error) && error->is_generic_error)
|
||||
return error;
|
||||
if (arrayp(error))
|
||||
return Error.Generic(@error);
|
||||
if (stringp(error))
|
||||
return Error.Generic(error);
|
||||
return Error.Generic(sprintf("%O", error));
|
||||
}
|
||||
360
samples/Pike/FakeFile.pike
Normal file
360
samples/Pike/FakeFile.pike
Normal file
@@ -0,0 +1,360 @@
|
||||
#pike __REAL_VERSION__
|
||||
|
||||
//! A string wrapper that pretends to be a @[Stdio.File] object
|
||||
//! in addition to some features of a @[Stdio.FILE] object.
|
||||
|
||||
|
||||
//! This constant can be used to distinguish a FakeFile object
|
||||
//! from a real @[Stdio.File] object.
|
||||
constant is_fake_file = 1;
|
||||
|
||||
protected string data;
|
||||
protected int ptr;
|
||||
protected int(0..1) r;
|
||||
protected int(0..1) w;
|
||||
protected int mtime;
|
||||
|
||||
protected function read_cb;
|
||||
protected function read_oob_cb;
|
||||
protected function write_cb;
|
||||
protected function write_oob_cb;
|
||||
protected function close_cb;
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->close()]
|
||||
int close(void|string direction) {
|
||||
direction = lower_case(direction||"rw");
|
||||
int cr = has_value(direction, "r");
|
||||
int cw = has_value(direction, "w");
|
||||
|
||||
if(cr) {
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if(cw) {
|
||||
w = 0;
|
||||
}
|
||||
|
||||
// FIXME: Close callback
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! @decl void create(string data, void|string type, void|int pointer)
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->create()]
|
||||
void create(string _data, void|string type, int|void _ptr) {
|
||||
if(!_data) error("No data string given to FakeFile.\n");
|
||||
data = _data;
|
||||
ptr = _ptr;
|
||||
mtime = time();
|
||||
if(type) {
|
||||
type = lower_case(type);
|
||||
if(has_value(type, "r"))
|
||||
r = 1;
|
||||
if(has_value(type, "w"))
|
||||
w = 1;
|
||||
}
|
||||
else
|
||||
r = w = 1;
|
||||
}
|
||||
|
||||
protected string make_type_str() {
|
||||
string type = "";
|
||||
if(r) type += "r";
|
||||
if(w) type += "w";
|
||||
return type;
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->dup()]
|
||||
this_program dup() {
|
||||
return this_program(data, make_type_str(), ptr);
|
||||
}
|
||||
|
||||
//! Always returns 0.
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->errno()]
|
||||
int errno() { return 0; }
|
||||
|
||||
//! Returns size and the creation time of the string.
|
||||
Stdio.Stat stat() {
|
||||
Stdio.Stat st = Stdio.Stat();
|
||||
st->size = sizeof(data);
|
||||
st->mtime=st->ctime=mtime;
|
||||
st->atime=time();
|
||||
return st;
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->line_iterator()]
|
||||
String.SplitIterator line_iterator(int|void trim) {
|
||||
if(trim)
|
||||
return String.SplitIterator( data-"\r", '\n' );
|
||||
return String.SplitIterator( data, '\n' );
|
||||
}
|
||||
|
||||
protected mixed id;
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->query_id()]
|
||||
mixed query_id() { return id; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_id()]
|
||||
void set_id(mixed _id) { id = _id; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->read_function()]
|
||||
function(:string) read_function(int nbytes) {
|
||||
return lambda() { return read(nbytes); };
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->peek()]
|
||||
int(-1..1) peek(int|float|void timeout) {
|
||||
if(!r) return -1;
|
||||
if(ptr >= sizeof(data)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! Always returns 0.
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->query_address()]
|
||||
string query_address(void|int(0..1) is_local) { return 0; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->read()]
|
||||
string read(void|int(0..) len, void|int(0..1) not_all) {
|
||||
if(!r) return 0;
|
||||
if (len < 0) error("Cannot read negative number of characters.\n");
|
||||
int start=ptr;
|
||||
ptr += len;
|
||||
if(zero_type(len) || ptr>sizeof(data))
|
||||
ptr = sizeof(data);
|
||||
|
||||
// FIXME: read callback
|
||||
return data[start..ptr-1];
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.FILE()->gets()]
|
||||
string gets() {
|
||||
if(!r) return 0;
|
||||
string ret;
|
||||
sscanf(data,"%*"+(string)ptr+"s%[^\n]",ret);
|
||||
if(ret)
|
||||
{
|
||||
ptr+=sizeof(ret)+1;
|
||||
if(ptr>sizeof(data))
|
||||
{
|
||||
ptr=sizeof(data);
|
||||
if(!sizeof(ret))
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: read callback
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.FILE()->getchar()]
|
||||
int getchar() {
|
||||
if(!r) return 0;
|
||||
int c;
|
||||
if(catch(c=data[ptr]))
|
||||
c=-1;
|
||||
else
|
||||
ptr++;
|
||||
|
||||
// FIXME: read callback
|
||||
return c;
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.FILE()->unread()]
|
||||
void unread(string s) {
|
||||
if(!r) return;
|
||||
if(data[ptr-sizeof(s)..ptr-1]==s)
|
||||
ptr-=sizeof(s);
|
||||
else
|
||||
{
|
||||
data=s+data[ptr..];
|
||||
ptr=0;
|
||||
}
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->seek()]
|
||||
int seek(int pos, void|int mult, void|int add) {
|
||||
if(mult)
|
||||
pos = pos*mult+add;
|
||||
if(pos<0)
|
||||
{
|
||||
pos = sizeof(data)+pos;
|
||||
if( pos < 0 )
|
||||
pos = 0;
|
||||
}
|
||||
ptr = pos;
|
||||
if( ptr > strlen( data ) )
|
||||
ptr = strlen(data);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//! Always returns 1.
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->sync()]
|
||||
int(1..1) sync() { return 1; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->tell()]
|
||||
int tell() { return ptr; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->truncate()]
|
||||
int(0..1) truncate(int length) {
|
||||
data = data[..length-1];
|
||||
return sizeof(data)==length;
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->write()]
|
||||
int(-1..) write(string|array(string) str, mixed ... extra) {
|
||||
if(!w) return -1;
|
||||
if(arrayp(str)) str=str*"";
|
||||
if(sizeof(extra)) str=sprintf(str, @extra);
|
||||
|
||||
if(ptr==sizeof(data)) {
|
||||
data += str;
|
||||
ptr = sizeof(data);
|
||||
}
|
||||
else if(sizeof(str)==1)
|
||||
data[ptr++] = str[0];
|
||||
else {
|
||||
data = data[..ptr-1] + str + data[ptr+sizeof(str)..];
|
||||
ptr += sizeof(str);
|
||||
}
|
||||
|
||||
// FIXME: write callback
|
||||
return sizeof(str);
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_blocking]
|
||||
void set_blocking() {
|
||||
close_cb = 0;
|
||||
read_cb = 0;
|
||||
read_oob_cb = 0;
|
||||
write_cb = 0;
|
||||
write_oob_cb = 0;
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_blocking_keep_callbacks]
|
||||
void set_blocking_keep_callbacks() { }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_blocking]
|
||||
void set_nonblocking(function rcb, function wcb, function ccb,
|
||||
function rocb, function wocb) {
|
||||
read_cb = rcb;
|
||||
write_cb = wcb;
|
||||
close_cb = ccb;
|
||||
read_oob_cb = rocb;
|
||||
write_oob_cb = wocb;
|
||||
}
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_blocking_keep_callbacks]
|
||||
void set_nonblocking_keep_callbacks() { }
|
||||
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_close_callback]
|
||||
void set_close_callback(function cb) { close_cb = cb; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_read_callback]
|
||||
void set_read_callback(function cb) { read_cb = cb; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_read_oob_callback]
|
||||
void set_read_oob_callback(function cb) { read_oob_cb = cb; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_write_callback]
|
||||
void set_write_callback(function cb) { write_cb = cb; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->set_write_oob_callback]
|
||||
void set_write_oob_callback(function cb) { write_oob_cb = cb; }
|
||||
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->query_close_callback]
|
||||
function query_close_callback() { return close_cb; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->query_read_callback]
|
||||
function query_read_callback() { return read_cb; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->query_read_oob_callback]
|
||||
function query_read_oob_callback() { return read_oob_cb; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->query_write_callback]
|
||||
function query_write_callback() { return write_cb; }
|
||||
|
||||
//! @seealso
|
||||
//! @[Stdio.File()->query_write_oob_callback]
|
||||
function query_write_oob_callback() { return write_oob_cb; }
|
||||
|
||||
string _sprintf(int t) {
|
||||
return t=='O' && sprintf("%O(%d,%O)", this_program, sizeof(data),
|
||||
make_type_str());
|
||||
}
|
||||
|
||||
|
||||
// FakeFile specials.
|
||||
|
||||
//! A FakeFile can be casted to a string.
|
||||
mixed cast(string to) {
|
||||
switch(to) {
|
||||
case "string": return data;
|
||||
case "object": return this;
|
||||
}
|
||||
error("Can not cast object to %O.\n", to);
|
||||
}
|
||||
|
||||
//! Sizeof on a FakeFile returns the size of its contents.
|
||||
int(0..) _sizeof() {
|
||||
return sizeof(data);
|
||||
}
|
||||
|
||||
//! @ignore
|
||||
|
||||
#define NOPE(X) mixed X (mixed ... args) { error("This is a FakeFile. %s is not available.\n", #X); }
|
||||
NOPE(assign);
|
||||
NOPE(async_connect);
|
||||
NOPE(connect);
|
||||
NOPE(connect_unix);
|
||||
NOPE(open);
|
||||
NOPE(open_socket);
|
||||
NOPE(pipe);
|
||||
NOPE(tcgetattr);
|
||||
NOPE(tcsetattr);
|
||||
|
||||
// Stdio.Fd
|
||||
NOPE(dup2);
|
||||
NOPE(lock); // We could implement this
|
||||
NOPE(mode); // We could implement this
|
||||
NOPE(proxy); // We could implement this
|
||||
NOPE(query_fd);
|
||||
NOPE(read_oob);
|
||||
NOPE(set_close_on_exec);
|
||||
NOPE(set_keepalive);
|
||||
NOPE(trylock); // We could implement this
|
||||
NOPE(write_oob);
|
||||
|
||||
//! @endignore
|
||||
260
samples/Prolog/format_spec.pl
Normal file
260
samples/Prolog/format_spec.pl
Normal file
@@ -0,0 +1,260 @@
|
||||
:- module(format_spec, [ format_error/2
|
||||
, format_spec/2
|
||||
, format_spec//1
|
||||
, spec_arity/2
|
||||
, spec_types/2
|
||||
]).
|
||||
|
||||
:- use_module(library(dcg/basics), [eos//0, integer//1, string_without//2]).
|
||||
:- use_module(library(error)).
|
||||
:- use_module(library(when), [when/2]).
|
||||
|
||||
% TODO loading this module is optional
|
||||
% TODO it's for my own convenience during development
|
||||
%:- use_module(library(mavis)).
|
||||
|
||||
%% format_error(+Goal, -Error:string) is nondet.
|
||||
%
|
||||
% True if Goal exhibits an Error in its format string. The
|
||||
% Error string describes what is wrong with Goal. Iterates each
|
||||
% error on backtracking.
|
||||
%
|
||||
% Goal may be one of the following predicates:
|
||||
%
|
||||
% * format/2
|
||||
% * format/3
|
||||
% * debug/3
|
||||
format_error(format(Format,Args), Error) :-
|
||||
format_error_(Format, Args,Error).
|
||||
format_error(format(_,Format,Args), Error) :-
|
||||
format_error_(Format,Args,Error).
|
||||
format_error(debug(_,Format,Args), Error) :-
|
||||
format_error_(Format,Args,Error).
|
||||
|
||||
format_error_(Format,Args,Error) :-
|
||||
format_spec(Format, Spec),
|
||||
!,
|
||||
is_list(Args),
|
||||
spec_types(Spec, Types),
|
||||
types_error(Args, Types, Error).
|
||||
format_error_(Format,_,Error) :-
|
||||
% \+ format_spec(Format, _),
|
||||
format(string(Error), "Invalid format string: ~q", [Format]).
|
||||
|
||||
types_error(Args, Types, Error) :-
|
||||
length(Types, TypesLen),
|
||||
length(Args, ArgsLen),
|
||||
TypesLen =\= ArgsLen,
|
||||
!,
|
||||
format( string(Error)
|
||||
, "Wrong argument count. Expected ~d, got ~d"
|
||||
, [TypesLen, ArgsLen]
|
||||
).
|
||||
types_error(Args, Types, Error) :-
|
||||
types_error_(Args, Types, Error).
|
||||
|
||||
types_error_([Arg|_],[Type|_],Error) :-
|
||||
ground(Arg),
|
||||
\+ is_of_type(Type,Arg),
|
||||
message_to_string(error(type_error(Type,Arg),_Location),Error).
|
||||
types_error_([_|Args],[_|Types],Error) :-
|
||||
types_error_(Args, Types, Error).
|
||||
|
||||
|
||||
% check/0 augmentation
|
||||
:- multifile check:checker/2.
|
||||
:- dynamic check:checker/2.
|
||||
check:checker(format_spec:checker, "format/2 strings and arguments").
|
||||
|
||||
:- dynamic format_fail/3.
|
||||
|
||||
checker :-
|
||||
prolog_walk_code([ module_class([user])
|
||||
, infer_meta_predicates(false)
|
||||
, autoload(false) % format/{2,3} are always loaded
|
||||
, undefined(ignore)
|
||||
, trace_reference(_)
|
||||
, on_trace(check_format)
|
||||
]),
|
||||
retract(format_fail(Goal,Location,Error)),
|
||||
print_message(warning, format_error(Goal,Location,Error)),
|
||||
fail. % iterate all errors
|
||||
checker. % succeed even if no errors are found
|
||||
|
||||
check_format(Module:Goal, _Caller, Location) :-
|
||||
predicate_property(Module:Goal, imported_from(Source)),
|
||||
memberchk(Source, [system,prolog_debug]),
|
||||
can_check(Goal),
|
||||
format_error(Goal, Error),
|
||||
assert(format_fail(Goal, Location, Error)),
|
||||
fail.
|
||||
check_format(_,_,_). % succeed to avoid printing goals
|
||||
|
||||
% true if format_error/2 can check this goal
|
||||
can_check(Goal) :-
|
||||
once(clause(format_error(Goal,_),_)).
|
||||
|
||||
prolog:message(format_error(Goal,Location,Error)) -->
|
||||
prolog:message_location(Location),
|
||||
['~n In goal: ~q~n ~s'-[Goal,Error]].
|
||||
|
||||
|
||||
%% format_spec(-Spec)//
|
||||
%
|
||||
% DCG for parsing format strings. It doesn't yet generate format
|
||||
% strings from a spec. See format_spec/2 for details.
|
||||
format_spec([]) -->
|
||||
eos.
|
||||
format_spec([escape(Numeric,Modifier,Action)|Rest]) -->
|
||||
"~",
|
||||
numeric_argument(Numeric),
|
||||
modifier_argument(Modifier),
|
||||
action(Action),
|
||||
format_spec(Rest).
|
||||
format_spec([text(String)|Rest]) -->
|
||||
{ when((ground(String);ground(Codes)),string_codes(String, Codes)) },
|
||||
string_without("~", Codes),
|
||||
{ Codes \= [] },
|
||||
format_spec(Rest).
|
||||
|
||||
|
||||
%% format_spec(+Format, -Spec:list) is semidet.
|
||||
%
|
||||
% Parse a format string. Each element of Spec is one of the following:
|
||||
%
|
||||
% * `text(Text)` - text sent to the output as is
|
||||
% * `escape(Num,Colon,Action)` - a format escape
|
||||
%
|
||||
% `Num` represents the optional numeric portion of an esape. `Colon`
|
||||
% represents the optional colon in an escape. `Action` is an atom
|
||||
% representing the action to be take by this escape.
|
||||
format_spec(Format, Spec) :-
|
||||
when((ground(Format);ground(Codes)),text_codes(Format, Codes)),
|
||||
once(phrase(format_spec(Spec), Codes, [])).
|
||||
|
||||
%% spec_arity(+FormatSpec, -Arity:positive_integer) is det.
|
||||
%
|
||||
% True if FormatSpec requires format/2 to have Arity arguments.
|
||||
spec_arity(Spec, Arity) :-
|
||||
spec_types(Spec, Types),
|
||||
length(Types, Arity).
|
||||
|
||||
|
||||
%% spec_types(+FormatSpec, -Types:list(type)) is det.
|
||||
%
|
||||
% True if FormatSpec requires format/2 to have arguments of Types. Each
|
||||
% value of Types is a type as described by error:has_type/2. This
|
||||
% notion of types is compatible with library(mavis).
|
||||
spec_types(Spec, Types) :-
|
||||
phrase(spec_types(Spec), Types).
|
||||
|
||||
spec_types([]) -->
|
||||
[].
|
||||
spec_types([Item|Items]) -->
|
||||
item_types(Item),
|
||||
spec_types(Items).
|
||||
|
||||
item_types(text(_)) -->
|
||||
[].
|
||||
item_types(escape(Numeric,_,Action)) -->
|
||||
numeric_types(Numeric),
|
||||
action_types(Action).
|
||||
|
||||
numeric_types(number(_)) -->
|
||||
[].
|
||||
numeric_types(character(_)) -->
|
||||
[].
|
||||
numeric_types(star) -->
|
||||
[number].
|
||||
numeric_types(nothing) -->
|
||||
[].
|
||||
|
||||
action_types(Action) -->
|
||||
{ atom_codes(Action, [Code]) },
|
||||
{ action_types(Code, Types) },
|
||||
phrase(Types).
|
||||
|
||||
|
||||
%% text_codes(Text:text, Codes:codes).
|
||||
text_codes(Var, Codes) :-
|
||||
var(Var),
|
||||
!,
|
||||
string_codes(Var, Codes).
|
||||
text_codes(Atom, Codes) :-
|
||||
atom(Atom),
|
||||
!,
|
||||
atom_codes(Atom, Codes).
|
||||
text_codes(String, Codes) :-
|
||||
string(String),
|
||||
!,
|
||||
string_codes(String, Codes).
|
||||
text_codes(Codes, Codes) :-
|
||||
is_of_type(codes, Codes).
|
||||
|
||||
|
||||
numeric_argument(number(N)) -->
|
||||
integer(N).
|
||||
numeric_argument(character(C)) -->
|
||||
"`",
|
||||
[C].
|
||||
numeric_argument(star) -->
|
||||
"*".
|
||||
numeric_argument(nothing) -->
|
||||
"".
|
||||
|
||||
|
||||
modifier_argument(colon) -->
|
||||
":".
|
||||
modifier_argument(no_colon) -->
|
||||
\+ ":".
|
||||
|
||||
|
||||
action(Action) -->
|
||||
[C],
|
||||
{ is_action(C) },
|
||||
{ atom_codes(Action, [C]) }.
|
||||
|
||||
|
||||
%% is_action(+Action:integer) is semidet.
|
||||
%% is_action(-Action:integer) is multi.
|
||||
%
|
||||
% True if Action is a valid format/2 action character. Iterates all
|
||||
% acceptable action characters, if Action is unbound.
|
||||
is_action(Action) :-
|
||||
action_types(Action, _).
|
||||
|
||||
%% action_types(?Action:integer, ?Types:list(type))
|
||||
%
|
||||
% True if Action consumes arguments matching Types. An action (like
|
||||
% `~`), which consumes no arguments, has `Types=[]`. For example,
|
||||
%
|
||||
% ?- action_types(0'~, Types).
|
||||
% Types = [].
|
||||
% ?- action_types(0'a, Types).
|
||||
% Types = [atom].
|
||||
action_types(0'~, []).
|
||||
action_types(0'a, [atom]).
|
||||
action_types(0'c, [integer]). % specifically, a code
|
||||
action_types(0'd, [integer]).
|
||||
action_types(0'D, [integer]).
|
||||
action_types(0'e, [float]).
|
||||
action_types(0'E, [float]).
|
||||
action_types(0'f, [float]).
|
||||
action_types(0'g, [float]).
|
||||
action_types(0'G, [float]).
|
||||
action_types(0'i, [any]).
|
||||
action_types(0'I, [integer]).
|
||||
action_types(0'k, [any]).
|
||||
action_types(0'n, []).
|
||||
action_types(0'N, []).
|
||||
action_types(0'p, [any]).
|
||||
action_types(0'q, [any]).
|
||||
action_types(0'r, [integer]).
|
||||
action_types(0'R, [integer]).
|
||||
action_types(0's, [text]).
|
||||
action_types(0'@, [callable]).
|
||||
action_types(0't, []).
|
||||
action_types(0'|, []).
|
||||
action_types(0'+, []).
|
||||
action_types(0'w, [any]).
|
||||
action_types(0'W, [any, list]).
|
||||
194
samples/Prolog/func.pl
Normal file
194
samples/Prolog/func.pl
Normal file
@@ -0,0 +1,194 @@
|
||||
:- module(func, [ op(675, xfy, ($))
|
||||
, op(650, xfy, (of))
|
||||
, ($)/2
|
||||
, (of)/2
|
||||
]).
|
||||
:- use_module(library(list_util), [xfy_list/3]).
|
||||
:- use_module(library(function_expansion)).
|
||||
:- use_module(library(arithmetic)).
|
||||
:- use_module(library(error)).
|
||||
|
||||
|
||||
% true if the module whose terms are being read has specifically
|
||||
% imported library(func).
|
||||
wants_func :-
|
||||
prolog_load_context(module, Module),
|
||||
Module \== func, % we don't want func sugar ourselves
|
||||
predicate_property(Module:of(_,_),imported_from(func)).
|
||||
|
||||
|
||||
%% compile_function(+Term, -In, -Out, -Goal) is semidet.
|
||||
%
|
||||
% True if Term represents a function from In to Out
|
||||
% implemented by calling Goal. This multifile hook is
|
||||
% called by $/2 and of/2 to convert a term into a goal.
|
||||
% It's used at compile time for macro expansion.
|
||||
% It's used at run time to handle functions which aren't
|
||||
% known at compile time.
|
||||
% When called as a hook, Term is guaranteed to be =nonvar=.
|
||||
%
|
||||
% For example, to treat library(assoc) terms as functions which
|
||||
% map a key to a value, one might define:
|
||||
%
|
||||
% :- multifile compile_function/4.
|
||||
% compile_function(Assoc, Key, Value, Goal) :-
|
||||
% is_assoc(Assoc),
|
||||
% Goal = get_assoc(Key, Assoc, Value).
|
||||
%
|
||||
% Then one could write:
|
||||
%
|
||||
% list_to_assoc([a-1, b-2, c-3], Assoc),
|
||||
% Two = Assoc $ b,
|
||||
:- multifile compile_function/4.
|
||||
compile_function(Var, _, _, _) :-
|
||||
% variables storing functions must be evaluated at run time
|
||||
% and can't be compiled, a priori, into a goal
|
||||
var(Var),
|
||||
!,
|
||||
fail.
|
||||
compile_function(Expr, In, Out, Out is Expr) :-
|
||||
% arithmetic expression of one variable are simply evaluated
|
||||
\+ string(Expr), % evaluable/1 throws exception with strings
|
||||
arithmetic:evaluable(Expr),
|
||||
term_variables(Expr, [In]).
|
||||
compile_function(F, In, Out, func:Goal) :-
|
||||
% composed functions
|
||||
function_composition_term(F),
|
||||
user:function_expansion(F, func:Functor, true),
|
||||
Goal =.. [Functor,In,Out].
|
||||
compile_function(F, In, Out, Goal) :-
|
||||
% string interpolation via format templates
|
||||
format_template(F),
|
||||
( atom(F) ->
|
||||
Goal = format(atom(Out), F, In)
|
||||
; string(F) ->
|
||||
Goal = format(string(Out), F, In)
|
||||
; error:has_type(codes, F) ->
|
||||
Goal = format(codes(Out), F, In)
|
||||
; fail % to be explicit
|
||||
).
|
||||
compile_function(Dict, In, Out, Goal) :-
|
||||
is_dict(Dict),
|
||||
Goal = get_dict(In, Dict, Out).
|
||||
|
||||
%% $(+Function, +Argument) is det.
|
||||
%
|
||||
% Apply Function to an Argument. A Function is any predicate
|
||||
% whose final argument generates output and whose penultimate argument
|
||||
% accepts input.
|
||||
%
|
||||
% This is realized by expanding function application to chained
|
||||
% predicate calls at compile time. Function application itself can
|
||||
% be chained.
|
||||
%
|
||||
% ==
|
||||
% Reversed = reverse $ sort $ [c,d,b].
|
||||
% ==
|
||||
:- meta_predicate $(2,+).
|
||||
$(_,_) :-
|
||||
throw(error(permission_error(call, predicate, ($)/2),
|
||||
context(_, '$/2 must be subject to goal expansion'))).
|
||||
|
||||
user:function_expansion($(F,X), Y, Goal) :-
|
||||
wants_func,
|
||||
( func:compile_function(F, X, Y, Goal) ->
|
||||
true
|
||||
; var(F) -> Goal = % defer until run time
|
||||
( func:compile_function(F, X, Y, P) ->
|
||||
call(P)
|
||||
; call(F, X, Y)
|
||||
)
|
||||
; Goal = call(F, X, Y)
|
||||
).
|
||||
|
||||
|
||||
%% of(+F, +G) is det.
|
||||
%
|
||||
% Creates a new function by composing F and G. The functions are
|
||||
% composed at compile time to create a new, compiled predicate which
|
||||
% behaves like a function. Function composition can be chained.
|
||||
% Composed functions can also be applied with $/2.
|
||||
%
|
||||
% ==
|
||||
% Reversed = reverse of sort $ [c,d,b].
|
||||
% ==
|
||||
:- meta_predicate of(2,2).
|
||||
of(_,_).
|
||||
|
||||
|
||||
%% format_template(Format) is semidet.
|
||||
%
|
||||
% True if Format is a template string suitable for format/3.
|
||||
% The current check is very naive and should be improved.
|
||||
format_template(Format) :-
|
||||
atom(Format), !,
|
||||
atom_codes(Format, Codes),
|
||||
format_template(Codes).
|
||||
format_template(Format) :-
|
||||
string(Format),
|
||||
!,
|
||||
string_codes(Format, Codes),
|
||||
format_template(Codes).
|
||||
format_template(Format) :-
|
||||
error:has_type(codes, Format),
|
||||
memberchk(0'~, Format). % ' fix syntax highlighting
|
||||
|
||||
|
||||
% True if the argument is a function composition term
|
||||
function_composition_term(of(_,_)).
|
||||
|
||||
% Converts a function composition term into a list of functions to compose
|
||||
functions_to_compose(Term, Funcs) :-
|
||||
functor(Term, Op, 2),
|
||||
Op = (of),
|
||||
xfy_list(Op, Term, Funcs).
|
||||
|
||||
% Thread a state variable through a list of functions. This is similar
|
||||
% to a DCG expansion, but much simpler.
|
||||
thread_state([], [], Out, Out).
|
||||
thread_state([F|Funcs], [Goal|Goals], In, Out) :-
|
||||
( compile_function(F, In, Tmp, Goal) ->
|
||||
true
|
||||
; var(F) ->
|
||||
instantiation_error(F)
|
||||
; F =.. [Functor|Args],
|
||||
append(Args, [In, Tmp], NewArgs),
|
||||
Goal =.. [Functor|NewArgs]
|
||||
),
|
||||
thread_state(Funcs, Goals, Tmp, Out).
|
||||
|
||||
user:function_expansion(Term, func:Functor, true) :-
|
||||
wants_func,
|
||||
functions_to_compose(Term, Funcs),
|
||||
debug(func, 'building composed function for: ~w', [Term]),
|
||||
variant_sha1(Funcs, Sha),
|
||||
format(atom(Functor), 'composed_function_~w', [Sha]),
|
||||
debug(func, ' name: ~s', [Functor]),
|
||||
( func:current_predicate(Functor/2) ->
|
||||
debug(func, ' composed predicate already exists', [])
|
||||
; true ->
|
||||
reverse(Funcs, RevFuncs),
|
||||
thread_state(RevFuncs, Threaded, In, Out),
|
||||
xfy_list(',', Body, Threaded),
|
||||
Head =.. [Functor, In, Out],
|
||||
func:assert(Head :- Body),
|
||||
func:compile_predicates([Functor/2])
|
||||
).
|
||||
|
||||
|
||||
% support foo(x,~,y) evaluation
|
||||
user:function_expansion(Term, Output, Goal) :-
|
||||
wants_func,
|
||||
compound(Term),
|
||||
|
||||
% has a single ~ argument
|
||||
setof( X
|
||||
, ( arg(X,Term,Arg), Arg == '~' )
|
||||
, [N]
|
||||
),
|
||||
|
||||
% replace ~ with a variable
|
||||
Term =.. [Name|Args0],
|
||||
nth1(N, Args0, ~, Rest),
|
||||
nth1(N, Args, Output, Rest),
|
||||
Goal =.. [Name|Args].
|
||||
97
samples/Propeller Spin/4x4 Keypad Reader.spin
Normal file
97
samples/Propeller Spin/4x4 Keypad Reader.spin
Normal file
@@ -0,0 +1,97 @@
|
||||
{{
|
||||
*****************************************
|
||||
* 4x4 Keypad Reader v1.0 *
|
||||
* Author: Beau Schwabe *
|
||||
* Copyright (c) 2007 Parallax *
|
||||
* See end of file for terms of use. *
|
||||
*****************************************
|
||||
}}
|
||||
{
|
||||
|
||||
Operation:
|
||||
|
||||
This object uses a capacitive PIN approach to reading the keypad.
|
||||
To do so, ALL pins are made LOW and an OUTPUT to "discharge" the
|
||||
I/O pins. Then, ALL pins are set to an INPUT state. At this point,
|
||||
only one pin is made HIGH and an OUTPUT at a time. If the "switch"
|
||||
is closed, then a HIGH will be read on the input, otherwise a LOW
|
||||
will be returned.
|
||||
|
||||
The keypad decoding routine only requires two subroutines and returns
|
||||
the entire 4x4 keypad matrix into a single WORD variable indicating
|
||||
which buttons are pressed. Multiple button presses are allowed with
|
||||
the understanding that“BOX entries can be confused. An example of a
|
||||
BOX entry... 1,2,4,5 or 1,4,3,6 or 4,6,*,# etc. where any 3 of the 4
|
||||
buttons pressed will evaluate the non pressed button as being pressed,
|
||||
even when they are not. There is no danger of any physical or
|
||||
electrical damage, that s just the way this sensing method happens to
|
||||
work.
|
||||
|
||||
Schematic:
|
||||
No resistors, No capacitors. The connections are directly from the
|
||||
keypad to the I/O's. I literally plugged mine right into the demo
|
||||
board RevC.
|
||||
|
||||
Looking at the Back of the 4x4 keypad...
|
||||
|
||||
P7 P0
|
||||
││││││││
|
||||
┌─────── ││││││││ ───────┐
|
||||
│ oo ││││││││ o │
|
||||
│ │
|
||||
│ O O O O O │
|
||||
│ │
|
||||
│ O O O O O │
|
||||
│ {LABEL} │
|
||||
│ O O O O O │
|
||||
│ │
|
||||
│ O O O O O │
|
||||
│ │
|
||||
│ O O O O O │
|
||||
│ o o │
|
||||
└────────────────────────┘
|
||||
|
||||
}
|
||||
VAR
|
||||
word keypad
|
||||
|
||||
PUB ReadKeyPad
|
||||
keypad := 0 'Clear 4x4 'keypad' value
|
||||
ReadRow(3) 'Call routine to read entire ROW 0
|
||||
keypad <<= 4 'Shift 'keypad' value left by 4
|
||||
ReadRow(2) 'Call routine to read entire ROW 1
|
||||
keypad <<= 4 'Shift 'keypad' value left by 4
|
||||
ReadRow(1) 'Call routine to read entire ROW 2
|
||||
keypad <<= 4 'Shift 'keypad' value left by 4
|
||||
ReadRow(0) 'Call routine to read entire ROW 3
|
||||
Result := keypad
|
||||
|
||||
PRI ReadRow(n)
|
||||
outa[0..7]~ 'preset P0 to P7 as LOWs
|
||||
dira[0..7]~~ 'make P0 to P7 OUTPUTs ... discharge pins or "capacitors" to VSS
|
||||
dira[0..7]~ 'make P0 to P7 INPUTSs ... now the pins act like tiny capacitors
|
||||
outa[n]~~ 'preset Pin 'n' HIGH
|
||||
dira[n]~~ 'make Pin 'n' an OUTPUT... Make only one pin HIGH ; will charge
|
||||
' "capacitor" if switch is closed.
|
||||
'
|
||||
keypad += ina[4..7] 'read ROW value ... If a switch is open, the pin or "capacitor"
|
||||
dira[n]~ 'make Pn an INPUT will remain discharged
|
||||
|
||||
DAT
|
||||
{{
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ TERMS OF USE: MIT License │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
|
||||
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
|
||||
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
|
||||
│is furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
|
||||
│ │
|
||||
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
|
||||
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
|
||||
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
}}
|
||||
181
samples/Propeller Spin/Debug_Lcd.spin
Normal file
181
samples/Propeller Spin/Debug_Lcd.spin
Normal file
@@ -0,0 +1,181 @@
|
||||
''****************************************
|
||||
''* Debug_Lcd v1.2 *
|
||||
''* Authors: Jon Williams, Jeff Martin *
|
||||
''* Copyright (c) 2006 Parallax, Inc. *
|
||||
''* See end of file for terms of use. *
|
||||
''****************************************
|
||||
''
|
||||
'' Debugging wrapper for Serial_Lcd object
|
||||
''
|
||||
'' v1.2 - March 26, 2008 - Updated by Jeff Martin to conform to Propeller object initialization standards.
|
||||
'' v1.1 - April 29, 2006 - Updated by Jon Williams for consistency.
|
||||
''
|
||||
|
||||
|
||||
OBJ
|
||||
|
||||
lcd : "serial_lcd" ' driver for Parallax Serial LCD
|
||||
num : "simple_numbers" ' number to string conversion
|
||||
|
||||
|
||||
PUB init(pin, baud, lines) : okay
|
||||
|
||||
'' Initializes serial LCD object
|
||||
'' -- returns true if all parameters okay
|
||||
|
||||
okay := lcd.init(pin, baud, lines)
|
||||
|
||||
|
||||
PUB finalize
|
||||
|
||||
'' Finalizes lcd object -- frees the pin (floats)
|
||||
|
||||
lcd.finalize
|
||||
|
||||
|
||||
PUB putc(txbyte)
|
||||
|
||||
'' Send a byte to the terminal
|
||||
|
||||
lcd.putc(txbyte)
|
||||
|
||||
|
||||
PUB str(strAddr)
|
||||
|
||||
'' Print a zero-terminated string
|
||||
|
||||
lcd.str(strAddr)
|
||||
|
||||
|
||||
PUB dec(value)
|
||||
|
||||
'' Print a signed decimal number
|
||||
|
||||
lcd.str(num.dec(value))
|
||||
|
||||
|
||||
PUB decf(value, width)
|
||||
|
||||
'' Prints signed decimal value in space-padded, fixed-width field
|
||||
|
||||
lcd.str(num.decf(value, width))
|
||||
|
||||
|
||||
PUB decx(value, digits)
|
||||
|
||||
'' Prints zero-padded, signed-decimal string
|
||||
'' -- if value is negative, field width is digits+1
|
||||
|
||||
lcd.str(num.decx(value, digits))
|
||||
|
||||
|
||||
PUB hex(value, digits)
|
||||
|
||||
'' Print a hexadecimal number
|
||||
|
||||
lcd.str(num.hex(value, digits))
|
||||
|
||||
|
||||
PUB ihex(value, digits)
|
||||
|
||||
'' Print an indicated hexadecimal number
|
||||
|
||||
lcd.str(num.ihex(value, digits))
|
||||
|
||||
|
||||
PUB bin(value, digits)
|
||||
|
||||
'' Print a binary number
|
||||
|
||||
lcd.str(num.bin(value, digits))
|
||||
|
||||
|
||||
PUB ibin(value, digits)
|
||||
|
||||
'' Print an indicated (%) binary number
|
||||
|
||||
lcd.str(num.ibin(value, digits))
|
||||
|
||||
|
||||
PUB cls
|
||||
|
||||
'' Clears LCD and moves cursor to home (0, 0) position
|
||||
|
||||
lcd.cls
|
||||
|
||||
|
||||
PUB home
|
||||
|
||||
'' Moves cursor to 0, 0
|
||||
|
||||
lcd.home
|
||||
|
||||
|
||||
PUB gotoxy(col, line)
|
||||
|
||||
'' Moves cursor to col/line
|
||||
|
||||
lcd.gotoxy(col, line)
|
||||
|
||||
|
||||
PUB clrln(line)
|
||||
|
||||
'' Clears line
|
||||
|
||||
lcd.clrln(line)
|
||||
|
||||
|
||||
PUB cursor(type)
|
||||
|
||||
'' Selects cursor type
|
||||
'' 0 : cursor off, blink off
|
||||
'' 1 : cursor off, blink on
|
||||
'' 2 : cursor on, blink off
|
||||
'' 3 : cursor on, blink on
|
||||
|
||||
lcd.cursor(type)
|
||||
|
||||
|
||||
PUB display(status)
|
||||
|
||||
'' Controls display visibility; use display(false) to hide contents without clearing
|
||||
|
||||
if status
|
||||
lcd.displayOn
|
||||
else
|
||||
lcd.displayOff
|
||||
|
||||
|
||||
PUB custom(char, chrDataAddr)
|
||||
|
||||
'' Installs custom character map
|
||||
'' -- chrDataAddr is address of 8-byte character definition array
|
||||
|
||||
lcd.custom(char, chrDataAddr)
|
||||
|
||||
|
||||
PUB backLight(status)
|
||||
|
||||
'' Enable (true) or disable (false) LCD backlight
|
||||
'' -- affects only backlit models
|
||||
|
||||
lcd.backLight(status)
|
||||
|
||||
{{
|
||||
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ TERMS OF USE: MIT License │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
|
||||
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
|
||||
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
|
||||
│is furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
|
||||
│ │
|
||||
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
|
||||
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
|
||||
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
}}
|
||||
1669
samples/Propeller Spin/Graphics.spin
Normal file
1669
samples/Propeller Spin/Graphics.spin
Normal file
File diff suppressed because it is too large
Load Diff
221
samples/Propeller Spin/Inductor.spin
Normal file
221
samples/Propeller Spin/Inductor.spin
Normal file
@@ -0,0 +1,221 @@
|
||||
{{
|
||||
*****************************************
|
||||
* Inductive Sensor Demo v1.0 *
|
||||
* Author: Beau Schwabe *
|
||||
* Copyright (c) 2007 Parallax *
|
||||
* See end of file for terms of use. *
|
||||
*****************************************
|
||||
|
||||
|
||||
Test Circuit:
|
||||
|
||||
10pF 100K 1M
|
||||
FPin ───┳──┳── SDF(sigma-delta feedback)
|
||||
│ ┣──── SDI(sigma-delta input)
|
||||
L 100K
|
||||
|
||||
GND GND
|
||||
|
||||
|
||||
Test Coils:
|
||||
|
||||
Wire used was the "Radio Shack Special" GREEN (about 27 gauge)
|
||||
|
||||
25T (Coke Can form) = 2.1MHz
|
||||
15T (Coke Can form) = 3.9MHz
|
||||
5T (Coke Can form) = 5.3MHz
|
||||
50T (BIC pen form) = 3.2MHz
|
||||
|
||||
|
||||
|
||||
How does it work?
|
||||
|
||||
Note: The reported resonate frequency is NOT the actual resonate LC frequency. Instead it is where the voltage produced from
|
||||
the LC circuit was clipped.
|
||||
|
||||
In the example circuit below:
|
||||
|
||||
C L
|
||||
A ────┳──── GND
|
||||
│
|
||||
B
|
||||
|
||||
When you apply a small voltage at a specific frequency to an LC circuit (at point "A") that is at or near the resonate
|
||||
frequency of LC, it is not uncommon to measure 10's or 100's of times the amount of voltage (at point "B") that you are
|
||||
applying to the LC circuit. (at point "A")
|
||||
|
||||
|
||||
In the "Test Circuit" above, point "B" passes through a diode which then basically feeds a divide by 2 voltage divider:
|
||||
|
||||
100K 100K
|
||||
B ───┳── GND
|
||||
│
|
||||
C
|
||||
|
||||
...So in order see the sigma-delta ADC "clip" the frequency sweep result, the output from the LC circuit only needs
|
||||
to generate about 6.6 Volts above ground. (0.6V drop across the diode, and since the ADC is only sensitive to about
|
||||
3V, it works out to be about 6.6V after the voltage divider.)
|
||||
|
||||
|
||||
A typical magnitude plot of a frequency sweep applied to an LC circuit might look something like this:
|
||||
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
***** *****
|
||||
|
||||
|
||||
...With 'clipping' the pattern looks more like this:
|
||||
|
||||
X****
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
***** *****
|
||||
|
||||
...The 'X' denotes the location of the reported resonate frequency. The reason this is slightly off is for
|
||||
two reasons really. 1) lazy - I didn't want to fiddle with the voltage divider combo... adjusting so that the
|
||||
"peak" was also where the ADC happened to "clip". 2) some benefit - When you apply a frequency to a tuned LC
|
||||
circuit that's resonate frequency is the same as the applied frequency, the LC acts like a dead short. A
|
||||
situation not exactly great for Propeller I/O's
|
||||
|
||||
Now that we have that out of the way, what happens next? How can we use this so called "coil" as a sensor?
|
||||
|
||||
If a frequency sweep is initially preformed to determine the resonate frequency clip point, then it just so
|
||||
happens that adding additional "metal" (<- Does not need to be ferrous) causes the resonate frequency to shift
|
||||
to a HIGHER frequency.
|
||||
|
||||
Once you determine the "clip" frequency and you use one of the available counters to constantly feed that
|
||||
particular frequency back to the LC circuit, the resulting ADC output is proportional and somewhat linear when
|
||||
metal objects are introduced to the coil.
|
||||
|
||||
Assume frequency increases from Left to Right. With a slight resonate shift to the right, the ADC reports a
|
||||
lower "de-tuned" value because the voltage magnitude no longer "clips" at the reported resonate frequency.
|
||||
Typical ranges are full scale between 65535 (no metal) and 0 (metal saturation)
|
||||
|
||||
|
||||
X *****
|
||||
* *
|
||||
ADC reports value here --> * *
|
||||
* *
|
||||
***** *****
|
||||
|
||||
Slight shift to the right
|
||||
|
||||
I also made mention that the response is somewhat linear. As the LC resonance shifts and the ADC value begins
|
||||
to lower, the slope is steepest near the "clip" point. Therefore, the slightest shift results in larger value
|
||||
changes. Since the coil is actually the least sensitive to metal the further away it is (Law of squares) and
|
||||
most sensitive to metal the closer it is, the resulting combination acts to linearize the output. I need to
|
||||
point out that some LC combinations will exhibit plateaus and other anomalies caused by varying parasitic circuit
|
||||
conditions that will affect the overall output, so a little bit of trial and error is necessary to get things
|
||||
the way you want them.
|
||||
|
||||
}}
|
||||
OBJ
|
||||
Freq : "Synth"
|
||||
ADC : "ADC"
|
||||
gr : "graphics"
|
||||
Num : "Numbers"
|
||||
CON
|
||||
FPin = 0
|
||||
|
||||
UpperFrequency = 6_000_000
|
||||
LowerFrequency = 2_000_000
|
||||
|
||||
bitmap_base = $2000
|
||||
display_base = $5000
|
||||
|
||||
VAR
|
||||
long FMax, FTemp, FValue, Frequency
|
||||
|
||||
PUB demo
|
||||
'start and setup graphics
|
||||
gr.start
|
||||
gr.setup(16, 12, 128, 96, bitmap_base)
|
||||
|
||||
FindResonateFrequency
|
||||
|
||||
DisplayInductorValue
|
||||
|
||||
PUB DisplayInductorValue | X
|
||||
Freq.Synth("A", FPin, FValue)
|
||||
repeat
|
||||
ADC.SigmaDelta(@FTemp)
|
||||
|
||||
'**************************************** Graphics Option Start *********************************************
|
||||
'clear bitmap
|
||||
gr.clear
|
||||
'draw text
|
||||
gr.textmode(1,1,7,5)
|
||||
gr.colorwidth(1,0)
|
||||
gr.text(0,90,string("Inductive Propeller Sensor"))
|
||||
|
||||
gr.colorwidth(1,5)
|
||||
X := (65535 - FTemp )*200/65535
|
||||
gr.plot(-100+X,15)
|
||||
|
||||
gr.textmode(1,1,7,%0000)
|
||||
gr.colorwidth(1,0)
|
||||
gr.text(-100,-20,string("Resonate Frequency ="))
|
||||
gr.text(35,-20,Num.ToStr(FValue,10))
|
||||
|
||||
gr.text(-100,-36,string("ADC Frequency Response ="))
|
||||
gr.text(65,-36,Num.ToStr(FTemp,10))
|
||||
|
||||
'copy bitmap to display
|
||||
gr.copy(display_base)
|
||||
'**************************************** Graphics Option Finish *********************************************
|
||||
|
||||
PUB FindResonateFrequency | P
|
||||
dira[FPin] := 1
|
||||
|
||||
FMax := 0
|
||||
repeat Frequency from LowerFrequency to UpperFrequency step 1000
|
||||
Freq.Synth("A", FPin, Frequency)
|
||||
ADC.SigmaDelta(@FTemp)
|
||||
|
||||
if FTemp > FMax
|
||||
FMax := FTemp
|
||||
FValue := Frequency
|
||||
'**************************************** Graphics Option Start *********************************************
|
||||
P := (Frequency - LowerFrequency)*100/(UpperFrequency - LowerFrequency)
|
||||
|
||||
gr.colorwidth(1,5)
|
||||
gr.plot(0,0)
|
||||
gr.line(P,0)
|
||||
gr.colorwidth(3,5)
|
||||
gr.line(100,0)
|
||||
|
||||
gr.colorwidth(2,0)
|
||||
gr.plot(P,(FTemp/1024)+10)
|
||||
gr.colorwidth(0,1)
|
||||
gr.plot(P+1,5)
|
||||
gr.line(P+1,50)
|
||||
|
||||
gr.copy(display_base)
|
||||
'**************************************** Graphics Option Finish *********************************************
|
||||
|
||||
DAT
|
||||
{{
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ TERMS OF USE: MIT License │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
|
||||
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
|
||||
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
|
||||
│is furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
|
||||
│ │
|
||||
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
|
||||
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
|
||||
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
}}
|
||||
736
samples/Propeller Spin/Keyboard.spin
Normal file
736
samples/Propeller Spin/Keyboard.spin
Normal file
@@ -0,0 +1,736 @@
|
||||
''***************************************
|
||||
''* PS/2 Keyboard Driver v1.0.1 *
|
||||
''* Author: Chip Gracey *
|
||||
''* Copyright (c) 2004 Parallax, Inc. *
|
||||
''* See end of file for terms of use. *
|
||||
''***************************************
|
||||
|
||||
{-----------------REVISION HISTORY-----------------
|
||||
v1.0.1 - Updated 6/15/2006 to work with Propeller Tool 0.96}
|
||||
|
||||
VAR
|
||||
|
||||
long cog
|
||||
|
||||
long par_tail 'key buffer tail read/write (19 contiguous longs)
|
||||
long par_head 'key buffer head read-only
|
||||
long par_present 'keyboard present read-only
|
||||
long par_states[8] 'key states (256 bits) read-only
|
||||
long par_keys[8] 'key buffer (16 words) read-only (also used to pass initial parameters)
|
||||
|
||||
|
||||
PUB start(dpin, cpin) : okay
|
||||
|
||||
'' Start keyboard driver - starts a cog
|
||||
'' returns false if no cog available
|
||||
''
|
||||
'' dpin = data signal on PS/2 jack
|
||||
'' cpin = clock signal on PS/2 jack
|
||||
''
|
||||
'' use 100-ohm resistors between pins and jack
|
||||
'' use 10K-ohm resistors to pull jack-side signals to VDD
|
||||
'' connect jack-power to 5V, jack-gnd to VSS
|
||||
''
|
||||
'' all lock-keys will be enabled, NumLock will be initially 'on',
|
||||
'' and auto-repeat will be set to 15cps with a delay of .5s
|
||||
|
||||
okay := startx(dpin, cpin, %0_000_100, %01_01000)
|
||||
|
||||
|
||||
PUB startx(dpin, cpin, locks, auto) : okay
|
||||
|
||||
'' Like start, but allows you to specify lock settings and auto-repeat
|
||||
''
|
||||
'' locks = lock setup
|
||||
'' bit 6 disallows shift-alphas (case set soley by CapsLock)
|
||||
'' bits 5..3 disallow toggle of NumLock/CapsLock/ScrollLock state
|
||||
'' bits 2..0 specify initial state of NumLock/CapsLock/ScrollLock
|
||||
'' (eg. %0_001_100 = disallow ScrollLock, NumLock initially 'on')
|
||||
''
|
||||
'' auto = auto-repeat setup
|
||||
'' bits 6..5 specify delay (0=.25s, 1=.5s, 2=.75s, 3=1s)
|
||||
'' bits 4..0 specify repeat rate (0=30cps..31=2cps)
|
||||
'' (eg %01_00000 = .5s delay, 30cps repeat)
|
||||
|
||||
stop
|
||||
longmove(@par_keys, @dpin, 4)
|
||||
okay := cog := cognew(@entry, @par_tail) + 1
|
||||
|
||||
|
||||
PUB stop
|
||||
|
||||
'' Stop keyboard driver - frees a cog
|
||||
|
||||
if cog
|
||||
cogstop(cog~ - 1)
|
||||
longfill(@par_tail, 0, 19)
|
||||
|
||||
|
||||
PUB present : truefalse
|
||||
|
||||
'' Check if keyboard present - valid ~2s after start
|
||||
'' returns t|f
|
||||
|
||||
truefalse := -par_present
|
||||
|
||||
|
||||
PUB key : keycode
|
||||
|
||||
'' Get key (never waits)
|
||||
'' returns key (0 if buffer empty)
|
||||
|
||||
if par_tail <> par_head
|
||||
keycode := par_keys.word[par_tail]
|
||||
par_tail := ++par_tail & $F
|
||||
|
||||
|
||||
PUB getkey : keycode
|
||||
|
||||
'' Get next key (may wait for keypress)
|
||||
'' returns key
|
||||
|
||||
repeat until (keycode := key)
|
||||
|
||||
|
||||
PUB newkey : keycode
|
||||
|
||||
'' Clear buffer and get new key (always waits for keypress)
|
||||
'' returns key
|
||||
|
||||
par_tail := par_head
|
||||
keycode := getkey
|
||||
|
||||
|
||||
PUB gotkey : truefalse
|
||||
|
||||
'' Check if any key in buffer
|
||||
'' returns t|f
|
||||
|
||||
truefalse := par_tail <> par_head
|
||||
|
||||
|
||||
PUB clearkeys
|
||||
|
||||
'' Clear key buffer
|
||||
|
||||
par_tail := par_head
|
||||
|
||||
|
||||
PUB keystate(k) : state
|
||||
|
||||
'' Get the state of a particular key
|
||||
'' returns t|f
|
||||
|
||||
state := -(par_states[k >> 5] >> k & 1)
|
||||
|
||||
|
||||
DAT
|
||||
|
||||
'******************************************
|
||||
'* Assembly language PS/2 keyboard driver *
|
||||
'******************************************
|
||||
|
||||
org
|
||||
'
|
||||
'
|
||||
' Entry
|
||||
'
|
||||
entry movd :par,#_dpin 'load input parameters _dpin/_cpin/_locks/_auto
|
||||
mov x,par
|
||||
add x,#11*4
|
||||
mov y,#4
|
||||
:par rdlong 0,x
|
||||
add :par,dlsb
|
||||
add x,#4
|
||||
djnz y,#:par
|
||||
|
||||
mov dmask,#1 'set pin masks
|
||||
shl dmask,_dpin
|
||||
mov cmask,#1
|
||||
shl cmask,_cpin
|
||||
|
||||
test _dpin,#$20 wc 'modify port registers within code
|
||||
muxc _d1,dlsb
|
||||
muxc _d2,dlsb
|
||||
muxc _d3,#1
|
||||
muxc _d4,#1
|
||||
test _cpin,#$20 wc
|
||||
muxc _c1,dlsb
|
||||
muxc _c2,dlsb
|
||||
muxc _c3,#1
|
||||
|
||||
mov _head,#0 'reset output parameter _head
|
||||
'
|
||||
'
|
||||
' Reset keyboard
|
||||
'
|
||||
reset mov dira,#0 'reset directions
|
||||
mov dirb,#0
|
||||
|
||||
movd :par,#_present 'reset output parameters _present/_states[8]
|
||||
mov x,#1+8
|
||||
:par mov 0,#0
|
||||
add :par,dlsb
|
||||
djnz x,#:par
|
||||
|
||||
mov stat,#8 'set reset flag
|
||||
'
|
||||
'
|
||||
' Update parameters
|
||||
'
|
||||
update movd :par,#_head 'update output parameters _head/_present/_states[8]
|
||||
mov x,par
|
||||
add x,#1*4
|
||||
mov y,#1+1+8
|
||||
:par wrlong 0,x
|
||||
add :par,dlsb
|
||||
add x,#4
|
||||
djnz y,#:par
|
||||
|
||||
test stat,#8 wc 'if reset flag, transmit reset command
|
||||
if_c mov data,#$FF
|
||||
if_c call #transmit
|
||||
'
|
||||
'
|
||||
' Get scancode
|
||||
'
|
||||
newcode mov stat,#0 'reset state
|
||||
|
||||
:same call #receive 'receive byte from keyboard
|
||||
|
||||
cmp data,#$83+1 wc 'scancode?
|
||||
|
||||
if_nc cmp data,#$AA wz 'powerup/reset?
|
||||
if_nc_and_z jmp #configure
|
||||
|
||||
if_nc cmp data,#$E0 wz 'extended?
|
||||
if_nc_and_z or stat,#1
|
||||
if_nc_and_z jmp #:same
|
||||
|
||||
if_nc cmp data,#$F0 wz 'released?
|
||||
if_nc_and_z or stat,#2
|
||||
if_nc_and_z jmp #:same
|
||||
|
||||
if_nc jmp #newcode 'unknown, ignore
|
||||
'
|
||||
'
|
||||
' Translate scancode and enter into buffer
|
||||
'
|
||||
test stat,#1 wc 'lookup code with extended flag
|
||||
rcl data,#1
|
||||
call #look
|
||||
|
||||
cmp data,#0 wz 'if unknown, ignore
|
||||
if_z jmp #newcode
|
||||
|
||||
mov t,_states+6 'remember lock keys in _states
|
||||
|
||||
mov x,data 'set/clear key bit in _states
|
||||
shr x,#5
|
||||
add x,#_states
|
||||
movd :reg,x
|
||||
mov y,#1
|
||||
shl y,data
|
||||
test stat,#2 wc
|
||||
:reg muxnc 0,y
|
||||
|
||||
if_nc cmpsub data,#$F0 wc 'if released or shift/ctrl/alt/win, done
|
||||
if_c jmp #update
|
||||
|
||||
mov y,_states+7 'get shift/ctrl/alt/win bit pairs
|
||||
shr y,#16
|
||||
|
||||
cmpsub data,#$E0 wc 'translate keypad, considering numlock
|
||||
if_c test _locks,#%100 wz
|
||||
if_c_and_z add data,#@keypad1-@table
|
||||
if_c_and_nz add data,#@keypad2-@table
|
||||
if_c call #look
|
||||
if_c jmp #:flags
|
||||
|
||||
cmpsub data,#$DD wc 'handle scrlock/capslock/numlock
|
||||
if_c mov x,#%001_000
|
||||
if_c shl x,data
|
||||
if_c andn x,_locks
|
||||
if_c shr x,#3
|
||||
if_c shr t,#29 'ignore auto-repeat
|
||||
if_c andn x,t wz
|
||||
if_c xor _locks,x
|
||||
if_c add data,#$DD
|
||||
if_c_and_nz or stat,#4 'if change, set configure flag to update leds
|
||||
|
||||
test y,#%11 wz 'get shift into nz
|
||||
|
||||
if_nz cmp data,#$60+1 wc 'check shift1
|
||||
if_nz_and_c cmpsub data,#$5B wc
|
||||
if_nz_and_c add data,#@shift1-@table
|
||||
if_nz_and_c call #look
|
||||
if_nz_and_c andn y,#%11
|
||||
|
||||
if_nz cmp data,#$3D+1 wc 'check shift2
|
||||
if_nz_and_c cmpsub data,#$27 wc
|
||||
if_nz_and_c add data,#@shift2-@table
|
||||
if_nz_and_c call #look
|
||||
if_nz_and_c andn y,#%11
|
||||
|
||||
test _locks,#%010 wc 'check shift-alpha, considering capslock
|
||||
muxnc :shift,#$20
|
||||
test _locks,#$40 wc
|
||||
if_nz_and_nc xor :shift,#$20
|
||||
cmp data,#"z"+1 wc
|
||||
if_c cmpsub data,#"a" wc
|
||||
:shift if_c add data,#"A"
|
||||
if_c andn y,#%11
|
||||
|
||||
:flags ror data,#8 'add shift/ctrl/alt/win flags
|
||||
mov x,#4 '+$100 if shift
|
||||
:loop test y,#%11 wz '+$200 if ctrl
|
||||
shr y,#2 '+$400 if alt
|
||||
if_nz or data,#1 '+$800 if win
|
||||
ror data,#1
|
||||
djnz x,#:loop
|
||||
rol data,#12
|
||||
|
||||
rdlong x,par 'if room in buffer and key valid, enter
|
||||
sub x,#1
|
||||
and x,#$F
|
||||
cmp x,_head wz
|
||||
if_nz test data,#$FF wz
|
||||
if_nz mov x,par
|
||||
if_nz add x,#11*4
|
||||
if_nz add x,_head
|
||||
if_nz add x,_head
|
||||
if_nz wrword data,x
|
||||
if_nz add _head,#1
|
||||
if_nz and _head,#$F
|
||||
|
||||
test stat,#4 wc 'if not configure flag, done
|
||||
if_nc jmp #update 'else configure to update leds
|
||||
'
|
||||
'
|
||||
' Configure keyboard
|
||||
'
|
||||
configure mov data,#$F3 'set keyboard auto-repeat
|
||||
call #transmit
|
||||
mov data,_auto
|
||||
and data,#%11_11111
|
||||
call #transmit
|
||||
|
||||
mov data,#$ED 'set keyboard lock-leds
|
||||
call #transmit
|
||||
mov data,_locks
|
||||
rev data,#-3 & $1F
|
||||
test data,#%100 wc
|
||||
rcl data,#1
|
||||
and data,#%111
|
||||
call #transmit
|
||||
|
||||
mov x,_locks 'insert locks into _states
|
||||
and x,#%111
|
||||
shl _states+7,#3
|
||||
or _states+7,x
|
||||
ror _states+7,#3
|
||||
|
||||
mov _present,#1 'set _present
|
||||
|
||||
jmp #update 'done
|
||||
'
|
||||
'
|
||||
' Lookup byte in table
|
||||
'
|
||||
look ror data,#2 'perform lookup
|
||||
movs :reg,data
|
||||
add :reg,#table
|
||||
shr data,#27
|
||||
mov x,data
|
||||
:reg mov data,0
|
||||
shr data,x
|
||||
|
||||
jmp #rand 'isolate byte
|
||||
'
|
||||
'
|
||||
' Transmit byte to keyboard
|
||||
'
|
||||
transmit
|
||||
_c1 or dira,cmask 'pull clock low
|
||||
movs napshr,#13 'hold clock for ~128us (must be >100us)
|
||||
call #nap
|
||||
_d1 or dira,dmask 'pull data low
|
||||
movs napshr,#18 'hold data for ~4us
|
||||
call #nap
|
||||
_c2 xor dira,cmask 'release clock
|
||||
|
||||
test data,#$0FF wc 'append parity and stop bits to byte
|
||||
muxnc data,#$100
|
||||
or data,dlsb
|
||||
|
||||
mov x,#10 'ready 10 bits
|
||||
transmit_bit call #wait_c0 'wait until clock low
|
||||
shr data,#1 wc 'output data bit
|
||||
_d2 muxnc dira,dmask
|
||||
mov wcond,c1 'wait until clock high
|
||||
call #wait
|
||||
djnz x,#transmit_bit 'another bit?
|
||||
|
||||
mov wcond,c0d0 'wait until clock and data low
|
||||
call #wait
|
||||
mov wcond,c1d1 'wait until clock and data high
|
||||
call #wait
|
||||
|
||||
call #receive_ack 'receive ack byte with timed wait
|
||||
cmp data,#$FA wz 'if ack error, reset keyboard
|
||||
if_nz jmp #reset
|
||||
|
||||
transmit_ret ret
|
||||
'
|
||||
'
|
||||
' Receive byte from keyboard
|
||||
'
|
||||
receive test _cpin,#$20 wc 'wait indefinitely for initial clock low
|
||||
waitpne cmask,cmask
|
||||
receive_ack
|
||||
mov x,#11 'ready 11 bits
|
||||
receive_bit call #wait_c0 'wait until clock low
|
||||
movs napshr,#16 'pause ~16us
|
||||
call #nap
|
||||
_d3 test dmask,ina wc 'input data bit
|
||||
rcr data,#1
|
||||
mov wcond,c1 'wait until clock high
|
||||
call #wait
|
||||
djnz x,#receive_bit 'another bit?
|
||||
|
||||
shr data,#22 'align byte
|
||||
test data,#$1FF wc 'if parity error, reset keyboard
|
||||
if_nc jmp #reset
|
||||
rand and data,#$FF 'isolate byte
|
||||
|
||||
look_ret
|
||||
receive_ack_ret
|
||||
receive_ret ret
|
||||
'
|
||||
'
|
||||
' Wait for clock/data to be in required state(s)
|
||||
'
|
||||
wait_c0 mov wcond,c0 '(wait until clock low)
|
||||
|
||||
wait mov y,tenms 'set timeout to 10ms
|
||||
|
||||
wloop movs napshr,#18 'nap ~4us
|
||||
call #nap
|
||||
_c3 test cmask,ina wc 'check required state(s)
|
||||
_d4 test dmask,ina wz 'loop until got state(s) or timeout
|
||||
wcond if_never djnz y,#wloop '(replaced with c0/c1/c0d0/c1d1)
|
||||
|
||||
tjz y,#reset 'if timeout, reset keyboard
|
||||
wait_ret
|
||||
wait_c0_ret ret
|
||||
|
||||
|
||||
c0 if_c djnz y,#wloop '(if_never replacements)
|
||||
c1 if_nc djnz y,#wloop
|
||||
c0d0 if_c_or_nz djnz y,#wloop
|
||||
c1d1 if_nc_or_z djnz y,#wloop
|
||||
'
|
||||
'
|
||||
' Nap
|
||||
'
|
||||
nap rdlong t,#0 'get clkfreq
|
||||
napshr shr t,#18/16/13 'shr scales time
|
||||
min t,#3 'ensure waitcnt won't snag
|
||||
add t,cnt 'add cnt to time
|
||||
waitcnt t,#0 'wait until time elapses (nap)
|
||||
|
||||
nap_ret ret
|
||||
'
|
||||
'
|
||||
' Initialized data
|
||||
'
|
||||
'
|
||||
dlsb long 1 << 9
|
||||
tenms long 10_000 / 4
|
||||
'
|
||||
'
|
||||
' Lookup table
|
||||
' ascii scan extkey regkey ()=keypad
|
||||
'
|
||||
table word $0000 '00
|
||||
word $00D8 '01 F9
|
||||
word $0000 '02
|
||||
word $00D4 '03 F5
|
||||
word $00D2 '04 F3
|
||||
word $00D0 '05 F1
|
||||
word $00D1 '06 F2
|
||||
word $00DB '07 F12
|
||||
word $0000 '08
|
||||
word $00D9 '09 F10
|
||||
word $00D7 '0A F8
|
||||
word $00D5 '0B F6
|
||||
word $00D3 '0C F4
|
||||
word $0009 '0D Tab
|
||||
word $0060 '0E `
|
||||
word $0000 '0F
|
||||
word $0000 '10
|
||||
word $F5F4 '11 Alt-R Alt-L
|
||||
word $00F0 '12 Shift-L
|
||||
word $0000 '13
|
||||
word $F3F2 '14 Ctrl-R Ctrl-L
|
||||
word $0071 '15 q
|
||||
word $0031 '16 1
|
||||
word $0000 '17
|
||||
word $0000 '18
|
||||
word $0000 '19
|
||||
word $007A '1A z
|
||||
word $0073 '1B s
|
||||
word $0061 '1C a
|
||||
word $0077 '1D w
|
||||
word $0032 '1E 2
|
||||
word $F600 '1F Win-L
|
||||
word $0000 '20
|
||||
word $0063 '21 c
|
||||
word $0078 '22 x
|
||||
word $0064 '23 d
|
||||
word $0065 '24 e
|
||||
word $0034 '25 4
|
||||
word $0033 '26 3
|
||||
word $F700 '27 Win-R
|
||||
word $0000 '28
|
||||
word $0020 '29 Space
|
||||
word $0076 '2A v
|
||||
word $0066 '2B f
|
||||
word $0074 '2C t
|
||||
word $0072 '2D r
|
||||
word $0035 '2E 5
|
||||
word $CC00 '2F Apps
|
||||
word $0000 '30
|
||||
word $006E '31 n
|
||||
word $0062 '32 b
|
||||
word $0068 '33 h
|
||||
word $0067 '34 g
|
||||
word $0079 '35 y
|
||||
word $0036 '36 6
|
||||
word $CD00 '37 Power
|
||||
word $0000 '38
|
||||
word $0000 '39
|
||||
word $006D '3A m
|
||||
word $006A '3B j
|
||||
word $0075 '3C u
|
||||
word $0037 '3D 7
|
||||
word $0038 '3E 8
|
||||
word $CE00 '3F Sleep
|
||||
word $0000 '40
|
||||
word $002C '41 ,
|
||||
word $006B '42 k
|
||||
word $0069 '43 i
|
||||
word $006F '44 o
|
||||
word $0030 '45 0
|
||||
word $0039 '46 9
|
||||
word $0000 '47
|
||||
word $0000 '48
|
||||
word $002E '49 .
|
||||
word $EF2F '4A (/) /
|
||||
word $006C '4B l
|
||||
word $003B '4C ;
|
||||
word $0070 '4D p
|
||||
word $002D '4E -
|
||||
word $0000 '4F
|
||||
word $0000 '50
|
||||
word $0000 '51
|
||||
word $0027 '52 '
|
||||
word $0000 '53
|
||||
word $005B '54 [
|
||||
word $003D '55 =
|
||||
word $0000 '56
|
||||
word $0000 '57
|
||||
word $00DE '58 CapsLock
|
||||
word $00F1 '59 Shift-R
|
||||
word $EB0D '5A (Enter) Enter
|
||||
word $005D '5B ]
|
||||
word $0000 '5C
|
||||
word $005C '5D \
|
||||
word $CF00 '5E WakeUp
|
||||
word $0000 '5F
|
||||
word $0000 '60
|
||||
word $0000 '61
|
||||
word $0000 '62
|
||||
word $0000 '63
|
||||
word $0000 '64
|
||||
word $0000 '65
|
||||
word $00C8 '66 BackSpace
|
||||
word $0000 '67
|
||||
word $0000 '68
|
||||
word $C5E1 '69 End (1)
|
||||
word $0000 '6A
|
||||
word $C0E4 '6B Left (4)
|
||||
word $C4E7 '6C Home (7)
|
||||
word $0000 '6D
|
||||
word $0000 '6E
|
||||
word $0000 '6F
|
||||
word $CAE0 '70 Insert (0)
|
||||
word $C9EA '71 Delete (.)
|
||||
word $C3E2 '72 Down (2)
|
||||
word $00E5 '73 (5)
|
||||
word $C1E6 '74 Right (6)
|
||||
word $C2E8 '75 Up (8)
|
||||
word $00CB '76 Esc
|
||||
word $00DF '77 NumLock
|
||||
word $00DA '78 F11
|
||||
word $00EC '79 (+)
|
||||
word $C7E3 '7A PageDn (3)
|
||||
word $00ED '7B (-)
|
||||
word $DCEE '7C PrScr (*)
|
||||
word $C6E9 '7D PageUp (9)
|
||||
word $00DD '7E ScrLock
|
||||
word $0000 '7F
|
||||
word $0000 '80
|
||||
word $0000 '81
|
||||
word $0000 '82
|
||||
word $00D6 '83 F7
|
||||
|
||||
keypad1 byte $CA, $C5, $C3, $C7, $C0, 0, $C1, $C4, $C2, $C6, $C9, $0D, "+-*/"
|
||||
|
||||
keypad2 byte "0123456789.", $0D, "+-*/"
|
||||
|
||||
shift1 byte "{|}", 0, 0, "~"
|
||||
|
||||
shift2 byte $22, 0, 0, 0, 0, "<_>?)!@#$%^&*(", 0, ":", 0, "+"
|
||||
'
|
||||
'
|
||||
' Uninitialized data
|
||||
'
|
||||
dmask res 1
|
||||
cmask res 1
|
||||
stat res 1
|
||||
data res 1
|
||||
x res 1
|
||||
y res 1
|
||||
t res 1
|
||||
|
||||
_head res 1 'write-only
|
||||
_present res 1 'write-only
|
||||
_states res 8 'write-only
|
||||
_dpin res 1 'read-only at start
|
||||
_cpin res 1 'read-only at start
|
||||
_locks res 1 'read-only at start
|
||||
_auto res 1 'read-only at start
|
||||
|
||||
''
|
||||
''
|
||||
'' _________
|
||||
'' Key Codes
|
||||
''
|
||||
'' 00..DF = keypress and keystate
|
||||
'' E0..FF = keystate only
|
||||
''
|
||||
''
|
||||
'' 09 Tab
|
||||
'' 0D Enter
|
||||
'' 20 Space
|
||||
'' 21 !
|
||||
'' 22 "
|
||||
'' 23 #
|
||||
'' 24 $
|
||||
'' 25 %
|
||||
'' 26 &
|
||||
'' 27 '
|
||||
'' 28 (
|
||||
'' 29 )
|
||||
'' 2A *
|
||||
'' 2B +
|
||||
'' 2C ,
|
||||
'' 2D -
|
||||
'' 2E .
|
||||
'' 2F /
|
||||
'' 30 0..9
|
||||
'' 3A :
|
||||
'' 3B ;
|
||||
'' 3C <
|
||||
'' 3D =
|
||||
'' 3E >
|
||||
'' 3F ?
|
||||
'' 40 @
|
||||
'' 41..5A A..Z
|
||||
'' 5B [
|
||||
'' 5C \
|
||||
'' 5D ]
|
||||
'' 5E ^
|
||||
'' 5F _
|
||||
'' 60 `
|
||||
'' 61..7A a..z
|
||||
'' 7B {
|
||||
'' 7C |
|
||||
'' 7D }
|
||||
'' 7E ~
|
||||
''
|
||||
'' 80-BF (future international character support)
|
||||
''
|
||||
'' C0 Left Arrow
|
||||
'' C1 Right Arrow
|
||||
'' C2 Up Arrow
|
||||
'' C3 Down Arrow
|
||||
'' C4 Home
|
||||
'' C5 End
|
||||
'' C6 Page Up
|
||||
'' C7 Page Down
|
||||
'' C8 Backspace
|
||||
'' C9 Delete
|
||||
'' CA Insert
|
||||
'' CB Esc
|
||||
'' CC Apps
|
||||
'' CD Power
|
||||
'' CE Sleep
|
||||
'' CF Wakeup
|
||||
''
|
||||
'' D0..DB F1..F12
|
||||
'' DC Print Screen
|
||||
'' DD Scroll Lock
|
||||
'' DE Caps Lock
|
||||
'' DF Num Lock
|
||||
''
|
||||
'' E0..E9 Keypad 0..9
|
||||
'' EA Keypad .
|
||||
'' EB Keypad Enter
|
||||
'' EC Keypad +
|
||||
'' ED Keypad -
|
||||
'' EE Keypad *
|
||||
'' EF Keypad /
|
||||
''
|
||||
'' F0 Left Shift
|
||||
'' F1 Right Shift
|
||||
'' F2 Left Ctrl
|
||||
'' F3 Right Ctrl
|
||||
'' F4 Left Alt
|
||||
'' F5 Right Alt
|
||||
'' F6 Left Win
|
||||
'' F7 Right Win
|
||||
''
|
||||
'' FD Scroll Lock State
|
||||
'' FE Caps Lock State
|
||||
'' FF Num Lock State
|
||||
''
|
||||
'' +100 if Shift
|
||||
'' +200 if Ctrl
|
||||
'' +400 if Alt
|
||||
'' +800 if Win
|
||||
''
|
||||
'' eg. Ctrl-Alt-Delete = $6C9
|
||||
''
|
||||
''
|
||||
'' Note: Driver will buffer up to 15 keystrokes, then ignore overflow.
|
||||
|
||||
{{
|
||||
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ TERMS OF USE: MIT License │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
|
||||
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
|
||||
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
|
||||
│is furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
|
||||
│ │
|
||||
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
|
||||
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
|
||||
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
}}
|
||||
711
samples/Propeller Spin/TV.spin
Normal file
711
samples/Propeller Spin/TV.spin
Normal file
@@ -0,0 +1,711 @@
|
||||
''***************************************
|
||||
''* TV Driver v1.1 *
|
||||
''* Author: Chip Gracey *
|
||||
''* Copyright (c) 2004 Parallax, Inc. *
|
||||
''* See end of file for terms of use. *
|
||||
''***************************************
|
||||
|
||||
' v1.0 - 01 May 2006 - original version
|
||||
' v1.1 - 17 May 2006 - pixel tile size can now be 16 x 32 to enable more efficient
|
||||
' character displays utilizing the internal font - see 'tv_mode'
|
||||
|
||||
|
||||
CON
|
||||
|
||||
fntsc = 3_579_545 'NTSC color frequency
|
||||
lntsc = 3640 'NTSC color cycles per line * 16
|
||||
sntsc = 624 'NTSC color cycles per sync * 16
|
||||
|
||||
fpal = 4_433_618 'PAL color frequency
|
||||
lpal = 4540 'PAL color cycles per line * 16
|
||||
spal = 848 'PAL color cycles per sync * 16
|
||||
|
||||
paramcount = 14
|
||||
colortable = $180 'start of colortable inside cog
|
||||
|
||||
|
||||
VAR
|
||||
|
||||
long cog
|
||||
|
||||
|
||||
PUB start(tvptr) : okay
|
||||
|
||||
'' Start TV driver - starts a cog
|
||||
'' returns false if no cog available
|
||||
''
|
||||
'' tvptr = pointer to TV parameters
|
||||
|
||||
stop
|
||||
okay := cog := cognew(@entry, tvptr) + 1
|
||||
|
||||
|
||||
PUB stop
|
||||
|
||||
'' Stop TV driver - frees a cog
|
||||
|
||||
if cog
|
||||
cogstop(cog~ - 1)
|
||||
|
||||
|
||||
DAT
|
||||
|
||||
'*******************************
|
||||
'* Assembly language TV driver *
|
||||
'*******************************
|
||||
|
||||
org
|
||||
'
|
||||
'
|
||||
' Entry
|
||||
'
|
||||
entry mov taskptr,#tasks 'reset tasks
|
||||
|
||||
mov x,#10 'perform task sections initially
|
||||
:init jmpret taskret,taskptr
|
||||
djnz x,#:init
|
||||
'
|
||||
'
|
||||
' Superfield
|
||||
'
|
||||
superfield mov taskptr,#tasks 'reset tasks
|
||||
|
||||
test _mode,#%0001 wc 'if ntsc, set phaseflip
|
||||
if_nc mov phaseflip,phasemask
|
||||
|
||||
test _mode,#%0010 wz 'get interlace into nz
|
||||
'
|
||||
'
|
||||
' Field
|
||||
'
|
||||
field mov x,vinv 'do invisible back porch lines
|
||||
:black call #hsync 'do hsync
|
||||
waitvid burst,sync_high2 'do black
|
||||
jmpret taskret,taskptr 'call task section (z undisturbed)
|
||||
djnz x,#:black 'another black line?
|
||||
|
||||
wrlong visible,par 'set status to visible
|
||||
|
||||
mov x,vb 'do visible back porch lines
|
||||
call #blank_lines
|
||||
|
||||
mov screen,_screen 'point to first tile (upper-leftmost)
|
||||
mov y,_vt 'set vertical tiles
|
||||
:line mov vx,_vx 'set vertical expand
|
||||
:vert if_z xor interlace,#1 'interlace skip?
|
||||
if_z tjz interlace,#:skip
|
||||
|
||||
call #hsync 'do hsync
|
||||
|
||||
mov vscl,hb 'do visible back porch pixels
|
||||
xor tile,colortable
|
||||
waitvid tile,#0
|
||||
|
||||
mov x,_ht 'set horizontal tiles
|
||||
mov vscl,hx 'set horizontal expand
|
||||
|
||||
:tile rdword tile,screen 'read tile
|
||||
or tile,line 'set pointer bits into tile
|
||||
rol tile,#6 'read tile pixels
|
||||
rdlong pixels,tile '(2 instructions between reads)
|
||||
shr tile,#10+6 'set tile colors
|
||||
movs :color,tile
|
||||
add screen,#2 'point to next tile
|
||||
mov tile,phaseflip
|
||||
:color xor tile,colortable
|
||||
waitvid tile,pixels 'pass colors and pixels to video
|
||||
djnz x,#:tile 'another tile?
|
||||
|
||||
sub screen,hc2x 'repoint to first tile in same line
|
||||
|
||||
mov vscl,hf 'do visible front porch pixels
|
||||
mov tile,phaseflip
|
||||
xor tile,colortable
|
||||
waitvid tile,#0
|
||||
|
||||
:skip djnz vx,#:vert 'vertical expand?
|
||||
ror line,linerot 'set next line
|
||||
add line,lineadd wc
|
||||
rol line,linerot
|
||||
if_nc jmp #:line
|
||||
add screen,hc2x 'point to first tile in next line
|
||||
djnz y,#:line 'another tile line?
|
||||
|
||||
if_z xor interlace,#1 wz 'get interlace and field1 into z
|
||||
|
||||
test _mode,#%0001 wc 'do visible front porch lines
|
||||
mov x,vf
|
||||
if_nz_and_c add x,#1
|
||||
call #blank_lines
|
||||
|
||||
if_nz wrlong invisible,par 'unless interlace and field1, set status to invisible
|
||||
|
||||
if_z_eq_c call #hsync 'if required, do short line
|
||||
if_z_eq_c mov vscl,hrest
|
||||
if_z_eq_c waitvid burst,sync_high2
|
||||
if_z_eq_c xor phaseflip,phasemask
|
||||
|
||||
call #vsync_high 'do high vsync pulses
|
||||
|
||||
movs vsync1,#sync_low1 'do low vsync pulses
|
||||
movs vsync2,#sync_low2
|
||||
call #vsync_low
|
||||
|
||||
call #vsync_high 'do high vsync pulses
|
||||
|
||||
if_nz mov vscl,hhalf 'if odd frame, do half line
|
||||
if_nz waitvid burst,sync_high2
|
||||
|
||||
if_z jmp #field 'if interlace and field1, display field2
|
||||
jmp #superfield 'else, new superfield
|
||||
'
|
||||
'
|
||||
' Blank lines
|
||||
'
|
||||
blank_lines call #hsync 'do hsync
|
||||
|
||||
xor tile,colortable 'do background
|
||||
waitvid tile,#0
|
||||
|
||||
djnz x,#blank_lines
|
||||
|
||||
blank_lines_ret ret
|
||||
'
|
||||
'
|
||||
' Horizontal sync
|
||||
'
|
||||
hsync test _mode,#%0001 wc 'if pal, toggle phaseflip
|
||||
if_c xor phaseflip,phasemask
|
||||
|
||||
mov vscl,sync_scale1 'do hsync
|
||||
mov tile,phaseflip
|
||||
xor tile,burst
|
||||
waitvid tile,sync_normal
|
||||
|
||||
mov vscl,hvis 'setup in case blank line
|
||||
mov tile,phaseflip
|
||||
|
||||
hsync_ret ret
|
||||
'
|
||||
'
|
||||
' Vertical sync
|
||||
'
|
||||
vsync_high movs vsync1,#sync_high1 'vertical sync
|
||||
movs vsync2,#sync_high2
|
||||
|
||||
vsync_low mov x,vrep
|
||||
|
||||
vsyncx mov vscl,sync_scale1
|
||||
vsync1 waitvid burst,sync_high1
|
||||
|
||||
mov vscl,sync_scale2
|
||||
vsync2 waitvid burst,sync_high2
|
||||
|
||||
djnz x,#vsyncx
|
||||
vsync_low_ret
|
||||
vsync_high_ret ret
|
||||
'
|
||||
'
|
||||
' Tasks - performed in sections during invisible back porch lines
|
||||
'
|
||||
tasks mov t1,par 'load parameters
|
||||
movd :par,#_enable '(skip _status)
|
||||
mov t2,#paramcount - 1
|
||||
:load add t1,#4
|
||||
:par rdlong 0,t1
|
||||
add :par,d0
|
||||
djnz t2,#:load '+119
|
||||
|
||||
mov t1,_pins 'set video pins and directions
|
||||
test t1,#$08 wc
|
||||
if_nc mov t2,pins0
|
||||
if_c mov t2,pins1
|
||||
test t1,#$40 wc
|
||||
shr t1,#1
|
||||
shl t1,#3
|
||||
shr t2,t1
|
||||
movs vcfg,t2
|
||||
shr t1,#6
|
||||
movd vcfg,t1
|
||||
shl t1,#3
|
||||
and t2,#$FF
|
||||
shl t2,t1
|
||||
if_nc mov dira,t2
|
||||
if_nc mov dirb,#0
|
||||
if_c mov dira,#0
|
||||
if_c mov dirb,t2 '+18
|
||||
|
||||
tjz _enable,#disabled '+2, disabled?
|
||||
|
||||
jmpret taskptr,taskret '+1=140, break and return later
|
||||
|
||||
movs :rd,#wtab 'load ntsc/pal metrics from word table
|
||||
movd :wr,#hvis
|
||||
mov t1,#wtabx - wtab
|
||||
test _mode,#%0001 wc
|
||||
:rd mov t2,0
|
||||
add :rd,#1
|
||||
if_nc shl t2,#16
|
||||
shr t2,#16
|
||||
:wr mov 0,t2
|
||||
add :wr,d0
|
||||
djnz t1,#:rd '+54
|
||||
|
||||
if_nc movs :ltab,#ltab 'load ntsc/pal metrics from long table
|
||||
if_c movs :ltab,#ltab+1
|
||||
movd :ltab,#fcolor
|
||||
mov t1,#(ltabx - ltab) >> 1
|
||||
:ltab mov 0,0
|
||||
add :ltab,d0s1
|
||||
djnz t1,#:ltab '+17
|
||||
|
||||
rdlong t1,#0 'get CLKFREQ
|
||||
shr t1,#1 'if CLKFREQ < 16MHz, cancel _broadcast
|
||||
cmp t1,m8 wc
|
||||
if_c mov _broadcast,#0
|
||||
shr t1,#1 'if CLKFREQ < color frequency * 4, disable
|
||||
cmp t1,fcolor wc
|
||||
if_c jmp #disabled '+11
|
||||
|
||||
jmpret taskptr,taskret '+1=83, break and return later
|
||||
|
||||
mov t1,fcolor 'set ctra pll to fcolor * 16
|
||||
call #divide 'if ntsc, set vco to fcolor * 32 (114.5454 MHz)
|
||||
test _mode,#%0001 wc 'if pal, set vco to fcolor * 16 (70.9379 MHz)
|
||||
if_c movi ctra,#%00001_111 'select fcolor * 16 output (ntsc=/2, pal=/1)
|
||||
if_nc movi ctra,#%00001_110
|
||||
if_nc shl t2,#1
|
||||
mov frqa,t2 '+147
|
||||
|
||||
jmpret taskptr,taskret '+1=148, break and return later
|
||||
|
||||
mov t1,_broadcast 'set ctrb pll to _broadcast
|
||||
mov t2,#0 'if 0, turn off ctrb
|
||||
tjz t1,#:off
|
||||
min t1,m8 'limit from 8MHz to 128MHz
|
||||
max t1,m128
|
||||
mov t2,#%00001_100 'adjust _broadcast to be within 4MHz-8MHz
|
||||
:scale shr t1,#1 '(vco will be within 64MHz-128MHz)
|
||||
cmp m8,t1 wc
|
||||
if_c add t2,#%00000_001
|
||||
if_c jmp #:scale
|
||||
:off movi ctrb,t2
|
||||
call #divide
|
||||
mov frqb,t2 '+165
|
||||
|
||||
jmpret taskptr,taskret '+1=166, break and return later
|
||||
|
||||
mov t1,#%10100_000 'set video configuration
|
||||
test _pins,#$01 wc '(swap broadcast/baseband output bits?)
|
||||
if_c or t1,#%01000_000
|
||||
test _mode,#%1000 wc '(strip chroma from broadcast?)
|
||||
if_nc or t1,#%00010_000
|
||||
test _mode,#%0100 wc '(strip chroma from baseband?)
|
||||
if_nc or t1,#%00001_000
|
||||
and _auralcog,#%111 '(set aural cog)
|
||||
or t1,_auralcog
|
||||
movi vcfg,t1 '+10
|
||||
|
||||
mov hx,_hx 'compute horizontal metrics
|
||||
shl hx,#8
|
||||
or hx,_hx
|
||||
shl hx,#4
|
||||
|
||||
mov hc2x,_ht
|
||||
shl hc2x,#1
|
||||
|
||||
mov t1,_ht
|
||||
mov t2,_hx
|
||||
call #multiply
|
||||
mov hf,hvis
|
||||
sub hf,t1
|
||||
shr hf,#1 wc
|
||||
mov hb,_ho
|
||||
addx hb,hf
|
||||
sub hf,_ho '+52
|
||||
|
||||
mov t1,_vt 'compute vertical metrics
|
||||
mov t2,_vx
|
||||
call #multiply
|
||||
test _mode,#%10000 wc 'consider tile size
|
||||
muxc linerot,#1
|
||||
mov lineadd,lineinc
|
||||
if_c shr lineadd,#1
|
||||
if_c shl t1,#1
|
||||
test _mode,#%0010 wc 'consider interlace
|
||||
if_c shr t1,#1
|
||||
mov vf,vvis
|
||||
sub vf,t1
|
||||
shr vf,#1 wc
|
||||
neg vb,_vo
|
||||
addx vb,vf
|
||||
add vf,_vo '+53
|
||||
|
||||
xor _mode,#%0010 '+1, flip interlace bit for display
|
||||
|
||||
:colors jmpret taskptr,taskret '+1=117/160, break and return later
|
||||
|
||||
mov t1,#13 'load next 13 colors into colortable
|
||||
:colorloop mov t2,:colorreg '5 times = 65 (all 64 colors loaded)
|
||||
shr t2,#9-2
|
||||
and t2,#$FC
|
||||
add t2,_colors
|
||||
:colorreg rdlong colortable,t2
|
||||
add :colorreg,d0
|
||||
andn :colorreg,d6
|
||||
djnz t1,#:colorloop '+158
|
||||
|
||||
jmp #:colors '+1, keep loading colors
|
||||
'
|
||||
'
|
||||
' Divide t1/CLKFREQ to get frqa or frqb value into t2
|
||||
'
|
||||
divide rdlong m1,#0 'get CLKFREQ
|
||||
|
||||
mov m2,#32+1
|
||||
:loop cmpsub t1,m1 wc
|
||||
rcl t2,#1
|
||||
shl t1,#1
|
||||
djnz m2,#:loop
|
||||
|
||||
divide_ret ret '+140
|
||||
'
|
||||
'
|
||||
' Multiply t1 * t2 * 16 (t1, t2 = bytes)
|
||||
'
|
||||
multiply shl t2,#8+4-1
|
||||
|
||||
mov m1,#8
|
||||
:loop shr t1,#1 wc
|
||||
if_c add t1,t2
|
||||
djnz m1,#:loop
|
||||
|
||||
multiply_ret ret '+37
|
||||
'
|
||||
'
|
||||
' Disabled - reset status, nap ~4ms, try again
|
||||
'
|
||||
disabled mov ctra,#0 'reset ctra
|
||||
mov ctrb,#0 'reset ctrb
|
||||
mov vcfg,#0 'reset video
|
||||
|
||||
wrlong outa,par 'set status to disabled
|
||||
|
||||
rdlong t1,#0 'get CLKFREQ
|
||||
shr t1,#8 'nap for ~4ms
|
||||
min t1,#3
|
||||
add t1,cnt
|
||||
waitcnt t1,#0
|
||||
|
||||
jmp #entry 'reload parameters
|
||||
'
|
||||
'
|
||||
' Initialized data
|
||||
'
|
||||
m8 long 8_000_000
|
||||
m128 long 128_000_000
|
||||
d0 long 1 << 9 << 0
|
||||
d6 long 1 << 9 << 6
|
||||
d0s1 long 1 << 9 << 0 + 1 << 1
|
||||
interlace long 0
|
||||
invisible long 1
|
||||
visible long 2
|
||||
phaseflip long $00000000
|
||||
phasemask long $F0F0F0F0
|
||||
line long $00060000
|
||||
lineinc long $10000000
|
||||
linerot long 0
|
||||
pins0 long %11110000_01110000_00001111_00000111
|
||||
pins1 long %11111111_11110111_01111111_01110111
|
||||
sync_high1 long %0101010101010101010101_101010_0101
|
||||
sync_high2 long %01010101010101010101010101010101 'used for black
|
||||
sync_low1 long %1010101010101010101010101010_0101
|
||||
sync_low2 long %01_101010101010101010101010101010
|
||||
'
|
||||
'
|
||||
' NTSC/PAL metrics tables
|
||||
' ntsc pal
|
||||
' ----------------------------------------------
|
||||
wtab word lntsc - sntsc, lpal - spal 'hvis
|
||||
word lntsc / 2 - sntsc, lpal / 2 - spal 'hrest
|
||||
word lntsc / 2, lpal / 2 'hhalf
|
||||
word 243, 286 'vvis
|
||||
word 10, 18 'vinv
|
||||
word 6, 5 'vrep
|
||||
word $02_8A, $02_AA 'burst
|
||||
wtabx
|
||||
ltab long fntsc 'fcolor
|
||||
long fpal
|
||||
long sntsc >> 4 << 12 + sntsc 'sync_scale1
|
||||
long spal >> 4 << 12 + spal
|
||||
long 67 << 12 + lntsc / 2 - sntsc 'sync_scale2
|
||||
long 79 << 12 + lpal / 2 - spal
|
||||
long %0101_00000000_01_10101010101010_0101 'sync_normal
|
||||
long %010101_00000000_01_101010101010_0101
|
||||
ltabx
|
||||
'
|
||||
'
|
||||
' Uninitialized data
|
||||
'
|
||||
taskptr res 1 'tasks
|
||||
taskret res 1
|
||||
t1 res 1
|
||||
t2 res 1
|
||||
m1 res 1
|
||||
m2 res 1
|
||||
|
||||
x res 1 'display
|
||||
y res 1
|
||||
hf res 1
|
||||
hb res 1
|
||||
vf res 1
|
||||
vb res 1
|
||||
hx res 1
|
||||
vx res 1
|
||||
hc2x res 1
|
||||
screen res 1
|
||||
tile res 1
|
||||
pixels res 1
|
||||
lineadd res 1
|
||||
|
||||
hvis res 1 'loaded from word table
|
||||
hrest res 1
|
||||
hhalf res 1
|
||||
vvis res 1
|
||||
vinv res 1
|
||||
vrep res 1
|
||||
burst res 1
|
||||
|
||||
fcolor res 1 'loaded from long table
|
||||
sync_scale1 res 1
|
||||
sync_scale2 res 1
|
||||
sync_normal res 1
|
||||
'
|
||||
'
|
||||
' Parameter buffer
|
||||
'
|
||||
_enable res 1 '0/non-0 read-only
|
||||
_pins res 1 '%pppmmmm read-only
|
||||
_mode res 1 '%tccip read-only
|
||||
_screen res 1 '@word read-only
|
||||
_colors res 1 '@long read-only
|
||||
_ht res 1 '1+ read-only
|
||||
_vt res 1 '1+ read-only
|
||||
_hx res 1 '4+ read-only
|
||||
_vx res 1 '1+ read-only
|
||||
_ho res 1 '0+- read-only
|
||||
_vo res 1 '0+- read-only
|
||||
_broadcast res 1 '0+ read-only
|
||||
_auralcog res 1 '0-7 read-only
|
||||
|
||||
fit colortable 'fit underneath colortable ($180-$1BF)
|
||||
''
|
||||
''___
|
||||
''VAR 'TV parameters - 14 contiguous longs
|
||||
''
|
||||
'' long tv_status '0/1/2 = off/invisible/visible read-only
|
||||
'' long tv_enable '0/non-0 = off/on write-only
|
||||
'' long tv_pins '%pppmmmm = pin group, pin group mode write-only
|
||||
'' long tv_mode '%tccip = tile,chroma,interlace,ntsc/pal write-only
|
||||
'' long tv_screen 'pointer to screen (words) write-only
|
||||
'' long tv_colors 'pointer to colors (longs) write-only
|
||||
'' long tv_ht 'horizontal tiles write-only
|
||||
'' long tv_vt 'vertical tiles write-only
|
||||
'' long tv_hx 'horizontal tile expansion write-only
|
||||
'' long tv_vx 'vertical tile expansion write-only
|
||||
'' long tv_ho 'horizontal offset write-only
|
||||
'' long tv_vo 'vertical offset write-only
|
||||
'' long tv_broadcast 'broadcast frequency (Hz) write-only
|
||||
'' long tv_auralcog 'aural fm cog write-only
|
||||
''
|
||||
''The preceding VAR section may be copied into your code.
|
||||
''After setting variables, do start(@tv_status) to start driver.
|
||||
''
|
||||
''All parameters are reloaded each superframe, allowing you to make live
|
||||
''changes. To minimize flicker, correlate changes with tv_status.
|
||||
''
|
||||
''Experimentation may be required to optimize some parameters.
|
||||
''
|
||||
''Parameter descriptions:
|
||||
'' _________
|
||||
'' tv_status
|
||||
''
|
||||
'' driver sets this to indicate status:
|
||||
'' 0: driver disabled (tv_enable = 0 or CLKFREQ < requirement)
|
||||
'' 1: currently outputting invisible sync data
|
||||
'' 2: currently outputting visible screen data
|
||||
'' _________
|
||||
'' tv_enable
|
||||
''
|
||||
'' 0: disable (pins will be driven low, reduces power)
|
||||
'' non-0: enable
|
||||
'' _______
|
||||
'' tv_pins
|
||||
''
|
||||
'' bits 6..4 select pin group:
|
||||
'' %000: pins 7..0
|
||||
'' %001: pins 15..8
|
||||
'' %010: pins 23..16
|
||||
'' %011: pins 31..24
|
||||
'' %100: pins 39..32
|
||||
'' %101: pins 47..40
|
||||
'' %110: pins 55..48
|
||||
'' %111: pins 63..56
|
||||
''
|
||||
'' bits 3..0 select pin group mode:
|
||||
'' %0000: %0000_0111 - baseband
|
||||
'' %0001: %0000_0111 - broadcast
|
||||
'' %0010: %0000_1111 - baseband + chroma
|
||||
'' %0011: %0000_1111 - broadcast + aural
|
||||
'' %0100: %0111_0000 broadcast -
|
||||
'' %0101: %0111_0000 baseband -
|
||||
'' %0110: %1111_0000 broadcast + aural -
|
||||
'' %0111: %1111_0000 baseband + chroma -
|
||||
'' %1000: %0111_0111 broadcast baseband
|
||||
'' %1001: %0111_0111 baseband broadcast
|
||||
'' %1010: %0111_1111 broadcast baseband + chroma
|
||||
'' %1011: %0111_1111 baseband broadcast + aural
|
||||
'' %1100: %1111_0111 broadcast + aural baseband
|
||||
'' %1101: %1111_0111 baseband + chroma broadcast
|
||||
'' %1110: %1111_1111 broadcast + aural baseband + chroma
|
||||
'' %1111: %1111_1111 baseband + chroma broadcast + aural
|
||||
'' -----------------------------------------------------------
|
||||
'' active pins top nibble bottom nibble
|
||||
''
|
||||
'' the baseband signal nibble is arranged as:
|
||||
'' bit 3: chroma signal for s-video (attach via 560-ohm resistor)
|
||||
'' bits 2..0: baseband video (sum 270/560/1100-ohm resistors to form 75-ohm 1V signal)
|
||||
''
|
||||
'' the broadcast signal nibble is arranged as:
|
||||
'' bit 3: aural subcarrier (sum 560-ohm resistor into network below)
|
||||
'' bits 2..0: visual carrier (sum 270/560/1100-ohm resistors to form 75-ohm 1V signal)
|
||||
'' _______
|
||||
'' tv_mode
|
||||
''
|
||||
'' bit 4 selects between 16x16 and 16x32 pixel tiles:
|
||||
'' 0: 16x16 pixel tiles (tileheight = 16)
|
||||
'' 1: 16x32 pixel tiles (tileheight = 32)
|
||||
''
|
||||
'' bit 3 controls chroma mixing into broadcast:
|
||||
'' 0: mix chroma into broadcast (color)
|
||||
'' 1: strip chroma from broadcast (black/white)
|
||||
''
|
||||
'' bit 2 controls chroma mixing into baseband:
|
||||
'' 0: mix chroma into baseband (composite color)
|
||||
'' 1: strip chroma from baseband (black/white or s-video)
|
||||
''
|
||||
'' bit 1 controls interlace:
|
||||
'' 0: progressive scan (243 display lines for NTSC, 286 for PAL)
|
||||
'' less flicker, good for motion
|
||||
'' 1: interlaced scan (486 display lines for NTSC, 572 for PAL)
|
||||
'' doubles the vertical display lines, good for text
|
||||
''
|
||||
'' bit 0 selects NTSC or PAL format
|
||||
'' 0: NTSC
|
||||
'' 3016 horizontal display ticks
|
||||
'' 243 or 486 (interlaced) vertical display lines
|
||||
'' CLKFREQ must be at least 14_318_180 (4 * 3_579_545 Hz)*
|
||||
'' 1: PAL
|
||||
'' 3692 horizontal display ticks
|
||||
'' 286 or 572 (interlaced) vertical display lines
|
||||
'' CLKFREQ must be at least 17_734_472 (4 * 4_433_618 Hz)*
|
||||
''
|
||||
'' * driver will disable itself while CLKFREQ is below requirement
|
||||
'' _________
|
||||
'' tv_screen
|
||||
''
|
||||
'' pointer to words which define screen contents (left-to-right, top-to-bottom)
|
||||
'' number of words must be tv_ht * tv_vt
|
||||
'' each word has two bitfields: a 6-bit colorset ptr and a 10-bit pixelgroup ptr
|
||||
'' bits 15..10: select the colorset* for the associated pixel tile
|
||||
'' bits 9..0: select the pixelgroup** address %ppppppppppcccc00 (p=address, c=0..15)
|
||||
''
|
||||
'' * colorsets are longs which each define four 8-bit colors
|
||||
''
|
||||
'' ** pixelgroups are <tileheight> longs which define (left-to-right, top-to-bottom) the 2-bit
|
||||
'' (four color) pixels that make up a 16x16 or a 32x32 pixel tile
|
||||
'' _________
|
||||
'' tv_colors
|
||||
''
|
||||
'' pointer to longs which define colorsets
|
||||
'' number of longs must be 1..64
|
||||
'' each long has four 8-bit fields which define colors for 2-bit (four color) pixels
|
||||
'' first long's bottom color is also used as the screen background color
|
||||
'' 8-bit color fields are as follows:
|
||||
'' bits 7..4: chroma data (0..15 = blue..green..red..)*
|
||||
'' bit 3: controls chroma modulation (0=off, 1=on)
|
||||
'' bits 2..0: 3-bit luminance level:
|
||||
'' values 0..1: reserved for sync - don't use
|
||||
'' values 2..7: valid luminance range, modulation adds/subtracts 1 (beware of 7)
|
||||
'' value 0 may be modulated to produce a saturated color toggling between levels 1 and 7
|
||||
''
|
||||
'' * because of TV's limitations, it doesn't look good when chroma changes abruptly -
|
||||
'' rather, use luminance - change chroma only against a black or white background for
|
||||
'' best appearance
|
||||
'' _____
|
||||
'' tv_ht
|
||||
''
|
||||
'' horizontal number pixel tiles - must be at least 1
|
||||
'' practical limit is 40 for NTSC, 50 for PAL
|
||||
'' _____
|
||||
'' tv_vt
|
||||
''
|
||||
'' vertical number of pixel tiles - must be at least 1
|
||||
'' practical limit is 13 for NTSC, 15 for PAL (26/30 max for interlaced NTSC/PAL)
|
||||
'' _____
|
||||
'' tv_hx
|
||||
''
|
||||
'' horizontal tile expansion factor - must be at least 3 for NTSC, 4 for PAL
|
||||
''
|
||||
'' make sure 16 * tv_ht * tv_hx + ||tv_ho + 32 is less than the horizontal display ticks
|
||||
'' _____
|
||||
'' tv_vx
|
||||
''
|
||||
'' vertical tile expansion factor - must be at least 1
|
||||
''
|
||||
'' make sure <tileheight> * tv_vt * tv_vx + ||tv_vo + 1 is less than the display lines
|
||||
'' _____
|
||||
'' tv_ho
|
||||
''
|
||||
'' horizontal offset in ticks - pos/neg value (0 for centered image)
|
||||
'' shifts the display right/left
|
||||
'' _____
|
||||
'' tv_vo
|
||||
''
|
||||
'' vertical offset in lines - pos/neg value (0 for centered image)
|
||||
'' shifts the display up/down
|
||||
'' ____________
|
||||
'' tv_broadcast
|
||||
''
|
||||
'' broadcast frequency expressed in Hz (ie channel 2 is 55_250_000)
|
||||
'' if 0, modulator is turned off - saves power
|
||||
''
|
||||
'' broadcasting requires CLKFREQ to be at least 16_000_000
|
||||
'' while CLKFREQ is below 16_000_000, modulator will be turned off
|
||||
'' ___________
|
||||
'' tv_auralcog
|
||||
''
|
||||
'' selects cog to supply aural fm signal - 0..7
|
||||
'' uses ctra pll output from selected cog
|
||||
''
|
||||
'' in NTSC, the offset frequency must be 4.5MHz and the max bandwidth +-25KHz
|
||||
'' in PAL, the offset frequency and max bandwidth vary by PAL type
|
||||
|
||||
{{
|
||||
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ TERMS OF USE: MIT License │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
|
||||
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
|
||||
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
|
||||
│is furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
|
||||
│ │
|
||||
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
|
||||
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
|
||||
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
}}
|
||||
244
samples/Propeller Spin/TV_Terminal.spin
Normal file
244
samples/Propeller Spin/TV_Terminal.spin
Normal file
@@ -0,0 +1,244 @@
|
||||
''***************************************
|
||||
''* TV Terminal v1.1 *
|
||||
''* Author: Chip Gracey *
|
||||
''* Copyright (c) 2005 Parallax, Inc. *
|
||||
''* See end of file for terms of use. *
|
||||
''***************************************
|
||||
|
||||
{-----------------REVISION HISTORY-----------------
|
||||
v1.1 - Updated 5/15/2006 to use actual pin number, instead of pin group, for Start method's basepin parameter.}
|
||||
|
||||
CON
|
||||
|
||||
x_tiles = 16
|
||||
y_tiles = 13
|
||||
|
||||
x_screen = x_tiles << 4
|
||||
y_screen = y_tiles << 4
|
||||
|
||||
width = 0 '0 = minimum
|
||||
x_scale = 1 '1 = minimum
|
||||
y_scale = 1 '1 = minimum
|
||||
x_spacing = 6 '6 = normal
|
||||
y_spacing = 13 '13 = normal
|
||||
|
||||
x_chr = x_scale * x_spacing
|
||||
y_chr = y_scale * y_spacing
|
||||
|
||||
y_offset = y_spacing / 6 + y_chr - 1
|
||||
|
||||
x_limit = x_screen / (x_scale * x_spacing)
|
||||
y_limit = y_screen / (y_scale * y_spacing)
|
||||
y_max = y_limit - 1
|
||||
|
||||
y_screen_bytes = y_screen << 2
|
||||
y_scroll = y_chr << 2
|
||||
y_scroll_longs = y_chr * y_max
|
||||
y_clear = y_scroll_longs << 2
|
||||
y_clear_longs = y_screen - y_scroll_longs
|
||||
|
||||
paramcount = 14
|
||||
|
||||
|
||||
VAR
|
||||
|
||||
long x, y, bitmap_base
|
||||
|
||||
long tv_status '0/1/2 = off/visible/invisible read-only
|
||||
long tv_enable '0/? = off/on write-only
|
||||
long tv_pins '%ppmmm = pins write-only
|
||||
long tv_mode '%ccinp = chroma,interlace,ntsc/pal,swap write-only
|
||||
long tv_screen 'pointer to screen (words) write-only
|
||||
long tv_colors 'pointer to colors (longs) write-only
|
||||
long tv_hc 'horizontal cells write-only
|
||||
long tv_vc 'vertical cells write-only
|
||||
long tv_hx 'horizontal cell expansion write-only
|
||||
long tv_vx 'vertical cell expansion write-only
|
||||
long tv_ho 'horizontal offset write-only
|
||||
long tv_vo 'vertical offset write-only
|
||||
long tv_broadcast 'broadcast frequency (Hz) write-only
|
||||
long tv_auralcog 'aural fm cog write-only
|
||||
|
||||
long bitmap[x_tiles * y_tiles << 4 + 16] 'add 16 longs to allow for 64-byte alignment
|
||||
word screen[x_tiles * y_tiles]
|
||||
|
||||
|
||||
OBJ
|
||||
|
||||
tv : "tv"
|
||||
gr : "graphics"
|
||||
|
||||
|
||||
PUB start(basepin)
|
||||
|
||||
'' Start terminal
|
||||
''
|
||||
'' basepin = first of three pins on a 4-pin boundary (0, 4, 8...) to have
|
||||
'' 1.1k, 560, and 270 ohm resistors connected and summed to form the 1V,
|
||||
'' 75 ohm DAC for baseband video
|
||||
|
||||
'init bitmap and tile screen
|
||||
bitmap_base := (@bitmap + $3F) & $7FC0
|
||||
repeat x from 0 to x_tiles - 1
|
||||
repeat y from 0 to y_tiles - 1
|
||||
screen[y * x_tiles + x] := bitmap_base >> 6 + y + x * y_tiles
|
||||
|
||||
'start tv
|
||||
tvparams_pins := (basepin & $38) << 1 | (basepin & 4 == 4) & %0101
|
||||
longmove(@tv_status, @tvparams, paramcount)
|
||||
tv_screen := @screen
|
||||
tv_colors := @color_schemes
|
||||
tv.start(@tv_status)
|
||||
|
||||
'start graphics
|
||||
gr.start
|
||||
gr.setup(x_tiles, y_tiles, 0, y_screen, bitmap_base)
|
||||
gr.textmode(x_scale, y_scale, x_spacing, 0)
|
||||
gr.width(width)
|
||||
out(0)
|
||||
|
||||
|
||||
PUB stop
|
||||
|
||||
'' Stop terminal
|
||||
|
||||
tv.stop
|
||||
gr.stop
|
||||
|
||||
|
||||
PUB out(c)
|
||||
|
||||
'' Print a character
|
||||
''
|
||||
'' $00 = home
|
||||
'' $01..$03 = color
|
||||
'' $04..$07 = color schemes
|
||||
'' $09 = tab
|
||||
'' $0D = return
|
||||
'' $20..$7E = character
|
||||
|
||||
case c
|
||||
|
||||
$00: 'home?
|
||||
gr.clear
|
||||
x := y := 0
|
||||
|
||||
$01..$03: 'color?
|
||||
gr.color(c)
|
||||
|
||||
$04..$07: 'color scheme?
|
||||
tv_colors := @color_schemes[c & 3]
|
||||
|
||||
$09: 'tab?
|
||||
repeat
|
||||
out($20)
|
||||
while x & 7
|
||||
|
||||
$0D: 'return?
|
||||
newline
|
||||
|
||||
$20..$7E: 'character?
|
||||
gr.text(x * x_chr, -y * y_chr - y_offset, @c)
|
||||
gr.finish
|
||||
if ++x == x_limit
|
||||
newline
|
||||
|
||||
|
||||
PUB str(string_ptr)
|
||||
|
||||
'' Print a zero-terminated string
|
||||
|
||||
repeat strsize(string_ptr)
|
||||
out(byte[string_ptr++])
|
||||
|
||||
|
||||
PUB dec(value) | i
|
||||
|
||||
'' Print a decimal number
|
||||
|
||||
if value < 0
|
||||
-value
|
||||
out("-")
|
||||
|
||||
i := 1_000_000_000
|
||||
|
||||
repeat 10
|
||||
if value => i
|
||||
out(value / i + "0")
|
||||
value //= i
|
||||
result~~
|
||||
elseif result or i == 1
|
||||
out("0")
|
||||
i /= 10
|
||||
|
||||
|
||||
PUB hex(value, digits)
|
||||
|
||||
'' Print a hexadecimal number
|
||||
|
||||
value <<= (8 - digits) << 2
|
||||
repeat digits
|
||||
out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
|
||||
|
||||
|
||||
PUB bin(value, digits)
|
||||
|
||||
'' Print a binary number
|
||||
|
||||
value <<= 32 - digits
|
||||
repeat digits
|
||||
out((value <-= 1) & 1 + "0")
|
||||
|
||||
|
||||
PRI newline
|
||||
|
||||
if ++y == y_limit
|
||||
gr.finish
|
||||
repeat x from 0 to x_tiles - 1
|
||||
y := bitmap_base + x * y_screen_bytes
|
||||
longmove(y, y + y_scroll, y_scroll_longs)
|
||||
longfill(y + y_clear, 0, y_clear_longs)
|
||||
y := y_max
|
||||
x := 0
|
||||
|
||||
|
||||
DAT
|
||||
|
||||
tvparams long 0 'status
|
||||
long 1 'enable
|
||||
tvparams_pins long %001_0101 'pins
|
||||
long %0000 'mode
|
||||
long 0 'screen
|
||||
long 0 'colors
|
||||
long x_tiles 'hc
|
||||
long y_tiles 'vc
|
||||
long 10 'hx
|
||||
long 1 'vx
|
||||
long 0 'ho
|
||||
long 0 'vo
|
||||
long 55_250_000 'broadcast
|
||||
long 0 'auralcog
|
||||
|
||||
color_schemes long $BC_6C_05_02
|
||||
long $0E_0D_0C_0A
|
||||
long $6E_6D_6C_6A
|
||||
long $BE_BD_BC_BA
|
||||
|
||||
{{
|
||||
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ TERMS OF USE: MIT License │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
|
||||
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
|
||||
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
|
||||
│is furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
|
||||
│ │
|
||||
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
|
||||
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
|
||||
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
}}
|
||||
232
samples/Propeller Spin/TV_Text.spin
Normal file
232
samples/Propeller Spin/TV_Text.spin
Normal file
@@ -0,0 +1,232 @@
|
||||
''***************************************
|
||||
''* TV Text 40x13 v1.0 *
|
||||
''* Author: Chip Gracey *
|
||||
''* Copyright (c) 2006 Parallax, Inc. *
|
||||
''* See end of file for terms of use. *
|
||||
''***************************************
|
||||
|
||||
CON
|
||||
|
||||
cols = 40
|
||||
rows = 13
|
||||
|
||||
screensize = cols * rows
|
||||
lastrow = screensize - cols
|
||||
|
||||
tv_count = 14
|
||||
|
||||
|
||||
VAR
|
||||
|
||||
long col, row, color, flag
|
||||
|
||||
word screen[screensize]
|
||||
long colors[8 * 2]
|
||||
|
||||
long tv_status '0/1/2 = off/invisible/visible read-only (14 longs)
|
||||
long tv_enable '0/non-0 = off/on write-only
|
||||
long tv_pins '%pppmmmm = pin group, pin group mode write-only
|
||||
long tv_mode '%tccip = tile,chroma,interlace,ntsc/pal write-only
|
||||
long tv_screen 'pointer to screen (words) write-only
|
||||
long tv_colors 'pointer to colors (longs) write-only
|
||||
long tv_ht 'horizontal tiles write-only
|
||||
long tv_vt 'vertical tiles write-only
|
||||
long tv_hx 'horizontal tile expansion write-only
|
||||
long tv_vx 'vertical tile expansion write-only
|
||||
long tv_ho 'horizontal offset write-only
|
||||
long tv_vo 'vertical offset write-only
|
||||
long tv_broadcast 'broadcast frequency (Hz) write-only
|
||||
long tv_auralcog 'aural fm cog write-only
|
||||
|
||||
|
||||
OBJ
|
||||
|
||||
tv : "tv"
|
||||
|
||||
|
||||
PUB start(basepin) : okay
|
||||
|
||||
'' Start terminal - starts a cog
|
||||
'' returns false if no cog available
|
||||
|
||||
setcolors(@palette)
|
||||
out(0)
|
||||
|
||||
longmove(@tv_status, @tv_params, tv_count)
|
||||
tv_pins := (basepin & $38) << 1 | (basepin & 4 == 4) & %0101
|
||||
tv_screen := @screen
|
||||
tv_colors := @colors
|
||||
|
||||
okay := tv.start(@tv_status)
|
||||
|
||||
|
||||
PUB stop
|
||||
|
||||
'' Stop terminal - frees a cog
|
||||
|
||||
tv.stop
|
||||
|
||||
|
||||
PUB str(stringptr)
|
||||
|
||||
'' Print a zero-terminated string
|
||||
|
||||
repeat strsize(stringptr)
|
||||
out(byte[stringptr++])
|
||||
|
||||
|
||||
PUB dec(value) | i
|
||||
|
||||
'' Print a decimal number
|
||||
|
||||
if value < 0
|
||||
-value
|
||||
out("-")
|
||||
|
||||
i := 1_000_000_000
|
||||
|
||||
repeat 10
|
||||
if value => i
|
||||
out(value / i + "0")
|
||||
value //= i
|
||||
result~~
|
||||
elseif result or i == 1
|
||||
out("0")
|
||||
i /= 10
|
||||
|
||||
|
||||
PUB hex(value, digits)
|
||||
|
||||
'' Print a hexadecimal number
|
||||
|
||||
value <<= (8 - digits) << 2
|
||||
repeat digits
|
||||
out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
|
||||
|
||||
|
||||
PUB bin(value, digits)
|
||||
|
||||
'' Print a binary number
|
||||
|
||||
value <<= 32 - digits
|
||||
repeat digits
|
||||
out((value <-= 1) & 1 + "0")
|
||||
|
||||
|
||||
PUB out(c) | i, k
|
||||
|
||||
'' Output a character
|
||||
''
|
||||
'' $00 = clear screen
|
||||
'' $01 = home
|
||||
'' $08 = backspace
|
||||
'' $09 = tab (8 spaces per)
|
||||
'' $0A = set X position (X follows)
|
||||
'' $0B = set Y position (Y follows)
|
||||
'' $0C = set color (color follows)
|
||||
'' $0D = return
|
||||
'' others = printable characters
|
||||
|
||||
case flag
|
||||
$00: case c
|
||||
$00: wordfill(@screen, $220, screensize)
|
||||
col := row := 0
|
||||
$01: col := row := 0
|
||||
$08: if col
|
||||
col--
|
||||
$09: repeat
|
||||
print(" ")
|
||||
while col & 7
|
||||
$0A..$0C: flag := c
|
||||
return
|
||||
$0D: newline
|
||||
other: print(c)
|
||||
$0A: col := c // cols
|
||||
$0B: row := c // rows
|
||||
$0C: color := c & 7
|
||||
flag := 0
|
||||
|
||||
|
||||
PUB setcolors(colorptr) | i, fore, back
|
||||
|
||||
'' Override default color palette
|
||||
'' colorptr must point to a list of up to 8 colors
|
||||
'' arranged as follows:
|
||||
''
|
||||
'' fore back
|
||||
'' ------------
|
||||
'' palette byte color, color 'color 0
|
||||
'' byte color, color 'color 1
|
||||
'' byte color, color 'color 2
|
||||
'' ...
|
||||
|
||||
repeat i from 0 to 7
|
||||
fore := byte[colorptr][i << 1]
|
||||
back := byte[colorptr][i << 1 + 1]
|
||||
colors[i << 1] := fore << 24 + back << 16 + fore << 8 + back
|
||||
colors[i << 1 + 1] := fore << 24 + fore << 16 + back << 8 + back
|
||||
|
||||
|
||||
PRI print(c)
|
||||
|
||||
screen[row * cols + col] := (color << 1 + c & 1) << 10 + $200 + c & $FE
|
||||
if ++col == cols
|
||||
newline
|
||||
|
||||
|
||||
PRI newline | i
|
||||
|
||||
col := 0
|
||||
if ++row == rows
|
||||
row--
|
||||
wordmove(@screen, @screen[cols], lastrow) 'scroll lines
|
||||
wordfill(@screen[lastrow], $220, cols) 'clear new line
|
||||
|
||||
|
||||
DAT
|
||||
|
||||
tv_params long 0 'status
|
||||
long 1 'enable
|
||||
long 0 'pins
|
||||
long %10010 'mode
|
||||
long 0 'screen
|
||||
long 0 'colors
|
||||
long cols 'hc
|
||||
long rows 'vc
|
||||
long 4 'hx
|
||||
long 1 'vx
|
||||
long 0 'ho
|
||||
long 0 'vo
|
||||
long 0 'broadcast
|
||||
long 0 'auralcog
|
||||
|
||||
|
||||
' fore back
|
||||
' color color
|
||||
palette byte $07, $0A '0 white / dark blue
|
||||
byte $07, $BB '1 white / red
|
||||
byte $9E, $9B '2 yellow / brown
|
||||
byte $04, $07 '3 grey / white
|
||||
byte $3D, $3B '4 cyan / dark cyan
|
||||
byte $6B, $6E '5 green / gray-green
|
||||
byte $BB, $CE '6 red / pink
|
||||
byte $3C, $0A '7 cyan / blue
|
||||
|
||||
{{
|
||||
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ TERMS OF USE: MIT License │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
|
||||
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
|
||||
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
|
||||
│is furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
|
||||
│ │
|
||||
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
|
||||
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
|
||||
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
}}
|
||||
596
samples/Propeller Spin/VGA.spin
Normal file
596
samples/Propeller Spin/VGA.spin
Normal file
@@ -0,0 +1,596 @@
|
||||
''***************************************
|
||||
''* VGA Driver v1.1 *
|
||||
''* Author: Chip Gracey *
|
||||
''* Copyright (c) 2006 Parallax, Inc. *
|
||||
''* See end of file for terms of use. *
|
||||
''***************************************
|
||||
|
||||
' v1.0 - 01 May 2006 - original version
|
||||
' v1.1 - 15 May 2006 - pixel tile size can now be 16 x 32 to enable more efficient
|
||||
' character displays utilizing the internal font - see 'vga_mode'
|
||||
|
||||
CON
|
||||
|
||||
paramcount = 21
|
||||
colortable = $180 'start of colortable inside cog
|
||||
|
||||
|
||||
VAR
|
||||
|
||||
long cog
|
||||
|
||||
|
||||
PUB start(vgaptr) : okay
|
||||
|
||||
'' Start VGA driver - starts a cog
|
||||
'' returns false if no cog available
|
||||
''
|
||||
'' vgaptr = pointer to VGA parameters
|
||||
|
||||
stop
|
||||
okay := cog := cognew(@entry, vgaptr) + 1
|
||||
|
||||
|
||||
PUB stop
|
||||
|
||||
'' Stop VGA driver - frees a cog
|
||||
|
||||
if cog
|
||||
cogstop(cog~ - 1)
|
||||
|
||||
|
||||
DAT
|
||||
|
||||
'********************************
|
||||
'* Assembly language VGA driver *
|
||||
'********************************
|
||||
|
||||
org
|
||||
'
|
||||
'
|
||||
' Entry
|
||||
'
|
||||
entry mov taskptr,#tasks 'reset tasks
|
||||
|
||||
mov x,#8 'perform task sections initially
|
||||
:init jmpret taskret,taskptr
|
||||
djnz x,#:init
|
||||
'
|
||||
'
|
||||
' Superfield
|
||||
'
|
||||
superfield mov hv,hvbase 'set hv
|
||||
|
||||
mov interlace,#0 'reset interlace
|
||||
|
||||
test _mode,#%0100 wz 'get interlace into nz
|
||||
'
|
||||
'
|
||||
' Field
|
||||
'
|
||||
field wrlong visible,par 'set status to visible
|
||||
|
||||
tjz vb,#:nobl 'do any visible back porch lines
|
||||
mov x,vb
|
||||
movd bcolor,#colortable
|
||||
call #blank_line
|
||||
:nobl
|
||||
mov screen,_screen 'point to first tile (upper-leftmost)
|
||||
mov y,_vt 'set vertical tiles
|
||||
:line mov vx,_vx 'set vertical expand
|
||||
:vert if_nz xor interlace,#1 'interlace skip?
|
||||
if_nz tjz interlace,#:skip
|
||||
|
||||
tjz hb,#:nobp 'do any visible back porch pixels
|
||||
mov vscl,hb
|
||||
waitvid colortable,#0
|
||||
:nobp
|
||||
mov x,_ht 'set horizontal tiles
|
||||
mov vscl,hx 'set horizontal expand
|
||||
|
||||
:tile rdword tile,screen 'read tile
|
||||
add tile,line 'set pointer bits into tile
|
||||
rol tile,#6 'read tile pixels
|
||||
rdlong pixels,tile '(8 clocks between reads)
|
||||
shr tile,#10+6 'set tile colors
|
||||
movd :color,tile
|
||||
add screen,#2 'point to next tile
|
||||
:color waitvid colortable,pixels 'pass colors and pixels to video
|
||||
djnz x,#:tile 'another tile?
|
||||
|
||||
sub screen,hc2x 'repoint to first tile in same line
|
||||
|
||||
tjz hf,#:nofp 'do any visible front porch pixels
|
||||
mov vscl,hf
|
||||
waitvid colortable,#0
|
||||
:nofp
|
||||
mov x,#1 'do hsync
|
||||
call #blank_hsync '(x=0)
|
||||
|
||||
:skip djnz vx,#:vert 'vertical expand?
|
||||
ror line,linerot 'set next line
|
||||
add line,lineadd wc
|
||||
rol line,linerot
|
||||
if_nc jmp #:line
|
||||
add screen,hc2x 'point to first tile in next line
|
||||
djnz y,#:line wc 'another tile line? (c=0)
|
||||
|
||||
tjz vf,#:nofl 'do any visible front porch lines
|
||||
mov x,vf
|
||||
movd bcolor,#colortable
|
||||
call #blank_line
|
||||
:nofl
|
||||
if_nz xor interlace,#1 wc,wz 'get interlace and field1 into nz (c=0/?)
|
||||
|
||||
if_z wrlong invisible,par 'unless interlace and field1, set status to invisible
|
||||
|
||||
mov taskptr,#tasks 'reset tasks
|
||||
|
||||
addx x,_vf wc 'do invisible front porch lines (x=0 before, c=0 after)
|
||||
call #blank_line
|
||||
|
||||
mov x,_vs 'do vsync lines
|
||||
call #blank_vsync
|
||||
|
||||
mov x,_vb 'do invisible back porch lines, except last
|
||||
call #blank_vsync
|
||||
|
||||
if_nz jmp #field 'if interlace and field1, display field2
|
||||
jmp #superfield 'else, new superfield
|
||||
'
|
||||
'
|
||||
' Blank line(s)
|
||||
'
|
||||
blank_vsync cmp interlace,#2 wc 'vsync (c=1)
|
||||
|
||||
blank_line mov vscl,h1 'blank line or vsync-interlace?
|
||||
if_nc add vscl,h2
|
||||
if_c_and_nz xor hv,#%01
|
||||
if_c waitvid hv,#0
|
||||
if_c mov vscl,h2 'blank line or vsync-normal?
|
||||
if_c_and_z xor hv,#%01
|
||||
bcolor waitvid hv,#0
|
||||
|
||||
if_nc jmpret taskret,taskptr 'call task section (z undisturbed)
|
||||
|
||||
blank_hsync mov vscl,_hf 'hsync, do invisible front porch pixels
|
||||
waitvid hv,#0
|
||||
|
||||
mov vscl,_hs 'do invisble sync pixels
|
||||
xor hv,#%10
|
||||
waitvid hv,#0
|
||||
|
||||
mov vscl,_hb 'do invisible back porch pixels
|
||||
xor hv,#%10
|
||||
waitvid hv,#0
|
||||
|
||||
djnz x,#blank_line wc '(c=0)
|
||||
|
||||
movd bcolor,#hv
|
||||
blank_hsync_ret
|
||||
blank_line_ret
|
||||
blank_vsync_ret ret
|
||||
'
|
||||
'
|
||||
' Tasks - performed in sections during invisible back porch lines
|
||||
'
|
||||
tasks mov t1,par 'load parameters
|
||||
movd :par,#_enable '(skip _status)
|
||||
mov t2,#paramcount - 1
|
||||
:load add t1,#4
|
||||
:par rdlong 0,t1
|
||||
add :par,d0
|
||||
djnz t2,#:load '+164
|
||||
|
||||
mov t1,#2 'set video pins and directions
|
||||
shl t1,_pins '(if video disabled, pins will drive low)
|
||||
sub t1,#1
|
||||
test _pins,#$20 wc
|
||||
and _pins,#$38
|
||||
shr t1,_pins
|
||||
movs vcfg,t1
|
||||
shl t1,_pins
|
||||
shr _pins,#3
|
||||
movd vcfg,_pins
|
||||
if_nc mov dira,t1
|
||||
if_nc mov dirb,#0
|
||||
if_c mov dira,#0
|
||||
if_c mov dirb,t1 '+14
|
||||
|
||||
tjz _enable,#disabled '+2, disabled?
|
||||
|
||||
jmpret taskptr,taskret '+1=181, break and return later
|
||||
|
||||
rdlong t1,#0 'make sure CLKFREQ => 16MHz
|
||||
shr t1,#1
|
||||
cmp t1,m8 wc
|
||||
if_c jmp #disabled '+8
|
||||
|
||||
min _rate,pllmin 'limit _rate to pll range
|
||||
max _rate,pllmax '+2
|
||||
|
||||
mov t1,#%00001_011 'set ctra configuration
|
||||
:max cmp m8,_rate wc 'adjust rate to be within 4MHz-8MHz
|
||||
if_c shr _rate,#1 '(vco will be within 64MHz-128MHz)
|
||||
if_c add t1,#%00000_001
|
||||
if_c jmp #:max
|
||||
:min cmp _rate,m4 wc
|
||||
if_c shl _rate,#1
|
||||
if_c sub x,#%00000_001
|
||||
if_c jmp #:min
|
||||
movi ctra,t1 '+22
|
||||
|
||||
rdlong t1,#0 'divide _rate/CLKFREQ and set frqa
|
||||
mov hvbase,#32+1
|
||||
:div cmpsub _rate,t1 wc
|
||||
rcl t2,#1
|
||||
shl _rate,#1
|
||||
djnz hvbase,#:div '(hvbase=0)
|
||||
mov frqa,t2 '+136
|
||||
|
||||
test _mode,#%0001 wc 'make hvbase
|
||||
muxnc hvbase,vmask
|
||||
test _mode,#%0010 wc
|
||||
muxnc hvbase,hmask '+4
|
||||
|
||||
jmpret taskptr,taskret '+1=173, break and return later
|
||||
|
||||
mov hx,_hx 'compute horizontal metrics
|
||||
shl hx,#8
|
||||
or hx,_hx
|
||||
shl hx,#4
|
||||
|
||||
mov hc2x,_ht
|
||||
shl hc2x,#1
|
||||
|
||||
mov h1,_hd
|
||||
neg h2,_hf
|
||||
sub h2,_hs
|
||||
sub h2,_hb
|
||||
sub h1,h2
|
||||
shr h1,#1 wc
|
||||
addx h2,h1
|
||||
|
||||
mov t1,_ht
|
||||
mov t2,_hx
|
||||
call #multiply
|
||||
mov hf,_hd
|
||||
sub hf,t1
|
||||
shr hf,#1 wc
|
||||
mov hb,_ho
|
||||
addx hb,hf
|
||||
sub hf,_ho '+59
|
||||
|
||||
mov t1,_vt 'compute vertical metrics
|
||||
mov t2,_vx
|
||||
call #multiply
|
||||
test _mode,#%1000 wc 'consider tile size
|
||||
muxc linerot,#1
|
||||
mov lineadd,lineinc
|
||||
if_c shr lineadd,#1
|
||||
if_c shl t1,#1
|
||||
test _mode,#%0100 wc 'consider interlace
|
||||
if_c shr t1,#1
|
||||
mov vf,_vd
|
||||
sub vf,t1
|
||||
shr vf,#1 wc
|
||||
neg vb,_vo
|
||||
addx vb,vf
|
||||
add vf,_vo '+53
|
||||
|
||||
movi vcfg,#%01100_000 '+1, set video configuration
|
||||
|
||||
:colors jmpret taskptr,taskret '+1=114/160, break and return later
|
||||
|
||||
mov t1,#13 'load next 13 colors into colortable
|
||||
:loop mov t2,:color '5 times = 65 (all 64 colors loaded)
|
||||
shr t2,#9-2
|
||||
and t2,#$FC
|
||||
add t2,_colors
|
||||
rdlong t2,t2
|
||||
and t2,colormask
|
||||
or t2,hvbase
|
||||
:color mov colortable,t2
|
||||
add :color,d0
|
||||
andn :color,d6
|
||||
djnz t1,#:loop '+158
|
||||
|
||||
jmp #:colors '+1, keep loading colors
|
||||
'
|
||||
'
|
||||
' Multiply t1 * t2 * 16 (t1, t2 = bytes)
|
||||
'
|
||||
multiply shl t2,#8+4-1
|
||||
|
||||
mov tile,#8
|
||||
:loop shr t1,#1 wc
|
||||
if_c add t1,t2
|
||||
djnz tile,#:loop
|
||||
|
||||
multiply_ret ret '+37
|
||||
'
|
||||
'
|
||||
' Disabled - reset status, nap ~4ms, try again
|
||||
'
|
||||
disabled mov ctra,#0 'reset ctra
|
||||
mov vcfg,#0 'reset video
|
||||
|
||||
wrlong outa,par 'set status to disabled
|
||||
|
||||
rdlong t1,#0 'get CLKFREQ
|
||||
shr t1,#8 'nap for ~4ms
|
||||
min t1,#3
|
||||
add t1,cnt
|
||||
waitcnt t1,#0
|
||||
|
||||
jmp #entry 'reload parameters
|
||||
'
|
||||
'
|
||||
' Initialized data
|
||||
'
|
||||
pllmin long 500_000 'pll lowest output frequency
|
||||
pllmax long 128_000_000 'pll highest output frequency
|
||||
m8 long 8_000_000 '*16 = 128MHz (pll vco max)
|
||||
m4 long 4_000_000 '*16 = 64MHz (pll vco min)
|
||||
d0 long 1 << 9 << 0
|
||||
d6 long 1 << 9 << 6
|
||||
invisible long 1
|
||||
visible long 2
|
||||
line long $00060000
|
||||
lineinc long $10000000
|
||||
linerot long 0
|
||||
vmask long $01010101
|
||||
hmask long $02020202
|
||||
colormask long $FCFCFCFC
|
||||
'
|
||||
'
|
||||
' Uninitialized data
|
||||
'
|
||||
taskptr res 1 'tasks
|
||||
taskret res 1
|
||||
t1 res 1
|
||||
t2 res 1
|
||||
|
||||
x res 1 'display
|
||||
y res 1
|
||||
hf res 1
|
||||
hb res 1
|
||||
vf res 1
|
||||
vb res 1
|
||||
hx res 1
|
||||
vx res 1
|
||||
hc2x res 1
|
||||
screen res 1
|
||||
tile res 1
|
||||
pixels res 1
|
||||
lineadd res 1
|
||||
interlace res 1
|
||||
hv res 1
|
||||
hvbase res 1
|
||||
h1 res 1
|
||||
h2 res 1
|
||||
'
|
||||
'
|
||||
' Parameter buffer
|
||||
'
|
||||
_enable res 1 '0/non-0 read-only
|
||||
_pins res 1 '%pppttt read-only
|
||||
_mode res 1 '%tihv read-only
|
||||
_screen res 1 '@word read-only
|
||||
_colors res 1 '@long read-only
|
||||
_ht res 1 '1+ read-only
|
||||
_vt res 1 '1+ read-only
|
||||
_hx res 1 '1+ read-only
|
||||
_vx res 1 '1+ read-only
|
||||
_ho res 1 '0+- read-only
|
||||
_vo res 1 '0+- read-only
|
||||
_hd res 1 '1+ read-only
|
||||
_hf res 1 '1+ read-only
|
||||
_hs res 1 '1+ read-only
|
||||
_hb res 1 '1+ read-only
|
||||
_vd res 1 '1+ read-only
|
||||
_vf res 1 '1+ read-only
|
||||
_vs res 1 '1+ read-only
|
||||
_vb res 1 '2+ read-only
|
||||
_rate res 1 '500_000+ read-only
|
||||
|
||||
fit colortable 'fit underneath colortable ($180-$1BF)
|
||||
|
||||
|
||||
''
|
||||
''___
|
||||
''VAR 'VGA parameters - 21 contiguous longs
|
||||
''
|
||||
'' long vga_status '0/1/2 = off/visible/invisible read-only
|
||||
'' long vga_enable '0/non-0 = off/on write-only
|
||||
'' long vga_pins '%pppttt = pins write-only
|
||||
'' long vga_mode '%tihv = tile,interlace,hpol,vpol write-only
|
||||
'' long vga_screen 'pointer to screen (words) write-only
|
||||
'' long vga_colors 'pointer to colors (longs) write-only
|
||||
'' long vga_ht 'horizontal tiles write-only
|
||||
'' long vga_vt 'vertical tiles write-only
|
||||
'' long vga_hx 'horizontal tile expansion write-only
|
||||
'' long vga_vx 'vertical tile expansion write-only
|
||||
'' long vga_ho 'horizontal offset write-only
|
||||
'' long vga_vo 'vertical offset write-only
|
||||
'' long vga_hd 'horizontal display ticks write-only
|
||||
'' long vga_hf 'horizontal front porch ticks write-only
|
||||
'' long vga_hs 'horizontal sync ticks write-only
|
||||
'' long vga_hb 'horizontal back porch ticks write-only
|
||||
'' long vga_vd 'vertical display lines write-only
|
||||
'' long vga_vf 'vertical front porch lines write-only
|
||||
'' long vga_vs 'vertical sync lines write-only
|
||||
'' long vga_vb 'vertical back porch lines write-only
|
||||
'' long vga_rate 'tick rate (Hz) write-only
|
||||
''
|
||||
''The preceding VAR section may be copied into your code.
|
||||
''After setting variables, do start(@vga_status) to start driver.
|
||||
''
|
||||
''All parameters are reloaded each superframe, allowing you to make live
|
||||
''changes. To minimize flicker, correlate changes with vga_status.
|
||||
''
|
||||
''Experimentation may be required to optimize some parameters.
|
||||
''
|
||||
''Parameter descriptions:
|
||||
'' __________
|
||||
'' vga_status
|
||||
''
|
||||
'' driver sets this to indicate status:
|
||||
'' 0: driver disabled (vga_enable = 0 or CLKFREQ < 16MHz)
|
||||
'' 1: currently outputting invisible sync data
|
||||
'' 2: currently outputting visible screen data
|
||||
'' __________
|
||||
'' vga_enable
|
||||
''
|
||||
'' 0: disable (pins will be driven low, reduces power)
|
||||
'' non-0: enable
|
||||
'' ________
|
||||
'' vga_pins
|
||||
''
|
||||
'' bits 5..3 select pin group:
|
||||
'' %000: pins 7..0
|
||||
'' %001: pins 15..8
|
||||
'' %010: pins 23..16
|
||||
'' %011: pins 31..24
|
||||
'' %100: pins 39..32
|
||||
'' %101: pins 47..40
|
||||
'' %110: pins 55..48
|
||||
'' %111: pins 63..56
|
||||
''
|
||||
'' bits 2..0 select top pin within group
|
||||
'' for example: %01111 (15) will use pins %01000-%01111 (8-15)
|
||||
'' ________
|
||||
'' vga_mode
|
||||
''
|
||||
'' bit 3 selects between 16x16 and 16x32 pixel tiles:
|
||||
'' 0: 16x16 pixel tiles (tileheight = 16)
|
||||
'' 1: 16x32 pixel tiles (tileheight = 32)
|
||||
''
|
||||
'' bit 2 controls interlace:
|
||||
'' 0: progressive scan (less flicker, good for motion, required for LCD monitors)
|
||||
'' 1: interlaced scan (allows you to double vga_vt, good for text)
|
||||
''
|
||||
'' bits 1 and 0 select horizontal and vertical sync polarity, respectively
|
||||
'' 0: active low
|
||||
'' 1: active high
|
||||
'' __________
|
||||
'' vga_screen
|
||||
''
|
||||
'' pointer to words which define screen contents (left-to-right, top-to-bottom)
|
||||
'' number of words must be vga_ht * vga_vt
|
||||
'' each word has two bitfields: a 6-bit colorset ptr and a 10-bit pixelgroup ptr
|
||||
'' bits 15..10: select the colorset* for the associated pixel tile
|
||||
'' bits 9..0: select the pixelgroup** address %ppppppppppcccc00 (p=address, c=0..15)
|
||||
''
|
||||
'' * colorsets are longs which each define four 8-bit colors
|
||||
''
|
||||
'' ** pixelgroups are <tileheight> longs which define (left-to-right, top-to-bottom) the 2-bit
|
||||
'' (four color) pixels that make up a 16x16 or a 16x32 pixel tile
|
||||
'' __________
|
||||
'' vga_colors
|
||||
''
|
||||
'' pointer to longs which define colorsets
|
||||
'' number of longs must be 1..64
|
||||
'' each long has four 8-bit fields which define colors for 2-bit (four color) pixels
|
||||
'' first long's bottom color is also used as the screen background color
|
||||
'' 8-bit color fields are as follows:
|
||||
'' bits 7..2: actual state of pins 7..2 within pin group*
|
||||
'' bits 1..0: don't care (used within driver for hsync and vsync)
|
||||
''
|
||||
'' * it is suggested that:
|
||||
'' bits/pins 7..6 are used for red
|
||||
'' bits/pins 5..4 are used for green
|
||||
'' bits/pins 3..2 are used for blue
|
||||
'' for each bit/pin set, sum 240 and 470-ohm resistors to form 75-ohm 1V signals
|
||||
'' connect signal sets to RED, GREEN, and BLUE on VGA connector
|
||||
'' always connect group pin 1 to HSYNC on VGA connector via 240-ohm resistor
|
||||
'' always connect group pin 0 to VSYNC on VGA connector via 240-ohm resistor
|
||||
'' ______
|
||||
'' vga_ht
|
||||
''
|
||||
'' horizontal number of pixel tiles - must be at least 1
|
||||
'' ______
|
||||
'' vga_vt
|
||||
''
|
||||
'' vertical number of pixel tiles - must be at least 1
|
||||
'' ______
|
||||
'' vga_hx
|
||||
''
|
||||
'' horizontal tile expansion factor - must be at least 1
|
||||
''
|
||||
'' make sure 16 * vga_ht * vga_hx + ||vga_ho is equal to or at least 16 less than vga_hd
|
||||
'' ______
|
||||
'' vga_vx
|
||||
''
|
||||
'' vertical tile expansion factor - must be at least 1
|
||||
''
|
||||
'' make sure <tileheight> * vga_vt * vga_vx + ||vga_vo does not exceed vga_vd
|
||||
'' (for interlace, use <tileheight> / 2 * vga_vt * vga_vx + ||vga_vo)
|
||||
'' ______
|
||||
'' vga_ho
|
||||
''
|
||||
'' horizontal offset in ticks - pos/neg value (0 recommended)
|
||||
'' shifts the display right/left
|
||||
'' ______
|
||||
'' vga_vo
|
||||
''
|
||||
'' vertical offset in lines - pos/neg value (0 recommended)
|
||||
'' shifts the display up/down
|
||||
'' ______
|
||||
'' vga_hd
|
||||
''
|
||||
'' horizontal display ticks
|
||||
'' ______
|
||||
'' vga_hf
|
||||
''
|
||||
'' horizontal front porch ticks
|
||||
'' ______
|
||||
'' vga_hs
|
||||
''
|
||||
'' horizontal sync ticks
|
||||
'' ______
|
||||
'' vga_hb
|
||||
''
|
||||
'' horizontal back porch ticks
|
||||
'' ______
|
||||
'' vga_vd
|
||||
''
|
||||
'' vertical display lines
|
||||
'' ______
|
||||
'' vga_vf
|
||||
''
|
||||
'' vertical front porch lines
|
||||
'' ______
|
||||
'' vga_vs
|
||||
''
|
||||
'' vertical sync lines
|
||||
'' ______
|
||||
'' vga_vb
|
||||
''
|
||||
'' vertical back porch lines
|
||||
'' ________
|
||||
'' vga_rate
|
||||
''
|
||||
'' tick rate in Hz
|
||||
''
|
||||
'' driver will limit value to be within 500KHz and 128MHz
|
||||
'' pixel rate (vga_rate / vga_hx) should be no more than CLKFREQ / 4
|
||||
|
||||
{{
|
||||
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ TERMS OF USE: MIT License │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
|
||||
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
|
||||
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
|
||||
│is furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
|
||||
│ │
|
||||
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
|
||||
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
|
||||
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
}}
|
||||
737
samples/Propeller Spin/VocalTract.spin
Normal file
737
samples/Propeller Spin/VocalTract.spin
Normal file
@@ -0,0 +1,737 @@
|
||||
{{
|
||||
┌───────────────────────────────────────────┬────────────────┬───────────────────────────────────┬─────────────────┐
|
||||
│ Vocal Tract v1.1 │ by Chip Gracey │ Copyright (c) 2006 Parallax, Inc. │ 28 October 2006 │
|
||||
├───────────────────────────────────────────┴────────────────┴───────────────────────────────────┴─────────────────┤
|
||||
│ │
|
||||
│ This object synthesizes a human vocal tract in real-time. It requires one cog and at least 80 MHz. │
|
||||
│ │
|
||||
│ The vocal tract is controlled via 13 single-byte parameters which must reside in the parent object: │
|
||||
│ │
|
||||
│ VAR byte aa,ga,gp,vp,vr,f1,f2,f3,f4,na,nf,fa,ff 'vocal tract parameters │
|
||||
│ │
|
||||
│ │
|
||||
│ aa │
|
||||
│ ┌────────────┐ │
|
||||
│ │ ASPIRATION ├──┐ │
|
||||
│ └────────────┘ │ f1 f2 f3 f4 na nf │
|
||||
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌───────┐ │
|
||||
│ +┣──┤ F1 ├──┤ F2 ├──┤ F3 ├──┤ F4 ├──┤ NASAL ├──┐ │
|
||||
│ ga gp └────┘ └────┘ └────┘ └────┘ └───────┘ │ │
|
||||
│ ┌─────────┐ │ │
|
||||
│ │ GLOTTAL ├──┘ +┣── OUTPUT │
|
||||
│ └────┬────┘ fa ff │
|
||||
│ ┌───────────┐ │ │
|
||||
│ vp │ vr │ FRICATION ├──┘ │
|
||||
│ ┌────┴────┐ └───────────┘ │
|
||||
│ │ VIBRATO │ │
|
||||
│ └─────────┘ │
|
||||
│ │
|
||||
│ │
|
||||
│ ┌───────────┬──────────────────────┬─────────────┬────────────────────────────────────────────────┐ │
|
||||
│ │ parameter │ description │ unit │ notes │ │
|
||||
│ ├───────────┼──────────────────────┼─────────────┼────────────────────────────────────────────────┤ │
|
||||
│ │ aa │ aspiration amplitude │ 0..255 │ breath volume: silent..loud, linear │ │
|
||||
│ │ ga │ glottal amplitude │ 0..255 │ voice volume: silent..loud, linear │ │
|
||||
│ │ gp │ glottal pitch │ 1/48 octave │ voice pitch: 100 ─ 110.00Hz (musical note A2) │ │
|
||||
│ │ vp │ vibrato pitch │ 1/48 octave │ voice vibrato pitch: 48 ─ ± 1/2 octave swing │ │
|
||||
│ │ vr │ vibrato rate │ 0.0763 Hz │ voice vibrato rate: 52 ─ 4 Hz │ │
|
||||
│ │ f1 │ formant1 frequency │ 19.53 Hz │ 1st resonator frequency: 40 ─ 781 Hz │ │
|
||||
│ │ f2 │ formant2 frequency │ 19.53 Hz │ 2nd resonator frequency: 56 ─ 1094 Hz │ │
|
||||
│ │ f3 │ formant3 frequency │ 19.53 Hz │ 3rd resonator frequency: 128 ─ 2500 Hz │ │
|
||||
│ │ f4 │ formant4 frequency │ 19.53 Hz │ 4th resonator frequency: 179 ─ 3496 Hz │ │
|
||||
│ │ na │ nasal amplitude │ 0..255 │ anti-resonator level: off..on, linear │ │
|
||||
│ │ nf │ nasal frequency │ 19.53 Hz │ anti-resonator frequency: 102 ─ 1992 Hz │ │
|
||||
│ │ fa │ frication amplitude │ 0..255 │ white noise volume: silent..loud, linear │ │
|
||||
│ │ ff │ frication frequency │ 39.06 Hz │ white noise frequency: 60 ─ 2344 Hz ("Sh") │ │
|
||||
│ └───────────┴──────────────────────┴─────────────┴────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ The parent object alternately modifies one or more of these parameters and then calls the go(time) method to │
|
||||
│ queue the entire 13-parameter frame for feeding to the vocal tract. The vocal tract will load one queued frame │
|
||||
│ after another and smoothly interpolate between them over specified amounts of time without interruption. Up to │
|
||||
│ eight frames will be queued in order to relax the frame-generation timing requirement of the parent object. If │
|
||||
│ eight frames are queued, the parent must then wait to queue another frame. If the vocal tract runs out of │
|
||||
│ frames, it will continue generating samples based on the last frame. When a new frame is queued, it will │
|
||||
│ immediately load it and begin inter-polating towards it. │
|
||||
│ │
|
||||
│ The vocal tract generates audio samples at a continuous rate of 20KHz. These samples can be output to pins via │
|
||||
│ delta-modulation for RC filtering or direct transducer driving. An FM aural subcarrier can also be generated for │
|
||||
│ inclusion into a TV broadcast controlled by another cog. Regardless of any output mode, samples are always │
|
||||
│ streamed into a special variable so that other objects can access them in real-time. │
|
||||
│ │
|
||||
│ In order to achieve optimal sound quality, it is worthwhile to maximize amplitudes such as 'ga' to the point │
|
||||
│ just shy of numerical overflow. Numerical overflow results in high-amplitude noise bursts which are quite │
|
||||
│ disruptive. The closeness of 'f1'-'f4' and their relationship to 'gp' can greatly influence the amount of 'ga' │
|
||||
│ that can be applied before overflow occurs. You must determine through experimentation what the limits are. By │
|
||||
│ pushing 'ga' close to the overflow point, you will maximize the signal-to-noise ratio of the vocal tract, │
|
||||
│ resulting in the highest quality sound. Once your vocal tract programming is complete, the attenuation level │
|
||||
│ can then be used to reduce the overall output in 3dB steps while preserving the signal-to-noise ratio. │
|
||||
│ │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ Revision History v1.0 released 26 October 2006 │
|
||||
│ │
|
||||
│ v1.1 If the vocal tract runs out of frames, its internal parameters will now be brought all the way to the │
|
||||
│ last frame's values. Before, they were left one interpolation point shy, and then set to the last frame's │
|
||||
│ values at the start of the next frame. For continuous frames this was trivial, but it posed a problem │
|
||||
│ during frame gaps because the internal parameters would get stalled at transition points just shy of the │
|
||||
│ last frame's values. This change makes the vocal tract behave more sensibly during frame gaps. │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
}}
|
||||
CON
|
||||
|
||||
frame_buffers = 8 'frame buffers (2n)
|
||||
|
||||
frame_bytes = 3 {for stepsize} + 13 {for aa..ff} '16 bytes per frame
|
||||
frame_longs = frame_bytes / 4 '4 longs per frame
|
||||
|
||||
frame_buffer_bytes = frame_bytes * frame_buffers
|
||||
frame_buffer_longs = frame_longs * frame_buffers
|
||||
|
||||
|
||||
VAR
|
||||
|
||||
long cog, tract, pace
|
||||
|
||||
long index, attenuation, sample '3 longs ...must
|
||||
long dira_, dirb_, ctra_, ctrb_, frqa_, cnt_ '6 longs ...be
|
||||
long frames[frame_buffer_longs] 'many longs ...contiguous
|
||||
|
||||
|
||||
PUB start(tract_ptr, pos_pin, neg_pin, fm_offset) : okay
|
||||
|
||||
'' Start vocal tract driver - starts a cog
|
||||
'' returns false if no cog available
|
||||
''
|
||||
'' tract_ptr = pointer to vocal tract parameters (13 bytes)
|
||||
'' pos_pin = positive delta-modulation pin (-1 to disable)
|
||||
'' neg_pin = negative delta-modulation pin (pos_pin must also be enabled, -1 to disable)
|
||||
'' fm_offset = offset frequency for fm aural subcarrier generation (-1 to disable, 4_500_000 for NTSC)
|
||||
|
||||
'Reset driver
|
||||
stop
|
||||
|
||||
'Remember vocal tract parameters pointer
|
||||
tract := tract_ptr
|
||||
|
||||
'Initialize pace to 100%
|
||||
pace := 100
|
||||
|
||||
'If delta-modulation pin(s) enabled, ready output(s) and ready ctrb for duty mode
|
||||
if pos_pin > -1
|
||||
dira_[pos_pin >> 5 & 1] |= |< pos_pin
|
||||
ctrb_ := $18000000 + pos_pin & $3F
|
||||
if neg_pin > -1
|
||||
dira_[neg_pin >> 5 & 1] |= |< neg_pin
|
||||
ctrb_ += $04000000 + (neg_pin & $3F) << 9
|
||||
|
||||
'If fm offset is valid, ready ctra for pll mode with divide-by-16 (else disabled)
|
||||
if fm_offset > -1
|
||||
ctra_ := $05800000
|
||||
|
||||
'Ready frqa value for fm offset
|
||||
repeat 33
|
||||
frqa_ <<= 1
|
||||
if fm_offset => clkfreq
|
||||
fm_offset -= clkfreq
|
||||
frqa_++
|
||||
fm_offset <<= 1
|
||||
|
||||
'Ready 20KHz sample period
|
||||
cnt_ := clkfreq / 20_000
|
||||
|
||||
'Launch vocal tract cog
|
||||
return cog := cognew(@entry, @attenuation) + 1
|
||||
|
||||
|
||||
PUB stop
|
||||
|
||||
'' Stop vocal tract driver - frees a cog
|
||||
|
||||
'If already running, stop vocal tract cog
|
||||
if cog
|
||||
cogstop(cog~ - 1)
|
||||
|
||||
'Reset variables and buffers
|
||||
longfill(@index, 0, constant(3 + 6 + frame_buffer_longs))
|
||||
|
||||
|
||||
PUB set_attenuation(level)
|
||||
|
||||
'' Set master attenuation level (0..7, initially 0)
|
||||
|
||||
attenuation := level
|
||||
|
||||
|
||||
PUB set_pace(percentage)
|
||||
|
||||
'' Set pace to some percentage (initially 100)
|
||||
|
||||
pace := percentage
|
||||
|
||||
|
||||
PUB go(time)
|
||||
|
||||
'' Queue current parameters to transition over time
|
||||
''
|
||||
'' actual time = integer(time * 100 / pace) #> 2 * 700µs (at least 1400µs, see set_pace)
|
||||
|
||||
'Wait until frame available (first long will be zeroed)
|
||||
repeat while frames[index]
|
||||
|
||||
'Load parameters into frame
|
||||
bytemove(@frames[index] + 3, tract, 13)
|
||||
|
||||
'Write stepsize into frame (non-0 alerts vocal tract that frame is ready)
|
||||
frames[index] |= $01000000 / (time * 100 / pace #> 2)
|
||||
|
||||
'Increment frame index
|
||||
index := (index + frame_longs) & constant(frame_buffer_longs - 1)
|
||||
|
||||
|
||||
PUB full : status
|
||||
|
||||
'' Returns true if the parameter queue is full
|
||||
'' (useful for checking if "go" would have to wait)
|
||||
|
||||
return frames[index]
|
||||
|
||||
|
||||
PUB empty : status | i
|
||||
|
||||
'' Returns true if the parameter queue is empty
|
||||
'' (useful for detecting when the vocal tract is finished)
|
||||
|
||||
repeat i from 0 to constant(frame_buffers - 1)
|
||||
if frames[i * frame_longs]
|
||||
return {false}
|
||||
return true
|
||||
|
||||
|
||||
PUB sample_ptr : ptr
|
||||
|
||||
'' Returns the address of the long which receives the audio samples in real-time
|
||||
'' (signed 32-bit values updated at 20KHz)
|
||||
|
||||
return @sample
|
||||
|
||||
|
||||
PUB aural_id : id
|
||||
|
||||
'' Returns the id of the cog executing the vocal tract algorithm
|
||||
'' (for connecting a broadcast tv driver with the aural subcarrier)
|
||||
|
||||
return cog - 1
|
||||
|
||||
|
||||
DAT
|
||||
|
||||
' ┌──────────────────┐
|
||||
' │ Initialization │
|
||||
' └──────────────────┘
|
||||
|
||||
entry org
|
||||
|
||||
:zero mov reserves,#0 'zero all reserved data
|
||||
add :zero,d0
|
||||
djnz clear_cnt,#:zero
|
||||
|
||||
mov t1,#2*15 'assemble 15 multiply steps into reserves
|
||||
:minst mov mult_steps,mult_step '(saves hub memory)
|
||||
add :minst,d0s0
|
||||
test t1,#1 wc
|
||||
if_c sub :minst,#2
|
||||
djnz t1,#:minst
|
||||
mov mult_ret,antilog_ret 'write 'ret' after last instruction
|
||||
|
||||
mov t1,#13 'assemble 13 cordic steps into reserves
|
||||
:cstep mov t2,#8 '(saves hub memory)
|
||||
:cinst mov cordic_steps,cordic_step
|
||||
add :cinst,d0s0
|
||||
djnz t2,#:cinst
|
||||
sub :cinst,#8
|
||||
add cordic_dx,#1
|
||||
add cordic_dy,#1
|
||||
add cordic_a,#1
|
||||
djnz t1,#:cstep
|
||||
mov cordic_ret,antilog_ret 'write 'ret' over last instruction
|
||||
|
||||
mov t1,par 'get dira/dirb/ctra/ctrb
|
||||
add t1,#2*4
|
||||
mov t2,#4
|
||||
:regs rdlong dira,t1
|
||||
add t1,#4
|
||||
add :regs,d0
|
||||
djnz t2,#:regs
|
||||
|
||||
rdlong frqa_center,t1 'get frqa center
|
||||
|
||||
add t1,#4 'get cnt ticks
|
||||
rdlong cnt_ticks,t1
|
||||
|
||||
mov cnt_value,cnt 'prepare for initial waitcnt
|
||||
add cnt_value,cnt_ticks
|
||||
|
||||
|
||||
' ┌────────────────────┐
|
||||
' │ Vocal Tract Loop │
|
||||
' └────────────────────┘
|
||||
|
||||
' Wait for next sample period, then output sample
|
||||
|
||||
loop waitcnt cnt_value,cnt_ticks 'wait for sample period
|
||||
|
||||
rdlong t1,par 'perform master attenuation
|
||||
sar x,t1
|
||||
|
||||
mov t1,x 'update fm aural subcarrier for tv broadcast
|
||||
sar t1,#10
|
||||
add t1,frqa_center
|
||||
mov frqa,t1
|
||||
|
||||
mov t1,x 'update duty cycle output for pin driving
|
||||
add t1,h80000000
|
||||
mov frqb,t1
|
||||
|
||||
mov t1,par 'update sample receiver in main memory
|
||||
add t1,#1*4
|
||||
wrlong x,t1
|
||||
|
||||
' White noise source
|
||||
|
||||
test lfsr,lfsr_taps wc 'iterate lfsr three times
|
||||
rcl lfsr,#1
|
||||
test lfsr,lfsr_taps wc
|
||||
rcl lfsr,#1
|
||||
test lfsr,lfsr_taps wc
|
||||
rcl lfsr,#1
|
||||
|
||||
' Aspiration
|
||||
|
||||
mov t1,aa 'aspiration amplitude
|
||||
mov t2,lfsr
|
||||
call #mult
|
||||
|
||||
sar t1,#8 'set x
|
||||
mov x,t1
|
||||
|
||||
' Vibrato
|
||||
|
||||
mov t1,vr 'vibrato rate
|
||||
shr t1,#10
|
||||
add vphase,t1
|
||||
|
||||
mov t1,vp 'vibrato pitch
|
||||
mov t2,vphase
|
||||
call #sine
|
||||
|
||||
add t1,gp 'sum glottal pitch (+) into vibrato pitch (+/-)
|
||||
|
||||
' Glottal pulse
|
||||
|
||||
shr t1,#2 'divide final pitch by 3 to mesh with
|
||||
mov t2,t1 '...12 notes/octave musical scale
|
||||
shr t2,#2 '(multiply by %0.0101010101010101)
|
||||
add t1,t2
|
||||
mov t2,t1
|
||||
shr t2,#4
|
||||
add t1,t2
|
||||
mov t2,t1
|
||||
shr t2,#8
|
||||
add t1,t2
|
||||
|
||||
add t1,tune 'tune scale so that gp=100 produces 110.00Hz (A2)
|
||||
|
||||
call #antilog 'convert pitch (log frequency) to phase delta
|
||||
add gphase,t2
|
||||
|
||||
mov t1,gphase 'convert phase to glottal pulse sample
|
||||
call #antilog
|
||||
sub t2,h40000000
|
||||
mov t1,ga
|
||||
call #sine
|
||||
|
||||
sar t1,#6 'add to x
|
||||
add x,t1
|
||||
|
||||
' Vocal tract formants
|
||||
|
||||
mov y,#0 'reset y
|
||||
|
||||
mov a,f1 'formant1, sum and rotate (x,y)
|
||||
add x,f1x
|
||||
add y,f1y
|
||||
call #cordic
|
||||
mov f1x,x
|
||||
mov f1y,y
|
||||
|
||||
mov a,f2 'formant2, sum and rotate (x,y)
|
||||
add x,f2x
|
||||
add y,f2y
|
||||
call #cordic
|
||||
mov f2x,x
|
||||
mov f2y,y
|
||||
|
||||
mov a,f3 'formant3, sum and rotate (x,y)
|
||||
add x,f3x
|
||||
add y,f3y
|
||||
call #cordic
|
||||
mov f3x,x
|
||||
mov f3y,y
|
||||
|
||||
mov a,f4 'formant4, sum and rotate (x,y)
|
||||
add x,f4x
|
||||
add y,f4y
|
||||
call #cordic
|
||||
mov f4x,x
|
||||
mov f4y,y
|
||||
|
||||
' Nasal anti-formant
|
||||
|
||||
add nx,x 'subtract from x (nx negated)
|
||||
|
||||
mov a,nf 'nasal frequency
|
||||
call #cordic
|
||||
|
||||
mov t1,na 'nasal amplitude
|
||||
mov t2,x
|
||||
call #mult
|
||||
|
||||
mov x,nx 'restore x
|
||||
neg nx,t1 'negate nx
|
||||
|
||||
' Frication
|
||||
|
||||
mov t1,lfsr 'phase noise
|
||||
sar t1,#3
|
||||
add fphase,t1
|
||||
sar t1,#1
|
||||
add fphase,t1
|
||||
|
||||
mov t1,ff 'frication frequency
|
||||
shr t1,#1
|
||||
add fphase,t1
|
||||
|
||||
mov t1,fa 'frication amplitude
|
||||
mov t2,fphase
|
||||
call #sine
|
||||
|
||||
add x,t1 'add to x
|
||||
|
||||
' Handle frame
|
||||
|
||||
jmp :ret 'run segment of frame handler, return to loop
|
||||
|
||||
|
||||
' ┌─────────────────┐
|
||||
' │ Frame Handler │
|
||||
' └─────────────────┘
|
||||
|
||||
:ret long :wait 'pointer to next frame handler routine
|
||||
|
||||
|
||||
:wait jmpret :ret,#loop '(6 or 17.5 cycles)
|
||||
mov frame_ptr,par 'check for next frame
|
||||
add frame_ptr,#8*4 'point past miscellaneous data
|
||||
add frame_ptr,frame_index 'point to start of frame
|
||||
rdlong step_size,frame_ptr 'get stepsize
|
||||
and step_size,h00FFFFFF wz 'isolate stepsize and check if not 0
|
||||
if_nz jmp #:next 'if not 0, next frame ready
|
||||
|
||||
|
||||
mov :final1,:finali 'no frame ready, ready to finalize parameters
|
||||
mov frame_cnt,#13 'iterate aa..ff
|
||||
|
||||
:final jmpret :ret,#loop '(13.5 or 4 cycles)
|
||||
:final1 mov par_curr,par_next 'current parameter = next parameter
|
||||
add :final1,d0s0 'update pointers
|
||||
djnz frame_cnt,#:final 'another parameter?
|
||||
|
||||
jmp #:wait 'check for next frame
|
||||
|
||||
|
||||
:next add step_size,#1 'next frame ready, insure accurate accumulation
|
||||
mov step_acc,step_size 'initialize step accumulator
|
||||
|
||||
|
||||
movs :set1,#par_next 'ready to get parameters and steps for aa..ff
|
||||
movd :set2,#par_curr
|
||||
movd :set3,#par_next
|
||||
movd :set4,#par_step
|
||||
add frame_ptr,#3 'point to first parameter
|
||||
mov frame_cnt,#13 'iterate aa..ff
|
||||
|
||||
:set jmpret :ret,#loop '(19.5 or 46.5 cycles)
|
||||
rdbyte t1,frame_ptr 'get new parameter
|
||||
shl t1,#24 'msb justify
|
||||
:set1 mov t2,par_next 'get next parameter
|
||||
:set2 mov par_curr,t2 'current parameter = next parameter
|
||||
:set3 mov par_next,t1 'next parameter = new parameter
|
||||
sub t1,t2 wc 'get next-current delta with sign in c
|
||||
negc t1,t1 'make delta absolute (by c, not msb)
|
||||
rcl vscl,#1 wz, nr 'save sign into nz (vscl unaffected)
|
||||
|
||||
mov t2,#8 'multiply delta by step size
|
||||
:mult shl t1,#1 wc
|
||||
if_c add t1,step_size
|
||||
djnz t2,#:mult
|
||||
|
||||
:set4 negnz par_step,t1 'set signed step
|
||||
|
||||
add :set1,#1 'update pointers for next parameter+step
|
||||
add :set2,d0
|
||||
add :set3,d0
|
||||
add :set4,d0
|
||||
add frame_ptr,#1
|
||||
djnz frame_cnt,#:set 'another parameter?
|
||||
|
||||
|
||||
:stepframe jmpret :ret,#loop '(47.5 or 8 cycles)
|
||||
mov :step1,:stepi 'ready to step parameters
|
||||
mov frame_cnt,#13 'iterate aa..ff
|
||||
|
||||
:step jmpret :ret,#loop '(3 or 4 cycles)
|
||||
:step1 add par_curr,par_step 'step parameter
|
||||
add :step1,d0s0 'update pointers for next parameter+step
|
||||
djnz frame_cnt,#:step 'another parameter?
|
||||
|
||||
add step_acc,step_size 'accumulate frame steps
|
||||
test step_acc,h01000000 wc 'check for frame steps done
|
||||
if_nc jmp #:stepframe 'another frame step?
|
||||
|
||||
|
||||
sub frame_ptr,#frame_bytes 'zero stepsize in frame to signal frame done
|
||||
wrlong vscl,frame_ptr
|
||||
|
||||
add frame_index,#frame_bytes'point to next frame
|
||||
and frame_index,#frame_buffer_bytes - 1
|
||||
|
||||
jmp #:wait 'check for next frame
|
||||
|
||||
|
||||
:finali mov par_curr,par_next 'instruction used to finalize parameters
|
||||
:stepi add par_curr,par_step 'instruction used to step parameters
|
||||
|
||||
|
||||
' ┌────────────────────┐
|
||||
' │ Math Subroutines │
|
||||
' └────────────────────┘
|
||||
|
||||
' Antilog
|
||||
'
|
||||
' in: t1 = log (top 4 bits = whole number, next 11 bits = fraction)
|
||||
'
|
||||
' out: t2 = antilog ($00010000..$FFEA0000)
|
||||
|
||||
antilog mov t2,t1
|
||||
shr t2,#16 'position 11-bit fraction
|
||||
shr t1,#16+12 'position 4-bit whole number
|
||||
and t2,h00000FFE 'get table offset
|
||||
or t2,h0000D000 'get table base
|
||||
rdword t2,t2 'lookup fractional antilog
|
||||
or t2,h00010000 'insert leading bit
|
||||
shl t2,t1 'shift up by whole number
|
||||
|
||||
antilog_ret ret
|
||||
|
||||
|
||||
' Scaled sine
|
||||
'
|
||||
' in: t1 = unsigned scale (15 top bits used)
|
||||
' t2 = angle (13 top bits used)
|
||||
'
|
||||
' out: t1 = 17-bit * 15-bit scaled sine ($80014000..$7FFEC000)
|
||||
|
||||
sine shr t2,#32-13 'get 13-bit angle
|
||||
test t2,h00001000 wz 'get sine quadrant 3|4 into nz
|
||||
test t2,h00000800 wc 'get sine quadrant 2|4 into c
|
||||
negc t2,t2 'if sine quadrant 2|4, negate table offset
|
||||
or t2,h00007000 'insert sine table base address >> 1
|
||||
shl t2,#1 'shift left to get final word address
|
||||
rdword t2,t2 'read sine word from table
|
||||
negnz t2,t2 'if quadrant 3|4, negate word
|
||||
shl t2,#15 'msb-justify result
|
||||
'multiply follows...
|
||||
|
||||
' Multiply
|
||||
'
|
||||
' in: t1 = unsigned multiplier (15 top bits used)
|
||||
' t2 = signed multiplicand (17 top bits used)
|
||||
'
|
||||
' out: t1 = 32-bit signed product
|
||||
|
||||
mult shr t1,#32-15 'position unsigned multiplier
|
||||
|
||||
sar t2,#15 'position signed multiplicand
|
||||
shl t2,#15-1
|
||||
|
||||
jmp #mult_steps 'do multiply steps
|
||||
|
||||
|
||||
mult_step sar t1,#1 wc 'multiply step that gets assembled into reserves (x15)
|
||||
if_c add t1,t2
|
||||
|
||||
|
||||
' Cordic rotation
|
||||
'
|
||||
' in: a = 0 to <90 degree angle (~13 top bits used)
|
||||
' x,y = signed coordinates
|
||||
'
|
||||
' out: x,y = scaled and rotated signed coordinates
|
||||
|
||||
cordic sar x,#1 'multiply (x,y) by %0.10011001 (0.60725 * 0.984)
|
||||
mov t1,x '...for cordic pre-scaling and slight damping
|
||||
sar t1,#3
|
||||
add x,t1
|
||||
mov t1,x
|
||||
sar t1,#4
|
||||
add x,t1
|
||||
|
||||
sar y,#1
|
||||
mov t1,y
|
||||
sar t1,#3
|
||||
add y,t1
|
||||
mov t1,y
|
||||
sar t1,#4
|
||||
add y,t1
|
||||
|
||||
mov t1,x 'do first cordic step
|
||||
sub x,y
|
||||
add y,t1
|
||||
sub a,h80000000 wc
|
||||
|
||||
jmp #cordic_steps+1 'do subsequent cordic steps (skip first instruction)
|
||||
|
||||
|
||||
cordic_step mov a,a wc 'cordic step that gets assembled into reserves (x13)
|
||||
mov t1,y
|
||||
cordic_dx sar t1,#1 '(source incremented for each step)
|
||||
mov t2,x
|
||||
cordic_dy sar t2,#1 '(source incremented for each step)
|
||||
sumnc x,t1
|
||||
sumc y,t2
|
||||
cordic_a sumnc a,cordic_delta '(source incremented for each step)
|
||||
|
||||
|
||||
' ┌────────────────┐
|
||||
' │ Defined Data │
|
||||
' └────────────────┘
|
||||
|
||||
tune long $66920000 'scale tuned to 110.00Hz at gp=100 (manually calibrated)
|
||||
|
||||
lfsr long 1 'linear feedback shift register for noise generation
|
||||
lfsr_taps long $80061000
|
||||
|
||||
cordic_delta long $4B901476 'cordic angle deltas (first is h80000000)
|
||||
long $27ECE16D
|
||||
long $14444750
|
||||
long $0A2C350C
|
||||
long $05175F85
|
||||
long $028BD879
|
||||
long $0145F154
|
||||
long $00A2F94D
|
||||
long $00517CBB
|
||||
long $0028BE60
|
||||
long $00145F30
|
||||
long $000A2F98
|
||||
|
||||
h80000000 long $80000000 'miscellaneous constants greater than 9 bits
|
||||
h40000000 long $40000000
|
||||
h01000000 long $01000000
|
||||
h00FFFFFF long $00FFFFFF
|
||||
h00010000 long $00010000
|
||||
h0000D000 long $0000D000
|
||||
h00007000 long $00007000
|
||||
h00001000 long $00001000
|
||||
h00000FFE long $00000FFE
|
||||
h00000800 long $00000800
|
||||
|
||||
d0 long $00000200 'destination/source field increments
|
||||
d0s0 long $00000201
|
||||
|
||||
clear_cnt long $1F0 - reserves 'number of reserved registers to clear on startup
|
||||
|
||||
|
||||
' ┌──────────────────────────────────────────────────┐
|
||||
' │ Undefined Data (zeroed by initialization code) │
|
||||
' └──────────────────────────────────────────────────┘
|
||||
|
||||
reserves
|
||||
|
||||
frqa_center res 1 'reserved registers that get cleared on startup
|
||||
|
||||
cnt_ticks res 1
|
||||
cnt_value res 1
|
||||
|
||||
frame_index res 1
|
||||
frame_ptr res 1
|
||||
frame_cnt res 1
|
||||
|
||||
step_size res 1
|
||||
step_acc res 1
|
||||
|
||||
vphase res 1
|
||||
gphase res 1
|
||||
fphase res 1
|
||||
|
||||
f1x res 1
|
||||
f1y res 1
|
||||
f2x res 1
|
||||
f2y res 1
|
||||
f3x res 1
|
||||
f3y res 1
|
||||
f4x res 1
|
||||
f4y res 1
|
||||
nx res 1
|
||||
|
||||
a res 1
|
||||
x res 1
|
||||
y res 1
|
||||
|
||||
t1 res 1
|
||||
t2 res 1
|
||||
|
||||
par_curr '*** current parameters
|
||||
aa res 1 'aspiration amplitude
|
||||
ga res 1 'glottal amplitude
|
||||
gp res 1 'glottal pitch
|
||||
vp res 1 'vibrato pitch
|
||||
vr res 1 'vibrato rate
|
||||
f1 res 1 'formant1 frequency
|
||||
f2 res 1 'formant2 frequency
|
||||
f3 res 1 'formant3 frequency
|
||||
f4 res 1 'formant4 frequency
|
||||
na res 1 'nasal amplitude
|
||||
nf res 1 'nasal frequency
|
||||
fa res 1 'frication amplitude
|
||||
ff res 1 'frication frequency
|
||||
|
||||
par_next res 13 '*** next parameters
|
||||
par_step res 13 '*** parameter steps
|
||||
|
||||
|
||||
mult_steps res 2 * 15 'assembly area for multiply steps w/ret
|
||||
mult_ret
|
||||
sine_ret res 1
|
||||
|
||||
cordic_steps res 8 * 13 - 1 'assembly area for cordic steps w/ret
|
||||
cordic_ret res 1
|
||||
|
||||
{{
|
||||
|
||||
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ TERMS OF USE: MIT License │
|
||||
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
|
||||
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
|
||||
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
|
||||
│is furnished to do so, subject to the following conditions: │
|
||||
│ │
|
||||
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
|
||||
│ │
|
||||
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
|
||||
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
|
||||
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
|
||||
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
}}
|
||||
63
samples/Python/AdditiveWave.pyde
Normal file
63
samples/Python/AdditiveWave.pyde
Normal file
@@ -0,0 +1,63 @@
|
||||
"""
|
||||
Additive Wave
|
||||
by Daniel Shiffman.
|
||||
|
||||
Create a more complex wave by adding two waves together.
|
||||
"""
|
||||
|
||||
xspacing = 8 # How far apart should each horizontal location be spaced
|
||||
maxwaves = 4 # total # of waves to add together
|
||||
theta = 0.0
|
||||
|
||||
amplitude = [] # Height of wave
|
||||
# Value for incrementing X, to be calculated as a function of period and
|
||||
# xspacing
|
||||
dx = []
|
||||
yvalues = []
|
||||
|
||||
|
||||
def setup():
|
||||
size(640, 360)
|
||||
frameRate(30)
|
||||
colorMode(RGB, 255, 255, 255, 100)
|
||||
w = width + 16
|
||||
for i in range(maxwaves):
|
||||
amplitude.append(random(10, 30))
|
||||
period = random(100, 300) # How many pixels before the wave repeats
|
||||
dx.append((TWO_PI / period) * xspacing)
|
||||
for _ in range(w / xspacing + 1):
|
||||
yvalues.append(0.0)
|
||||
|
||||
|
||||
def draw():
|
||||
background(0)
|
||||
calcWave()
|
||||
renderWave()
|
||||
|
||||
|
||||
def calcWave():
|
||||
# Increment theta (try different values for 'angular velocity' here
|
||||
theta += 0.02
|
||||
# Set all height values to zero
|
||||
for i in range(len(yvalues)):
|
||||
yvalues[i] = 0
|
||||
# Accumulate wave height values
|
||||
for j in range(maxwaves):
|
||||
x = theta
|
||||
for i in range(len(yvalues)):
|
||||
# Every other wave is cosine instead of sine
|
||||
if j % 2 == 0:
|
||||
yvalues[i] += sin(x) * amplitude[j]
|
||||
else:
|
||||
yvalues[i] += cos(x) * amplitude[j]
|
||||
x += dx[j]
|
||||
|
||||
|
||||
def renderWave():
|
||||
# A simple way to draw the wave with an ellipse at each location
|
||||
noStroke()
|
||||
fill(255, 50)
|
||||
ellipseMode(CENTER)
|
||||
for x, v in enumerate(yvalues):
|
||||
ellipse(x * xspacing, height / 2 + v, 16, 16)
|
||||
|
||||
241
samples/Python/Cinema4DPythonPlugin.pyp
Normal file
241
samples/Python/Cinema4DPythonPlugin.pyp
Normal file
@@ -0,0 +1,241 @@
|
||||
#
|
||||
# Cinema 4D Python Plugin Source file
|
||||
# https://github.com/nr-plugins/nr-xpresso-alignment-tools
|
||||
#
|
||||
|
||||
# coding: utf-8
|
||||
#
|
||||
# Copyright (C) 2012, Niklas Rosenstein
|
||||
# Licensed under the GNU General Public License
|
||||
#
|
||||
# XPAT - XPresso Alignment Tools
|
||||
# ==============================
|
||||
#
|
||||
# The XPAT plugin provides tools for aligning nodes in the Cinema 4D
|
||||
# XPresso Editor, improving readability of complex XPresso set-ups
|
||||
# immensively.
|
||||
#
|
||||
# Requirements:
|
||||
# - MAXON Cinema 4D R13+
|
||||
# - Python `c4dtools` library. Get it from
|
||||
# http://github.com/NiklasRosenstein/c4dtools
|
||||
#
|
||||
# Author: Niklas Rosenstein <rosensteinniklas@gmail.com>
|
||||
# Version: 1.1 (01/06/2012)
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import c4d
|
||||
import c4dtools
|
||||
import itertools
|
||||
|
||||
from c4d.modules import graphview as gv
|
||||
from c4dtools.misc import graphnode
|
||||
|
||||
res, importer = c4dtools.prepare(__file__, __res__)
|
||||
settings = c4dtools.helpers.Attributor({
|
||||
'options_filename': res.file('config.json'),
|
||||
})
|
||||
|
||||
def align_nodes(nodes, mode, spacing):
|
||||
r"""
|
||||
Aligns the passed nodes horizontally and apply the minimum spacing
|
||||
between them.
|
||||
"""
|
||||
|
||||
modes = ['horizontal', 'vertical']
|
||||
if not nodes:
|
||||
return
|
||||
if mode not in modes:
|
||||
raise ValueError('invalid mode, choices are: ' + ', '.join(modes))
|
||||
|
||||
get_0 = lambda x: x.x
|
||||
get_1 = lambda x: x.y
|
||||
set_0 = lambda x, v: setattr(x, 'x', v)
|
||||
set_1 = lambda x, v: setattr(x, 'y', v)
|
||||
|
||||
if mode == 'vertical':
|
||||
get_0, get_1 = get_1, get_0
|
||||
set_0, set_1 = set_1, set_0
|
||||
|
||||
nodes = [graphnode.GraphNode(n) for n in nodes]
|
||||
nodes.sort(key=lambda n: get_0(n.position))
|
||||
midpoint = graphnode.find_nodes_mid(nodes)
|
||||
|
||||
# Apply the spacing between the nodes relative to the coordinate-systems
|
||||
# origin. We can offset them later because we now the nodes' midpoint
|
||||
# already.
|
||||
first_position = nodes[0].position
|
||||
new_positions = []
|
||||
prev_offset = 0
|
||||
for node in nodes:
|
||||
# Compute the relative position of the node.
|
||||
position = node.position
|
||||
set_0(position, get_0(position) - get_0(first_position))
|
||||
|
||||
# Obtain it's size and check if the node needs to be re-placed.
|
||||
size = node.size
|
||||
if get_0(position) < prev_offset:
|
||||
set_0(position, prev_offset)
|
||||
prev_offset += spacing + get_0(size)
|
||||
else:
|
||||
prev_offset = get_0(position) + get_0(size) + spacing
|
||||
|
||||
set_1(position, get_1(midpoint))
|
||||
new_positions.append(position)
|
||||
|
||||
# Center the nodes again.
|
||||
bbox_size = prev_offset - spacing
|
||||
bbox_size_2 = bbox_size * 0.5
|
||||
for node, position in itertools.izip(nodes, new_positions):
|
||||
# TODO: Here is some issue with offsetting the nodes. Some value
|
||||
# dependent on the spacing must be added here to not make the nodes
|
||||
# move horizontally/vertically although they have already been
|
||||
# aligned.
|
||||
set_0(position, get_0(midpoint) + get_0(position) - bbox_size_2 + spacing)
|
||||
node.position = position
|
||||
|
||||
def align_nodes_shortcut(mode, spacing):
|
||||
master = gv.GetMaster(0)
|
||||
if not master:
|
||||
return
|
||||
|
||||
root = master.GetRoot()
|
||||
if not root:
|
||||
return
|
||||
|
||||
nodes = graphnode.find_selected_nodes(root)
|
||||
if nodes:
|
||||
master.AddUndo()
|
||||
align_nodes(nodes, mode, spacing)
|
||||
c4d.EventAdd()
|
||||
|
||||
return True
|
||||
|
||||
class XPAT_Options(c4dtools.helpers.Attributor):
|
||||
r"""
|
||||
This class organizes the options for the XPAT plugin, i.e.
|
||||
validating, loading and saving.
|
||||
"""
|
||||
|
||||
defaults = {
|
||||
'hspace': 50,
|
||||
'vspace': 20,
|
||||
}
|
||||
|
||||
def __init__(self, filename=None):
|
||||
super(XPAT_Options, self).__init__()
|
||||
self.load(filename)
|
||||
|
||||
def load(self, filename=None):
|
||||
r"""
|
||||
Load the options from file pointed to by filename. If filename
|
||||
is None, it defaults to the filename defined in options in the
|
||||
global scope.
|
||||
"""
|
||||
|
||||
if filename is None:
|
||||
filename = settings.options_filename
|
||||
|
||||
if os.path.isfile(filename):
|
||||
self.dict_ = self.defaults.copy()
|
||||
with open(filename, 'rb') as fp:
|
||||
self.dict_.update(json.load(fp))
|
||||
else:
|
||||
self.dict_ = self.defaults.copy()
|
||||
self.save()
|
||||
|
||||
def save(self, filename=None):
|
||||
r"""
|
||||
Save the options defined in XPAT_Options instance to HD.
|
||||
"""
|
||||
|
||||
if filename is None:
|
||||
filename = settings.options_filename
|
||||
|
||||
values = dict((k, v) for k, v in self.dict_.iteritems()
|
||||
if k in self.defaults)
|
||||
with open(filename, 'wb') as fp:
|
||||
json.dump(values, fp)
|
||||
|
||||
class XPAT_OptionsDialog(c4d.gui.GeDialog):
|
||||
r"""
|
||||
This class implements the behavior of the XPAT options dialog,
|
||||
taking care of storing the options on the HD and loading them
|
||||
again on startup.
|
||||
"""
|
||||
|
||||
# c4d.gui.GeDialog
|
||||
|
||||
def CreateLayout(self):
|
||||
return self.LoadDialogResource(res.DLG_OPTIONS)
|
||||
|
||||
def InitValues(self):
|
||||
self.SetLong(res.EDT_HSPACE, options.hspace)
|
||||
self.SetLong(res.EDT_VSPACE, options.vspace)
|
||||
return True
|
||||
|
||||
def Command(self, id, msg):
|
||||
if id == res.BTN_SAVE:
|
||||
options.hspace = self.GetLong(res.EDT_HSPACE)
|
||||
options.vspace = self.GetLong(res.EDT_VSPACE)
|
||||
options.save()
|
||||
self.Close()
|
||||
return True
|
||||
|
||||
class XPAT_Command_OpenOptionsDialog(c4dtools.plugins.Command):
|
||||
r"""
|
||||
This Cinema 4D CommandData plugin opens the XPAT options dialog
|
||||
when being executed.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(XPAT_Command_OpenOptionsDialog, self).__init__()
|
||||
self._dialog = None
|
||||
|
||||
@property
|
||||
def dialog(self):
|
||||
if not self._dialog:
|
||||
self._dialog = XPAT_OptionsDialog()
|
||||
return self._dialog
|
||||
|
||||
# c4dtools.plugins.Command
|
||||
|
||||
PLUGIN_ID = 1029621
|
||||
PLUGIN_NAME = res.string.XPAT_COMMAND_OPENOPTIONSDIALOG()
|
||||
PLUGIN_HELP = res.string.XPAT_COMMAND_OPENOPTIONSDIALOG_HELP()
|
||||
|
||||
# c4d.gui.CommandData
|
||||
|
||||
def Execute(self, doc):
|
||||
return self.dialog.Open(c4d.DLG_TYPE_MODAL)
|
||||
|
||||
class XPAT_Command_AlignHorizontal(c4dtools.plugins.Command):
|
||||
|
||||
PLUGIN_ID = 1029538
|
||||
PLUGIN_NAME = res.string.XPAT_COMMAND_ALIGNHORIZONTAL()
|
||||
PLUGIN_ICON = res.file('xpresso-align-h.png')
|
||||
PLUGIN_HELP = res.string.XPAT_COMMAND_ALIGNHORIZONTAL_HELP()
|
||||
|
||||
def Execute(self, doc):
|
||||
align_nodes_shortcut('horizontal', options.hspace)
|
||||
return True
|
||||
|
||||
class XPAT_Command_AlignVertical(c4dtools.plugins.Command):
|
||||
|
||||
PLUGIN_ID = 1029539
|
||||
PLUGIN_NAME = res.string.XPAT_COMMAND_ALIGNVERTICAL()
|
||||
PLUGIN_ICON = res.file('xpresso-align-v.png')
|
||||
PLUGIN_HELP = res.string.XPAT_COMMAND_ALIGNVERTICAL_HELP()
|
||||
|
||||
def Execute(self, doc):
|
||||
align_nodes_shortcut('vertical', options.vspace)
|
||||
return True
|
||||
|
||||
options = XPAT_Options()
|
||||
|
||||
if __name__ == '__main__':
|
||||
c4dtools.plugins.main()
|
||||
|
||||
|
||||
29
samples/Python/MoveEye.pyde
Normal file
29
samples/Python/MoveEye.pyde
Normal file
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
* Move Eye.
|
||||
* by Simon Greenwold.
|
||||
*
|
||||
* The camera lifts up (controlled by mouseY) while looking at the same point.
|
||||
"""
|
||||
|
||||
|
||||
def setup():
|
||||
size(640, 360, P3D)
|
||||
fill(204)
|
||||
|
||||
|
||||
def draw():
|
||||
lights()
|
||||
background(0)
|
||||
|
||||
# Change height of the camera with mouseY
|
||||
camera(30.0, mouseY, 220.0, # eyeX, eyeY, eyeZ
|
||||
0.0, 0.0, 0.0, # centerX, centerY, centerZ
|
||||
0.0, 1.0, 0.0) # upX, upY, upZ
|
||||
|
||||
noStroke()
|
||||
box(90)
|
||||
stroke(255)
|
||||
line(-100, 0, 0, 100, 0, 0)
|
||||
line(0, -100, 0, 0, 100, 0)
|
||||
line(0, 0, -100, 0, 0, 100)
|
||||
|
||||
30
samples/QMake/complex.pro
Normal file
30
samples/QMake/complex.pro
Normal file
@@ -0,0 +1,30 @@
|
||||
# This QMake file is complex, as it usese
|
||||
# boolean operators and function calls
|
||||
|
||||
QT += core gui
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
# We could use some OpenGL right now
|
||||
contains(QT_CONFIG, opengl) | contains(QT_CONFIG, opengles2) {
|
||||
QT += opengl
|
||||
} else {
|
||||
DEFINES += QT_NO_OPENGL
|
||||
}
|
||||
|
||||
TEMPLATE = app
|
||||
win32 {
|
||||
TARGET = BlahApp
|
||||
RC_FILE = Resources/winres.rc
|
||||
}
|
||||
!win32 { TARGET = blahapp }
|
||||
|
||||
# Let's add a PRI file!
|
||||
include(functions.pri)
|
||||
|
||||
SOURCES += file.cpp
|
||||
|
||||
HEADERS += file.h
|
||||
|
||||
FORMS += file.ui
|
||||
|
||||
RESOURCES += res.qrc
|
||||
8
samples/QMake/functions.pri
Normal file
8
samples/QMake/functions.pri
Normal file
@@ -0,0 +1,8 @@
|
||||
# QMake include file that calls some functions
|
||||
# and does nothing else...
|
||||
|
||||
exists(.git/HEAD) {
|
||||
system(git rev-parse HEAD >rev.txt)
|
||||
} else {
|
||||
system(echo ThisIsNotAGitRepo >rev.txt)
|
||||
}
|
||||
2
samples/QMake/qmake.script!
Normal file
2
samples/QMake/qmake.script!
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/qmake
|
||||
message(This is QMake.)
|
||||
17
samples/QMake/simple.pro
Normal file
17
samples/QMake/simple.pro
Normal file
@@ -0,0 +1,17 @@
|
||||
# Simple QMake file
|
||||
|
||||
CONFIG += qt
|
||||
QT += core gui
|
||||
TEMPLATE = app
|
||||
TARGET = simpleapp
|
||||
|
||||
SOURCES += file.cpp \
|
||||
file2.c \
|
||||
This/Is/Folder/file3.cpp
|
||||
|
||||
HEADERS += file.h \
|
||||
file2.h \
|
||||
This/Is/Folder/file3.h
|
||||
|
||||
FORMS += This/Is/Folder/file3.ui \
|
||||
Test.ui
|
||||
29
samples/R/df.residual.r
Normal file
29
samples/R/df.residual.r
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
df.residual.mira <- function(object, ...) {
|
||||
fit <- object$analyses[[1]]
|
||||
return(df.residual(fit))
|
||||
}
|
||||
|
||||
df.residual.lme <- function(object, ...) {
|
||||
return(object$fixDF[["X"]][1])
|
||||
}
|
||||
|
||||
df.residual.mer <- function(object, ...) {
|
||||
return(sum(object@dims[2:4] * c(1, -1, -1)) + 1)
|
||||
}
|
||||
|
||||
df.residual.default <- function(object, q = 1.3, ...) {
|
||||
df <- object$df.residual
|
||||
if (!is.null(df))
|
||||
return(df)
|
||||
|
||||
mk <- try(c <- coef(object), silent = TRUE)
|
||||
mn <- try(f <- fitted(object), silent = TRUE)
|
||||
if (inherits(mk, "try-error") | inherits(mn, "try-error"))
|
||||
return(NULL)
|
||||
n <- ifelse(is.data.frame(f) | is.matrix(f), nrow(f), length(f))
|
||||
k <- length(c)
|
||||
if (k == 0 | n == 0)
|
||||
return(NULL)
|
||||
return(max(1, n - q * k))
|
||||
}
|
||||
101
samples/R/filenames/expr-dist
Executable file
101
samples/R/filenames/expr-dist
Executable file
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env Rscript
|
||||
|
||||
# Copyright (c) 2013 Daniel S. Standage, released under MIT license
|
||||
#
|
||||
# expr-dist: plot distributions of expression values before and after
|
||||
# normalization; visually confirm that normalization worked
|
||||
# as expected
|
||||
#
|
||||
# Program input is a matrix of expression values, each row corresponding to a
|
||||
# molecule (gene, transcript, etc) and each row corresponding to that molecule's
|
||||
# expression level or abundance. The program expects the rows and columns to be
|
||||
# named, and was tested primarily on output produced by the
|
||||
# 'rsem-generate-data-matrix' script distributed with the RSEM package.
|
||||
#
|
||||
# The program plots the distributions of the logged expression values by sample
|
||||
# as provided, then normalizes the values, and finally plots the distribution of
|
||||
# the logged normalized expression values by sample. The expectation is that all
|
||||
# samples' distributions will have a similar shape but different medians prior
|
||||
# to normalization, and that post normalization they will all have an identical
|
||||
# median to facilitate cross-sample comparison.
|
||||
|
||||
|
||||
# MedianNorm function borrowed from the EBSeq library version 1.1.6
|
||||
# See http://www.bioconductor.org/packages/devel/bioc/html/EBSeq.html
|
||||
MedianNorm <- function(data)
|
||||
{
|
||||
geomeans <- exp( rowMeans(log(data)) )
|
||||
apply(data, 2, function(cnts) median((cnts/geomeans)[geomeans > 0]))
|
||||
}
|
||||
|
||||
library("getopt")
|
||||
print_usage <- function(file=stderr())
|
||||
{
|
||||
cat("
|
||||
expr-dist: see source code for full description
|
||||
Usage: expr-dist [options] < expr-matrix.txt
|
||||
Options:
|
||||
-h|--help: print this help message and exit
|
||||
-o|--out: STRING prefix for output files; default is 'expr-dist'
|
||||
-r|--res: INT resolution (dpi) of generated graphics; default is 150
|
||||
-t|--height: INT height (pixels) of generated graphics; default is 1200
|
||||
-w|--width: INT width (pixels) of generated graphics; default is 1200
|
||||
-y|--ylim: REAL the visible range of the Y axis depends on the first
|
||||
distribution plotted; if other distributions are getting
|
||||
cut off, use this setting to override the default\n\n")
|
||||
}
|
||||
|
||||
spec <- matrix( c("help", 'h', 0, "logical",
|
||||
"out", 'o', 1, "character",
|
||||
"res", 'r', 1, "integer",
|
||||
"height", 't', 1, "integer",
|
||||
"width", 'w', 1, "integer",
|
||||
"ylim", 'y', 1, "double"),
|
||||
byrow=TRUE, ncol=4)
|
||||
opt <- getopt(spec)
|
||||
if(!is.null(opt$help))
|
||||
{
|
||||
print_usage(file=stdout())
|
||||
q(status=1)
|
||||
}
|
||||
if(is.null(opt$height)) { opt$height <- 1200 }
|
||||
if(is.null(opt$out)) { opt$out <- "expr-dist" }
|
||||
if(is.null(opt$res)) { opt$res <- 150 }
|
||||
if(is.null(opt$width)) { opt$width <- 1200 }
|
||||
if(!is.null(opt$ylim)) { opt$ylim <- c(0, opt$ylim) }
|
||||
|
||||
# Load data, determine number of samples
|
||||
data <- read.table(file("stdin"), header=TRUE, sep="\t", quote="")
|
||||
nsamp <- dim(data)[2] - 1
|
||||
data <- data[,1:nsamp+1]
|
||||
|
||||
# Plot distribution of expression values before normalization
|
||||
outfile <- sprintf("%s-median.png", opt$out)
|
||||
png(outfile, height=opt$height, width=opt$width, res=opt$res)
|
||||
h <- hist(log(data[,1]), plot=FALSE)
|
||||
plot(h$mids, h$density, type="l", col=rainbow(nsamp)[1], main="",
|
||||
xlab="Log expression value", ylab="Proportion of molecules", ylim=opt$ylim)
|
||||
for(i in 2:nsamp)
|
||||
{
|
||||
h <- hist(log(data[,i]), plot=FALSE)
|
||||
lines(h$mids, h$density, col=rainbow(nsamp)[i])
|
||||
}
|
||||
devnum <- dev.off()
|
||||
|
||||
# Normalize by median
|
||||
size.factors <- MedianNorm(data.matrix(data))
|
||||
data.norm <- t(apply(data, 1, function(x){ x / size.factors }))
|
||||
|
||||
# Plot distribution of normalized expression values
|
||||
outfile <- sprintf("%s-median-norm.png", opt$out)
|
||||
png(outfile, height=opt$height, width=opt$width, res=opt$res)
|
||||
h <- hist(log(data.norm[,1]), plot=FALSE)
|
||||
plot(h$mids, h$density, type="l", col=rainbow(nsamp)[1], main="",
|
||||
xlab="Log normalized expression value", ylab="Proportion of molecules",
|
||||
ylim=opt$ylim)
|
||||
for(i in 2:nsamp)
|
||||
{
|
||||
h <- hist(log(data.norm[,i]), plot=FALSE)
|
||||
lines(h$mids, h$density, col=rainbow(nsamp)[i])
|
||||
}
|
||||
devnum <- dev.off()
|
||||
201
samples/R/import.r
Normal file
201
samples/R/import.r
Normal file
@@ -0,0 +1,201 @@
|
||||
#' Import a module into the current scope
|
||||
#'
|
||||
#' \code{module = import('module')} imports a specified module and makes its
|
||||
#' code available via the environment-like object it returns.
|
||||
#'
|
||||
#' @param module an identifier specifying the full module path
|
||||
#' @param attach if \code{TRUE}, attach the newly loaded module to the object
|
||||
#' search path (see \code{Details})
|
||||
#' @param attach_operators if \code{TRUE}, attach operators of module to the
|
||||
#' object search path, even if \code{attach} is \code{FALSE}
|
||||
#' @return the loaded module environment (invisible)
|
||||
#'
|
||||
#' @details Modules are loaded in an isolated environment which is returned, and
|
||||
#' optionally attached to the object search path of the current scope (if
|
||||
#' argument \code{attach} is \code{TRUE}).
|
||||
#' \code{attach} defaults to \code{FALSE}. However, in interactive code it is
|
||||
#' often helpful to attach packages by default. Therefore, in interactive code
|
||||
#' invoked directly from the terminal only (i.e. not within modules),
|
||||
#' \code{attach} defaults to the value of \code{options('import.attach')}, which
|
||||
#' can be set to \code{TRUE} or \code{FALSE} depending on the user’s preference.
|
||||
#'
|
||||
#' \code{attach_operators} causes \emph{operators} to be attached by default,
|
||||
#' because operators can only be invoked in R if they re found in the search
|
||||
#' path. Not attaching them therefore drastically limits a module’s usefulness.
|
||||
#'
|
||||
#' Modules are searched in the module search path \code{options('import.path')}.
|
||||
#' This is a vector of paths to consider, from the highest to the lowest
|
||||
#' priority. The current directory is \emph{always} considered first. That is,
|
||||
#' if a file \code{a.r} exists both in the current directory and in a module
|
||||
#' search path, the local file \code{./a.r} will be loaded.
|
||||
#'
|
||||
#' Module names can be fully qualified to refer to nested paths. See
|
||||
#' \code{Examples}.
|
||||
#'
|
||||
#' @note Unlike for packages, attaching happens \emph{locally}: if
|
||||
#' \code{import} is executed in the global environment, the effect is the same.
|
||||
#' Otherwise, the imported module is inserted as the parent of the current
|
||||
#' \code{environment()}. When used (globally) \emph{inside} a module, the newly
|
||||
#' imported module is only available inside the module’s search path, not
|
||||
#' outside it (nor in other modules which might be loaded).
|
||||
#'
|
||||
#' @examples
|
||||
#' # `a.r` is a file in the local directory containing a function `f`.
|
||||
#' a = import('a')
|
||||
#' a$f()
|
||||
#'
|
||||
#' # b/c.r is a file in path `b`, containing a function `g`.
|
||||
#' import('b/c', attach = TRUE)
|
||||
#' g() # No module name qualification necessary
|
||||
#'
|
||||
#' @seealso \code{unload}
|
||||
#' @seealso \code{reload}
|
||||
#' @seealso \code{module_name}
|
||||
#' @export
|
||||
import = function (module, attach, attach_operators = TRUE) {
|
||||
module = substitute(module)
|
||||
stopifnot(inherits(module, 'name'))
|
||||
|
||||
if (missing(attach)) {
|
||||
attach = if (interactive() && is.null(module_name()))
|
||||
getOption('import.attach', FALSE)
|
||||
else
|
||||
FALSE
|
||||
}
|
||||
|
||||
stopifnot(class(attach) == 'logical' && length(attach) == 1)
|
||||
|
||||
module_path = try(find_module(module), silent = TRUE)
|
||||
|
||||
if (inherits(module_path, 'try-error'))
|
||||
stop(attr(module_path, 'condition')$message)
|
||||
|
||||
containing_modules = module_init_files(module, module_path)
|
||||
mapply(do_import, names(containing_modules), containing_modules)
|
||||
|
||||
mod_ns = do_import(as.character(module), module_path)
|
||||
module_parent = parent.frame()
|
||||
mod_env = exhibit_namespace(mod_ns, as.character(module), module_parent)
|
||||
|
||||
if (attach) {
|
||||
if (identical(module_parent, .GlobalEnv))
|
||||
attach(mod_env, name = environmentName(mod_env))
|
||||
else
|
||||
parent.env(module_parent) = mod_env
|
||||
}
|
||||
else if (attach_operators)
|
||||
export_operators(mod_ns, module_parent)
|
||||
|
||||
invisible(mod_env)
|
||||
}
|
||||
|
||||
do_import = function (module_name, module_path) {
|
||||
if (is_module_loaded(module_path))
|
||||
return(get_loaded_module(module_path))
|
||||
|
||||
# The namespace contains a module’s content. This schema is very much like
|
||||
# R package organisation.
|
||||
# A good resource for this is:
|
||||
# <http://obeautifulcode.com/R/How-R-Searches-And-Finds-Stuff/>
|
||||
namespace = structure(new.env(parent = .BaseNamespaceEnv),
|
||||
name = paste('namespace', module_name, sep = ':'),
|
||||
path = module_path,
|
||||
class = c('namespace', 'environment'))
|
||||
local(source(attr(environment(), 'path'), chdir = TRUE, local = TRUE),
|
||||
envir = namespace)
|
||||
cache_module(namespace)
|
||||
namespace
|
||||
}
|
||||
|
||||
exhibit_namespace = function (namespace, name, parent) {
|
||||
exported_functions = lsf.str(namespace)
|
||||
# Skip one parent environment because this module is hooked into the chain
|
||||
# between the calling environment and its ancestor, thus sitting in its
|
||||
# local object search path.
|
||||
structure(list2env(sapply(exported_functions, get, envir = namespace),
|
||||
parent = parent.env(parent)),
|
||||
name = paste('module', name, sep = ':'),
|
||||
path = module_path(namespace),
|
||||
class = c('module', 'environment'))
|
||||
}
|
||||
|
||||
export_operators = function (namespace, parent) {
|
||||
# `$` cannot be overwritten, but it is generic so S3 variants of it can be
|
||||
# defined. We therefore test it as well.
|
||||
ops = c('+', '-', '*', '/', '^', '**', '&', '|', ':', '::', ':::', '$', '=',
|
||||
'<-', '<<-', '==', '<', '<=', '>', '>=', '!=', '~', '&&', '||')
|
||||
|
||||
is_predefined = function (f) f %in% ops
|
||||
|
||||
is_op = function (f) {
|
||||
prefix = strsplit(f, '\\.')[[1]][1]
|
||||
is_predefined(prefix) || grepl('^%.*%$', prefix)
|
||||
}
|
||||
|
||||
operators = Filter(is_op, lsf.str(namespace))
|
||||
name = module_name(namespace)
|
||||
# Skip one parent environment because this module is hooked into the chain
|
||||
# between the calling environment and its ancestor, thus sitting in its
|
||||
# local object search path.
|
||||
op_env = structure(list2env(sapply(operators, get, envir = namespace),
|
||||
parent = parent.env(parent)),
|
||||
name = paste('operators', name, sep = ':'),
|
||||
path = module_path(namespace),
|
||||
class = c('module', 'environment'))
|
||||
|
||||
if (identical(parent, .GlobalEnv))
|
||||
attach(op_env, name = environmentName(op_env))
|
||||
else
|
||||
parent.env(parent) = op_env
|
||||
}
|
||||
|
||||
#' Unload a given module
|
||||
#'
|
||||
#' Unset the module variable that is being passed as a parameter, and remove the
|
||||
#' loaded module from cache.
|
||||
#' @param module reference to the module which should be unloaded
|
||||
#' @note Any other references to the loaded modules remain unchanged, and will
|
||||
#' still work. However, subsequently importing the module again will reload its
|
||||
#' source files, which would not have happened without \code{unload}.
|
||||
#' Unloading modules is primarily useful for testing during development, and
|
||||
#' should not be used in production code.
|
||||
#'
|
||||
#' \code{unload} does not currently detach environments.
|
||||
#' @seealso \code{import}
|
||||
#' @seealso \code{reload}
|
||||
#' @export
|
||||
unload = function (module) {
|
||||
stopifnot(inherits(module, 'module'))
|
||||
module_ref = as.character(substitute(module))
|
||||
rm(list = module_path(module), envir = .loaded_modules)
|
||||
# unset the module reference in its scope, i.e. the caller’s environment or
|
||||
# some parent thereof.
|
||||
rm(list = module_ref, envir = parent.frame(), inherits = TRUE)
|
||||
}
|
||||
|
||||
#' Reload a given module
|
||||
#'
|
||||
#' Remove the loaded module from the cache, forcing a reload. The newly reloaded
|
||||
#' module is assigned to the module reference in the calling scope.
|
||||
#' @param module reference to the module which should be unloaded
|
||||
#' @note Any other references to the loaded modules remain unchanged, and will
|
||||
#' still work. Reloading modules is primarily useful for testing during
|
||||
#' development, and should not be used in production code.
|
||||
#'
|
||||
#' \code{reload} does not work correctly with attached environments.
|
||||
#' @seealso \code{import}
|
||||
#' @seealso \code{unload}
|
||||
#' @export
|
||||
reload = function (module) {
|
||||
stopifnot(inherits(module, 'module'))
|
||||
module_ref = as.character(substitute(module))
|
||||
module_path = module_path(module)
|
||||
module_name = module_name(module)
|
||||
rm(list = module_path, envir = .loaded_modules)
|
||||
#' @TODO Once we have `attach`, need also to take care of the search path
|
||||
#' and whatnot.
|
||||
mod_ns = do_import(module_name, module_path)
|
||||
module_parent = parent.frame()
|
||||
mod_env = exhibit_namespace(mod_ns, module_ref, module_parent)
|
||||
assign(module_ref, mod_env, envir = module_parent, inherits = TRUE)
|
||||
}
|
||||
25
samples/R/scholar.Rd
Normal file
25
samples/R/scholar.Rd
Normal file
@@ -0,0 +1,25 @@
|
||||
\docType{package}
|
||||
\name{scholar}
|
||||
\alias{scholar}
|
||||
\alias{scholar-package}
|
||||
\title{scholar}
|
||||
\source{
|
||||
The package reads data from
|
||||
\url{http://scholar.google.com}. Dates and citation
|
||||
counts are estimated and are determined automatically by
|
||||
a computer program. Use at your own risk.
|
||||
}
|
||||
\description{
|
||||
The \code{scholar} package provides functions to extract
|
||||
citation data from Google Scholar. There are also
|
||||
convenience functions for comparing multiple scholars and
|
||||
predicting h-index scores based on past publication
|
||||
records.
|
||||
}
|
||||
\note{
|
||||
A complementary set of Google Scholar functions can be
|
||||
found at
|
||||
\url{http://biostat.jhsph.edu/~jleek/code/googleCite.r}.
|
||||
The \code{scholar} package was developed independently.
|
||||
}
|
||||
|
||||
257
samples/Red/example.red
Normal file
257
samples/Red/example.red
Normal file
@@ -0,0 +1,257 @@
|
||||
Red [
|
||||
Title: "Red console"
|
||||
Author: ["Nenad Rakocevic" "Kaj de Vos"]
|
||||
File: %console.red
|
||||
Tabs: 4
|
||||
Rights: "Copyright (C) 2012-2013 Nenad Rakocevic. All rights reserved."
|
||||
License: {
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
See https://github.com/dockimbel/Red/blob/master/BSL-License.txt
|
||||
}
|
||||
Purpose: "Just some code for testing Pygments colorizer"
|
||||
Language: http://www.red-lang.org/
|
||||
]
|
||||
|
||||
#system-global [
|
||||
#either OS = 'Windows [
|
||||
#import [
|
||||
"kernel32.dll" stdcall [
|
||||
AttachConsole: "AttachConsole" [
|
||||
processID [integer!]
|
||||
return: [integer!]
|
||||
]
|
||||
SetConsoleTitle: "SetConsoleTitleA" [
|
||||
title [c-string!]
|
||||
return: [integer!]
|
||||
]
|
||||
ReadConsole: "ReadConsoleA" [
|
||||
consoleInput [integer!]
|
||||
buffer [byte-ptr!]
|
||||
charsToRead [integer!]
|
||||
numberOfChars [int-ptr!]
|
||||
inputControl [int-ptr!]
|
||||
return: [integer!]
|
||||
]
|
||||
]
|
||||
]
|
||||
line-buffer-size: 16 * 1024
|
||||
line-buffer: allocate line-buffer-size
|
||||
][
|
||||
#switch OS [
|
||||
MacOSX [
|
||||
#define ReadLine-library "libreadline.dylib"
|
||||
]
|
||||
#default [
|
||||
#define ReadLine-library "libreadline.so.6"
|
||||
#define History-library "libhistory.so.6"
|
||||
]
|
||||
]
|
||||
#import [
|
||||
ReadLine-library cdecl [
|
||||
read-line: "readline" [ ; Read a line from the console.
|
||||
prompt [c-string!]
|
||||
return: [c-string!]
|
||||
]
|
||||
rl-bind-key: "rl_bind_key" [
|
||||
key [integer!]
|
||||
command [integer!]
|
||||
return: [integer!]
|
||||
]
|
||||
rl-insert: "rl_insert" [
|
||||
count [integer!]
|
||||
key [integer!]
|
||||
return: [integer!]
|
||||
]
|
||||
]
|
||||
#if OS <> 'MacOSX [
|
||||
History-library cdecl [
|
||||
add-history: "add_history" [ ; Add line to the history.
|
||||
line [c-string!]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
rl-insert-wrapper: func [
|
||||
[cdecl]
|
||||
count [integer!]
|
||||
key [integer!]
|
||||
return: [integer!]
|
||||
][
|
||||
rl-insert count key
|
||||
]
|
||||
|
||||
]
|
||||
]
|
||||
|
||||
Windows?: system/platform = 'Windows
|
||||
|
||||
read-argument: routine [
|
||||
/local
|
||||
args [str-array!]
|
||||
str [red-string!]
|
||||
][
|
||||
if system/args-count <> 2 [
|
||||
SET_RETURN(none-value)
|
||||
exit
|
||||
]
|
||||
args: system/args-list + 1 ;-- skip binary filename
|
||||
str: simple-io/read-txt args/item
|
||||
SET_RETURN(str)
|
||||
]
|
||||
|
||||
init-console: routine [
|
||||
str [string!]
|
||||
/local
|
||||
ret
|
||||
][
|
||||
#either OS = 'Windows [
|
||||
;ret: AttachConsole -1
|
||||
;if zero? ret [print-line "ReadConsole failed!" halt]
|
||||
|
||||
ret: SetConsoleTitle as c-string! string/rs-head str
|
||||
if zero? ret [print-line "SetConsoleTitle failed!" halt]
|
||||
][
|
||||
rl-bind-key as-integer tab as-integer :rl-insert-wrapper
|
||||
]
|
||||
]
|
||||
|
||||
input: routine [
|
||||
prompt [string!]
|
||||
/local
|
||||
len ret str buffer line
|
||||
][
|
||||
#either OS = 'Windows [
|
||||
len: 0
|
||||
print as c-string! string/rs-head prompt
|
||||
ret: ReadConsole stdin line-buffer line-buffer-size :len null
|
||||
if zero? ret [print-line "ReadConsole failed!" halt]
|
||||
len: len + 1
|
||||
line-buffer/len: null-byte
|
||||
str: string/load as c-string! line-buffer len
|
||||
][
|
||||
line: read-line as c-string! string/rs-head prompt
|
||||
if line = null [halt] ; EOF
|
||||
|
||||
#if OS <> 'MacOSX [add-history line]
|
||||
|
||||
str: string/load line 1 + length? line
|
||||
; free as byte-ptr! line
|
||||
]
|
||||
SET_RETURN(str)
|
||||
]
|
||||
|
||||
count-delimiters: function [
|
||||
buffer [string!]
|
||||
return: [block!]
|
||||
][
|
||||
list: copy [0 0]
|
||||
c: none
|
||||
|
||||
foreach c buffer [
|
||||
case [
|
||||
escaped? [
|
||||
escaped?: no
|
||||
]
|
||||
in-comment? [
|
||||
switch c [
|
||||
#"^/" [in-comment?: no]
|
||||
]
|
||||
]
|
||||
'else [
|
||||
switch c [
|
||||
#"^^" [escaped?: yes]
|
||||
#";" [if zero? list/2 [in-comment?: yes]]
|
||||
#"[" [list/1: list/1 + 1]
|
||||
#"]" [list/1: list/1 - 1]
|
||||
#"{" [list/2: list/2 + 1]
|
||||
#"}" [list/2: list/2 - 1]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
list
|
||||
]
|
||||
|
||||
do-console: function [][
|
||||
buffer: make string! 10000
|
||||
prompt: red-prompt: "red>> "
|
||||
mode: 'mono
|
||||
|
||||
switch-mode: [
|
||||
mode: case [
|
||||
cnt/1 > 0 ['block]
|
||||
cnt/2 > 0 ['string]
|
||||
'else [
|
||||
prompt: red-prompt
|
||||
do eval
|
||||
'mono
|
||||
]
|
||||
]
|
||||
prompt: switch mode [
|
||||
block ["[^-"]
|
||||
string ["{^-"]
|
||||
mono [red-prompt]
|
||||
]
|
||||
]
|
||||
|
||||
eval: [
|
||||
code: load/all buffer
|
||||
|
||||
unless tail? code [
|
||||
set/any 'result do code
|
||||
|
||||
unless unset? :result [
|
||||
if 67 = length? result: mold/part :result 67 [ ;-- optimized for width = 72
|
||||
clear back tail result
|
||||
append result "..."
|
||||
]
|
||||
print ["==" result]
|
||||
]
|
||||
]
|
||||
clear buffer
|
||||
]
|
||||
|
||||
while [true][
|
||||
unless tail? line: input prompt [
|
||||
append buffer line
|
||||
cnt: count-delimiters buffer
|
||||
|
||||
either Windows? [
|
||||
remove skip tail buffer -2 ;-- clear extra CR (Windows)
|
||||
][
|
||||
append buffer lf ;-- Unix
|
||||
]
|
||||
|
||||
switch mode [
|
||||
block [if cnt/1 <= 0 [do switch-mode]]
|
||||
string [if cnt/2 <= 0 [do switch-mode]]
|
||||
mono [do either any [cnt/1 > 0 cnt/2 > 0][switch-mode][eval]]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
q: :quit
|
||||
|
||||
if script: read-argument [
|
||||
script: load script
|
||||
either any [
|
||||
script/1 <> 'Red
|
||||
not block? script/2
|
||||
][
|
||||
print "*** Error: not a Red program!"
|
||||
][
|
||||
do skip script 2
|
||||
]
|
||||
quit
|
||||
]
|
||||
|
||||
init-console "Red Console"
|
||||
|
||||
print {
|
||||
-=== Red Console alpha version ===-
|
||||
(only ASCII input supported)
|
||||
}
|
||||
|
||||
do-console
|
||||
124
samples/Red/example.reds
Normal file
124
samples/Red/example.reds
Normal file
@@ -0,0 +1,124 @@
|
||||
Red/System [
|
||||
Title: "Red/System example file"
|
||||
Purpose: "Just some code for testing Pygments colorizer"
|
||||
Language: http://www.red-lang.org/
|
||||
]
|
||||
|
||||
#include %../common/FPU-configuration.reds
|
||||
|
||||
; C types
|
||||
|
||||
#define time! long!
|
||||
#define clock! long!
|
||||
|
||||
date!: alias struct! [
|
||||
second [integer!] ; 0-61 (60?)
|
||||
minute [integer!] ; 0-59
|
||||
hour [integer!] ; 0-23
|
||||
|
||||
day [integer!] ; 1-31
|
||||
month [integer!] ; 0-11
|
||||
year [integer!] ; Since 1900
|
||||
|
||||
weekday [integer!] ; 0-6 since Sunday
|
||||
yearday [integer!] ; 0-365
|
||||
daylight-saving-time? [integer!] ; Negative: unknown
|
||||
]
|
||||
|
||||
#either OS = 'Windows [
|
||||
#define clocks-per-second 1000
|
||||
][
|
||||
; CLOCKS_PER_SEC value for Syllable, Linux (XSI-conformant systems)
|
||||
; TODO: check for other systems
|
||||
#define clocks-per-second 1000'000
|
||||
]
|
||||
|
||||
#import [LIBC-file cdecl [
|
||||
|
||||
; Error handling
|
||||
|
||||
form-error: "strerror" [ ; Return error description.
|
||||
code [integer!]
|
||||
return: [c-string!]
|
||||
]
|
||||
print-error: "perror" [ ; Print error to standard error output.
|
||||
string [c-string!]
|
||||
]
|
||||
|
||||
|
||||
; Memory management
|
||||
|
||||
make: "calloc" [ ; Allocate zero-filled memory.
|
||||
chunks [size!]
|
||||
size [size!]
|
||||
return: [binary!]
|
||||
]
|
||||
resize: "realloc" [ ; Resize memory allocation.
|
||||
memory [binary!]
|
||||
size [size!]
|
||||
return: [binary!]
|
||||
]
|
||||
]
|
||||
|
||||
JVM!: alias struct! [
|
||||
reserved0 [int-ptr!]
|
||||
reserved1 [int-ptr!]
|
||||
reserved2 [int-ptr!]
|
||||
|
||||
DestroyJavaVM [function! [[JNICALL] vm [JVM-ptr!] return: [jint!]]]
|
||||
AttachCurrentThread [function! [[JNICALL] vm [JVM-ptr!] penv [struct! [p [int-ptr!]]] args [byte-ptr!] return: [jint!]]]
|
||||
DetachCurrentThread [function! [[JNICALL] vm [JVM-ptr!] return: [jint!]]]
|
||||
GetEnv [function! [[JNICALL] vm [JVM-ptr!] penv [struct! [p [int-ptr!]]] version [integer!] return: [jint!]]]
|
||||
AttachCurrentThreadAsDaemon [function! [[JNICALL] vm [JVM-ptr!] penv [struct! [p [int-ptr!]]] args [byte-ptr!] return: [jint!]]]
|
||||
]
|
||||
|
||||
;just some datatypes for testing:
|
||||
|
||||
#some-hash
|
||||
10-1-2013
|
||||
quit
|
||||
|
||||
;binary:
|
||||
#{00FF0000}
|
||||
#{00FF0000 FF000000}
|
||||
#{00FF0000 FF000000} ;with tab instead of space
|
||||
2#{00001111}
|
||||
64#{/wAAAA==}
|
||||
64#{/wAAA A==} ;with space inside
|
||||
64#{/wAAA A==} ;with tab inside
|
||||
|
||||
|
||||
;string with char
|
||||
{bla ^(ff) foo}
|
||||
{bla ^(( foo}
|
||||
;some numbers:
|
||||
12
|
||||
1'000
|
||||
1.2
|
||||
FF00FF00h
|
||||
|
||||
;some tests of hexa number notation with not common ending
|
||||
[ff00h ff00h] ff00h{} FFh"foo" 00h(1 + 2) (AEh)
|
||||
|
||||
;normal words:
|
||||
foo char
|
||||
|
||||
;get-word
|
||||
:foo
|
||||
|
||||
;lit-word:
|
||||
'foo 'foo
|
||||
|
||||
to-integer foo
|
||||
foo/(a + 1)/b
|
||||
|
||||
call/output reform ['which interpreter] path: copy ""
|
||||
|
||||
version-1.1: 00010001h
|
||||
|
||||
#if type = 'exe [
|
||||
push system/stack/frame ;-- save previous frame pointer
|
||||
system/stack/frame: system/stack/top ;-- @@ reposition frame pointer just after the catch flag
|
||||
]
|
||||
push CATCH_ALL ;-- exceptions root barrier
|
||||
push 0 ;-- keep stack aligned on 64-bit
|
||||
19
samples/Ruby/filenames/.pryrc
Normal file
19
samples/Ruby/filenames/.pryrc
Normal file
@@ -0,0 +1,19 @@
|
||||
Pry.config.commands.import Pry::ExtendedCommands::Experimental
|
||||
|
||||
Pry.config.pager = false
|
||||
|
||||
Pry.config.color = false
|
||||
|
||||
Pry.config.commands.alias_command "lM", "ls -M"
|
||||
|
||||
Pry.config.commands.command "add", "Add a list of numbers together" do |*args|
|
||||
output.puts "Result is: #{args.map(&:to_i).inject(&:+)}"
|
||||
end
|
||||
|
||||
Pry.config.history.should_save = false
|
||||
|
||||
Pry.config.prompt = [proc { "input> " },
|
||||
proc { " | " }]
|
||||
|
||||
# Disable pry-buggy-plug:
|
||||
Pry.plugins["buggy-plug"].disable!
|
||||
17
samples/SAS/data.sas
Normal file
17
samples/SAS/data.sas
Normal file
@@ -0,0 +1,17 @@
|
||||
/* Example DATA step code for linguist */
|
||||
|
||||
libname source 'C:\path\to\file'
|
||||
|
||||
data work.working_copy;
|
||||
set source.original_file.sas7bdat;
|
||||
run;
|
||||
|
||||
data work.working_copy;
|
||||
set work.working_copy;
|
||||
if Purge = 1 then delete;
|
||||
run;
|
||||
|
||||
data work.working_copy;
|
||||
set work.working_copy;
|
||||
if ImportantVariable = . then MissingFlag = 1;
|
||||
run;
|
||||
15
samples/SAS/proc.sas
Normal file
15
samples/SAS/proc.sas
Normal file
@@ -0,0 +1,15 @@
|
||||
/* PROC examples for Linguist */
|
||||
|
||||
proc surveyselect data=work.data out=work.boot method=urs reps=20000 seed=2156 sampsize=28 outhits;
|
||||
samplingunit Site;
|
||||
run;
|
||||
|
||||
PROC MI data=work.boot out=work.bootmi nimpute=30 seed=5686 round = 1;
|
||||
By Replicate;
|
||||
VAR Variable1 Variable2;
|
||||
run;
|
||||
|
||||
proc logistic data=work.bootmi descending;
|
||||
By Replicate _Imputation_;
|
||||
model Outcome = Variable1 Variable2 / risklimits;
|
||||
run;
|
||||
19
samples/SQL/AvailableInSearchSel.prc
Normal file
19
samples/SQL/AvailableInSearchSel.prc
Normal file
@@ -0,0 +1,19 @@
|
||||
IF EXISTS (SELECT * FROM DBO.SYSOBJECTS WHERE ID = OBJECT_ID(N'dbo.AvailableInSearchSel') AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
|
||||
DROP PROCEDURE dbo.AvailableInSearchSel
|
||||
GO
|
||||
CREATE Procedure AvailableInSearchSel
|
||||
AS
|
||||
|
||||
SELECT '-1',
|
||||
'Select...'
|
||||
UNION ALL
|
||||
SELECT '1',
|
||||
'Yes'
|
||||
UNION ALL
|
||||
SELECT '0',
|
||||
'No'
|
||||
GO
|
||||
IF DB_NAME() = 'Diebold' BEGIN
|
||||
GRANT EXECUTE ON dbo.AvailableInSearchSel TO [rv]
|
||||
END
|
||||
GO
|
||||
225
samples/SQL/db.sql
Normal file
225
samples/SQL/db.sql
Normal file
@@ -0,0 +1,225 @@
|
||||
SHOW WARNINGS;
|
||||
--
|
||||
-- Table structure for table `articles`
|
||||
--
|
||||
CREATE TABLE IF NOT EXISTS `articles` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) DEFAULT NULL,
|
||||
`content` longtext,
|
||||
`date_posted` datetime NOT NULL,
|
||||
`created_by` varchar(255) NOT NULL,
|
||||
`last_modified` datetime DEFAULT NULL,
|
||||
`last_modified_by` varchar(255) DEFAULT NULL,
|
||||
`ordering` int(10) DEFAULT '0',
|
||||
`is_published` int(1) DEFAULT '1',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
--
|
||||
-- Dumping data for table `articles`
|
||||
--
|
||||
|
||||
INSERT INTO `articles` (`title`, `content`, `date_posted`, `created_by`, `last_modified`, `last_modified_by`, `ordering`, `is_published`) VALUES
|
||||
('Welcome', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed interdum, felis ac pellentesque feugiat, massa enim sagittis elit, sed dignissim sem ligula non nisl. Sed pulvinar nunc nec eros aliquet non tempus diam vehicula. Nunc tincidunt, leo ut interdum tristique, quam ligula porttitor tellus, at tincidunt magna enim nec arcu. Nunc tempor egestas libero. Vivamus nulla ligula, vehicula vitae mattis quis, laoreet eget urna. Proin eget est quis urna venenatis dictum nec vel lectus. Nullam sit amet vehicula leo. Sed commodo, orci vitae facilisis accumsan, arcu justo sagittis risus, quis aliquet purus neque eu odio. Mauris lectus orci, tincidunt in varius quis, dictum sed nibh. Quisque dapibus mollis blandit. Donec vel tellus nisl, sed scelerisque felis. Praesent ut eros tortor, sed molestie nunc. Duis eu massa at justo iaculis gravida.</p>\r\n<p>In adipiscing dictum risus a tincidunt. Sed nisi ipsum, rutrum sed ornare in, bibendum at augue. Integer ornare semper varius. Integer luctus vehicula elementum. Donec cursus elit quis erat laoreet elementum. Praesent eget justo purus, vitae accumsan massa. Ut tristique, mauris non dignissim luctus, velit justo sollicitudin odio, vel rutrum purus enim eu felis. In adipiscing elementum sagittis. Nam sed dui ante. Nunc laoreet hendrerit nisl vitae porta. Praesent sit amet ligula et nisi vulputate volutpat. Maecenas venenatis iaculis sapien sit amet auctor. Curabitur euismod venenatis velit non tempor. Cras vel sapien purus, mollis fermentum nulla. Mauris sed elementum enim. Donec ultrices urna at justo adipiscing rutrum.</p>', '2012-08-09 01:19:59', 'admin',NULL, NULL, 0, 1);
|
||||
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `challenges`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `challenges` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) DEFAULT NULL,
|
||||
`pkg_name` varchar(255) NOT NULL,
|
||||
`description` text,
|
||||
`author` varchar(255) NOT NULL,
|
||||
`category` varchar(255) NOT NULL,
|
||||
`date_posted` datetime NOT NULL,
|
||||
`visibility` varchar(255) DEFAULT 'private',
|
||||
`publish` int(10) DEFAULT '0',
|
||||
`abstract` varchar(255) DEFAULT NULL,
|
||||
`level` varchar(255) DEFAULT NULL,
|
||||
`duration` int(11) DEFAULT NULL,
|
||||
`goal` varchar(255) DEFAULT NULL,
|
||||
`solution` varchar(255) DEFAULT NULL,
|
||||
`availability` varchar(255) DEFAULT 'private',
|
||||
`default_points` int(11) DEFAULT NULL,
|
||||
`default_duration` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
--
|
||||
-- Dumping data for table `challenges`
|
||||
--
|
||||
|
||||
INSERT INTO `challenges` (`title`, `pkg_name`, `description`, `author`, `category`, `date_posted`, `visibility`, `publish`, `abstract`, `level`, `duration`, `goal`, `solution`, `availability`, `default_points`, `default_duration`) VALUES
|
||||
('Challenge 1', 'ch001', 'Our agents (hackers) informed us that there reasonable suspicion \r\nthat the site of this <a href="ch001/" target="_blank">Logistics Company</a> is a blind \r\nfor a human organs'' smuggling organisation.<br /> <br /> This organisation attracts its \r\nvictims through advertisments for jobs with very high salaries. They choose those ones who \r\ndo not have many relatives, they assasinate them and then sell their organs to very rich \r\nclients, at very high prices.<br /> <br /> These employees are registered in the secret \r\nfiles of the company as "special clients"!<br /> <br /> One of our agents has been hired \r\nas by the particular company. Unfortunately, since 01/01/2007 he has gone missing.<br /> \r\n<br /> We know that our agent is alive, but we cannot contact him. Last time he \r\ncommunicated with us, he mentioned that we could contact him at the e-mail address the \r\ncompany has supplied him with, should there a problem arise.<br /> <br /> The problem is \r\nthat when we last talked to him, he had not a company e-mail address yet, but he told us \r\nthat his e-mail can be found through the company''s site. <br /> <br /> The only thing we \r\nremember is that he was hired on Friday the 13th! <br /> <br /> You have to find his e-mail \r\naddress and send it to us by using the central communication panel of the company''s \r\nsite.<br /> <br /> Good luck!!!', 'Andreas Venieris,\n Konstantinos Papapanagiotou,\n \n Anastasios Stasinopoulos,\n Vasilios Vlachos,\n Alexandros \nPapanikolaou', 'web', '2012-08-09 00:23:14', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Challenge 2', 'ch002', 'Your Country needs your help for finding the password of an enemy \r\n\r\nsite that contains useful information, which if is not acquired on time, peace in our \r\n\r\narea will be at stake.<br /> <br />\n You must therefore succeed in finding the \r\n\r\npassword of this military <a href="ch002/index.php" target="_blank">SITE</a>.<br /> <br \r\n\r\n/> Good luck!', 'Andreas Venieris,\n Konstantinos Papapanagiotou,\n Anastasios \r\n\r\nStasinopoulos,\n Vasilios Vlachos,\n Alexandros Papanikolaou', 'web', '0000-00-00 00:00:00', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Challenge 3', 'ch003', 'XSS permits a malevolent user to inject his own code in vulnerable \r\n\r\nweb pages. According to the OWASP 2010 Top 10 Application Security Risks, XSS attacks \r\n\r\nrank 2nd in the "most dangerous" list.<br /> <br /> Your objective is to make an alert \r\n\r\nbox appear <a href="ch003/index.php" target="_blank">HERE</a> bearing the message: \r\n\r\n"<strong>XSS!</strong>".', 'Andreas Venieris,\n Konstantinos Papapanagiotou,\n \r\n\r\n Anastasios Stasinopoulos,\n Vasilios Vlachos,\n Alexandros \r\n\r\nPapanikolaou', 'web', '2012-08-09 00:24:46', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Challenge 4', 'ch004', 'A hacker informed us that <a href="ch004/index.php" target=\r\n\r\n"_blank">this</a> site suffers from an XSS-like type of vulnerability. Unfortunately, he \r\n\r\nlost the notes he had written regarding how exactly did he exploit the aforementioned \r\n\r\nvulnerability.<br /> Your objective is to make an alert box appear, bearing the message \r\n\r\n"<strong>XSS!</strong>". It should be noted, however, that this site has some protection \r\n\r\nagainst such attacks.', 'Andreas Venieris,\n Konstantinos Papapanagiotou,\n \r\n\r\nAnastasios Stasinopoulos,\n Vasilios Vlachos,\n Alexandros \r\n\r\nPapanikolaou', 'web', '2012-08-09 00:25:25', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Challenge 5', 'ch005', 'You need to get access to the contents of this <a href=\r\n\r\n"ch005/index.php" target="_blank">SITE</a>. In order to achieve this, however, you \r\n\r\nmust buy the "p0wnBrowser" web browser. Since it is too expensive, you will have to \r\n\r\n"fool" the system in some way, so that it let you read the site''s contents.', 'Andreas \r\n\r\nVenieris,\n Konstantinos Papapanagiotou,\n Anastasios Stasinopoulos,\n \r\n\r\nVasilios Vlachos,\n Alexandros Papanikolaou', 'web', '2012-08-09 00:26:09', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Challenge 6', 'ch006', 'In this assignment you must prove your... knightly skills! Real \r\n\r\nknights have not disappeared.They still exist, keeping their secrets well hidden.<br /> \r\n\r\nYour mission is to infiltrate their <a href="ch006/index.php" target="_blank">SITE</a>. \r\n\r\nThere is a small problem, however... We don''t know the password!<br /> Perhaps you could \r\n\r\nfind it?<br /> Let''s see!<br /> g00d luck dudes!', 'Andreas Venieris,\n Konstantinos \r\n\r\nPapapanagiotou,\n Anastasios Stasinopoulos,\n Vasilios Vlachos,\n \r\n\r\nAlexandros Papanikolaou', 'web', '2012-08-09 00:26:52', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Challenge 7', 'ch007', 'A good friend of mine studies at Acme University, in the <a href=\r\n\r\n"ch007/index.php" target="_blank">Computer Science and Telecomms Department</a>. \r\n\r\nUnfortunately, her grades are not that good. You are now thinking "This is big news!"... \r\n\r\nHmmm, maybe not. What is big news, however, is this: The network administrator asked for \r\n\r\n3,000 euros to change her marks into A''s. This is obviously a case of administrative \r\n\r\nauthority abuse. Hence... a good chance for D-phase and public exposure...<br /> I need to \r\n\r\nget into the site as admin and upload an index.htm file in the web-root directory, that \r\n\r\nwill present all required evidence for the University''s latest "re-marking" practices!\r\n\r\n<br /> I only need you to find the admin password for me...<br /> <br /> Good \r\n\r\nLuck!', 'Andreas Venieris,\n Konstantinos Papapanagiotou,\n Anastasios \r\n\r\nStasinopoulos,\n Vasilios Vlachos,\n Alexandros Papanikolaou', 'web', '0000-00-00 00:00:00', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Challenge 8', 'ch008', 'You have managed, after several tries, to install a backdoor shell \r\n\r\n(Locus7Shell) to <a href="ch008/" target="_blank">trytohack.gr<br /></a> <br /> The \r\n\r\nproblem is that, in order to execute the majority of the commands (on the machine running \r\n\r\nthe backdoor) you must have super-user rights (root).<br /> <br /> Your aim is to obtain \r\n\r\nroot rights.', 'Andreas Venieris,\n Konstantinos Papapanagiotou,\n Anastasios \r\n\r\nStasinopoulos,\n Vasilios Vlachos,\n Alexandros Papanikolaou', 'web', '0000-00-00 00:00:00', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Challenge 9', 'ch009', 'A friend of yours has set up a news blog at <a href=\r\n\r\n"ch009/index.php" target="_blank">slagoff.com</a>. However, he is kind of worried \r\n\r\nregarding the security of the news that gets posted on the blog and has asked you to check \r\n\r\nhow secure it is.<br /> <br /> Your objective is to determine whether any vulnerabilities \r\n\r\nexist that, if exploited, can grant access to the blog''s server.<br /> <br /> Hint: A \r\n\r\nspecially-tailored backdoor shell can be found at "<a href=\r\n\r\n"http://www.really_nasty_hacker.com/shell.txt" target="_blank\r\n\r\n">http://www.really_nasty_hacker.com/shell.txt</a>".', 'Andreas Venieris,\n \r\n\r\nKonstantinos Papapanagiotou,\n Anastasios Stasinopoulos,\n Vasilios Vlachos,\r\n\r\n\n Alexandros Papanikolaou', 'web', '2012-08-09 00:31:31', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Challenge 10', 'ch010', 'Would you like to become an active hacker ?<br /> How about \r\n\r\nbecoming a member of the world''s largest hacker group:<br /> The n1nJ4.n4x0rZ.CreW!<br /> \r\n\r\n<br /> Before you can join though, you ''ll have to prove yourself worthy by passing the \r\n\r\ntest that can be found at: <a href="ch010/" target="_blank\r\n\r\n">http://n1nj4h4x0rzcr3w.com</a><br /> <br /> If you succeed in completing the challenge, \r\n\r\nyou will get a serial number, which you will use for obtaining the password that will \r\n\r\nenable you to join the group.<br /> <br /> Your objective is to bypass the authentication \r\n\r\nmechanism, find the serial number and be supplied with your own username and password from \r\n\r\n the admin team of the site.', 'Andreas Venieris,\n Konstantinos Papapanagiotou,\n \r\n\r\n Anastasios Stasinopoulos,\n Vasilios Vlachos,\n Alexandros \r\n\r\nPapanikolaou', 'web', '2012-08-09 00:32:07', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Example Template For Challenge xml Files creation', 'example', '<p>Insert some text describing the scenario of the challenge(what the users are supposed to do and if there is any fictional story)</p>', 'Name or email or both', 'In what category does your challenge belong?(web? crypto? networks?)', '2012-10-16 22:35:01', 'private', 0, NULL, '1', 60, NULL, NULL, 'private', 1, 0),
|
||||
('cookiEng', 'cookiEng', '<p>Hello, we have heard that you are one of the best hackers in our country. We need your services.<br>You must visit an underground site and find<br> the right password. With this password we will cancel 100k+ illegal gun and drug deals!\n The good news are that we have the directory where the password is stored. Its here \\\"/t0psec.php\\\".\n The bad news are that we have no access there. Only the administrator does. Go and find the password for us!<br><br><br>Good luck!</p>', 'Nikos Danopoulos', 'web', '2012-08-09 00:32:07', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 1, 60),
|
||||
('Izon Challenge', 'izon', '<p>After the mysterious disappearance of your best friend, you are contacted by an unknown individual who claims to have information about your friend. This individual identifies himself as \"Mister Jax\" and claims that is a former colleague of your friend.</p><p>Your friend was working at Izon Corporation, a weapons manufactured and government contractor as a systems engineer. Mister Jax didn\'t tell you his role in Izon, but wants you to pass through a series of tests to infiltrate Izon\'s web security to find the truth about your friend</p><p>After much consideration you agree with Mister Jax and he, remotely, sets up your computer to look like as if it is a part of Izon\'s Virtual Private Network in order to access their site. He also said that he\'ll guide you while you work your way to uncover the truth about your lost friend</p><p>Here is a copy of Mister Jax\'s last email:</p><p><pre>The task is simple: You get in, get your information and get out.\r\nYour friend was either a dumb programmer or a brilliant one, he left\r\nmany holes to be exploited in order to gain higher access to the site.\r\nI\'ll be guiding you with tips while you try to hack through Izon\'s site.\r\nThere are four tasks, some related to each other, some not.\r\nYou need to use your skills to overcome the obstacles, knowledge will come along.\r\nSixty minutes will suffice. When they\'re over, I won\'t be able to offer any\r\ncover to you, and you\'ll be compromised, with unknown consequences, I\'m afraid.\r\nI\'ll be seeing you there.\r\n\r\ - Jax</pre></p> <p>Once you get in, you\'ll have sixty minutes to complete this challenge. Use common sense, remember that the most obvious place hides the most important stuff and try to behave as if you were hacking a real system.</p><p>Good Luck!</p>', 'Vasileios Mplanas', 'web', '2014-03-27 00:00:00', 'public', 1, NULL, '1', 60, NULL, NULL, 'public', 10, 60);
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `challenge_attempts`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `challenge_attempts` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`challenge_id` int(11) NOT NULL,
|
||||
`time` datetime NOT NULL,
|
||||
`status` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `challenge_attempt_count`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `challenge_attempt_count` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`challenge_id` int(11) NOT NULL,
|
||||
`tries` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `user_id` (`user_id`),
|
||||
UNIQUE KEY `challenge_id` (`challenge_id`)
|
||||
);
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `classes`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `classes` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`date_created` datetime NOT NULL,
|
||||
`archive` int(1) DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
--
|
||||
-- Dumping data for table `classes`
|
||||
--
|
||||
|
||||
INSERT INTO `classes` (`name`, `date_created`, `archive`) VALUES
|
||||
('Sample Class', '2012-08-09 00:43:48', 0),
|
||||
('fooClass', '2012-10-16 22:32:43', 0);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `class_challenges`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `class_challenges` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`challenge_id` int(11) NOT NULL,
|
||||
`class_id` int(11) NOT NULL,
|
||||
`date_created` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
--
|
||||
-- Dumping data for table `class_challenges`
|
||||
--
|
||||
|
||||
INSERT INTO `class_challenges` (`challenge_id`, `class_id`, `date_created`) VALUES
|
||||
(1, 1, '2012-08-09 01:01:07'),
|
||||
(2, 1, '2012-08-09 01:01:07'),
|
||||
(3, 1, '2012-08-09 01:01:07'),
|
||||
(4, 1, '2012-08-09 01:01:07'),
|
||||
(5, 1, '2012-08-09 01:01:07'),
|
||||
(6, 1, '2012-08-09 01:01:07'),
|
||||
(7, 1, '2012-08-09 01:01:07'),
|
||||
(9, 1, '2012-08-09 01:01:07'),
|
||||
(10, 1, '2012-08-09 01:01:07'),
|
||||
(1, 2, '2012-10-16 22:32:49'),
|
||||
(4, 2, '2012-10-16 22:32:52'),
|
||||
(9, 2, '2012-10-16 22:32:53'),
|
||||
(10, 2, '2012-10-16 22:32:55'),
|
||||
(8, 2, '2012-10-16 22:32:58');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `class_memberships`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `class_memberships` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`class_id` int(11) NOT NULL,
|
||||
`date_created` datetime NOT NULL,
|
||||
PRIMARY KEY (`user_id`,`class_id`),
|
||||
UNIQUE KEY `id` (`id`)
|
||||
);
|
||||
|
||||
--
|
||||
-- Dumping data for table `class_memberships`
|
||||
--
|
||||
|
||||
INSERT INTO `class_memberships` (`user_id`, `class_id`, `date_created`) VALUES
|
||||
( 1, 1, '2012-08-09 00:59:00'),
|
||||
( 2, 1, '2012-08-09 00:59:00'),
|
||||
( 3, 1, '2012-08-09 00:59:00'),
|
||||
( 4, 2, '2012-10-16 22:33:07'),
|
||||
( 5, 2, '2012-10-16 22:33:13');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `users`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`username` varchar(255) NOT NULL,
|
||||
`full_name` varchar(255) NOT NULL,
|
||||
`email` varchar(100) NOT NULL,
|
||||
`password` varchar(255) NOT NULL,
|
||||
`joined` datetime NOT NULL,
|
||||
`last_visit` datetime DEFAULT NULL,
|
||||
`is_activated` int(1) DEFAULT '0',
|
||||
`type` int(10) DEFAULT '0',
|
||||
`token` int(10) DEFAULT '0',
|
||||
PRIMARY KEY (`username`),
|
||||
UNIQUE KEY `id` (`id`)
|
||||
);
|
||||
|
||||
--
|
||||
-- Dumping data for table `users`
|
||||
--
|
||||
|
||||
INSERT INTO `users` (`username`, `full_name`, `email`, `password`, `joined`, `last_visit`, `is_activated`, `type`, `token`) VALUES
|
||||
('bar', 'mr. bar', 'bar@owasp.com', '$P$BJ8UtXZYqS/Lokm8zFMwcxO8dq797P.', '2012-10-16 22:12:52', '2012-10-16 22:22:39', 0, 0, 0),
|
||||
('foo', 'mr. foo', 'foo@owasp.com', '$P$BxCHeVG1RMF06UxwRbrVQtPA1yOwAq.', '2012-10-16 22:12:34', '2012-10-16 22:59:29', 0, 0, 0),
|
||||
('sensei', 'waspy sifu', 'waspy@owasp.sifu', '$P$Bj/JtLJJR3bUD0LLWXL2UW9DuRVo0I.', '2012-10-16 22:36:06', '2012-10-16 22:37:04', 1, 2, 0);
|
||||
|
||||
--
|
||||
-- Table structure for table `user_has_challenge_token`
|
||||
--
|
||||
DROP TABLE IF EXISTS `user_has_challenge_token`;
|
||||
CREATE TABLE IF NOT EXISTS `user_has_challenge_token` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` varchar(512) NOT NULL,
|
||||
`challenge_id` varchar(512) NOT NULL,
|
||||
`token` varchar(256) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
SHOW WARNINGS;
|
||||
22
samples/SQL/filial.tab
Normal file
22
samples/SQL/filial.tab
Normal file
@@ -0,0 +1,22 @@
|
||||
create table FILIAL
|
||||
(
|
||||
id NUMBER not null,
|
||||
title_ua VARCHAR2(128) not null,
|
||||
title_ru VARCHAR2(128) not null,
|
||||
title_eng VARCHAR2(128) not null,
|
||||
remove_date DATE,
|
||||
modify_date DATE,
|
||||
modify_user VARCHAR2(128)
|
||||
)
|
||||
;
|
||||
alter table FILIAL
|
||||
add constraint PK_ID primary key (ID);
|
||||
grant select on FILIAL to ATOLL;
|
||||
grant select on FILIAL to CRAMER2GIS;
|
||||
grant select on FILIAL to DMS;
|
||||
grant select on FILIAL to HPSM2GIS;
|
||||
grant select on FILIAL to PLANMONITOR;
|
||||
grant select on FILIAL to SIEBEL;
|
||||
grant select on FILIAL to VBIS;
|
||||
grant select on FILIAL to VPORTAL;
|
||||
|
||||
8
samples/SQL/object-update.udf
Normal file
8
samples/SQL/object-update.udf
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
if not exists(select * from sysobjects where name = '%object_name%' and type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
|
||||
exec('create FUNCTION dbo.%object_name%() returns int as begin return null end')
|
||||
GO
|
||||
|
||||
%object_ddl%
|
||||
|
||||
go
|
||||
6
samples/SQL/suspendedtoday.viw
Normal file
6
samples/SQL/suspendedtoday.viw
Normal file
@@ -0,0 +1,6 @@
|
||||
use translog;
|
||||
DROP VIEW IF EXISTS `suspendedtoday`;
|
||||
|
||||
create view suspendedtoday as
|
||||
select * from suspended
|
||||
where datediff(datetime, now()) = 0;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user