mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-12-28 21:01:00 +00:00
Merged with upstream. Updated M (aka MUMPS) detection to use the new bayesian / samples method.
This commit is contained in:
219
samples/ABAP/cl_csv_parser.abap
Normal file
219
samples/ABAP/cl_csv_parser.abap
Normal file
@@ -0,0 +1,219 @@
|
||||
*/**
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2012 René van Mil
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
*----------------------------------------------------------------------*
|
||||
* CLASS CL_CSV_PARSER DEFINITION
|
||||
*----------------------------------------------------------------------*
|
||||
*
|
||||
*----------------------------------------------------------------------*
|
||||
class cl_csv_parser definition
|
||||
public
|
||||
inheriting from cl_object
|
||||
final
|
||||
create public .
|
||||
|
||||
public section.
|
||||
*"* public components of class CL_CSV_PARSER
|
||||
*"* do not include other source files here!!!
|
||||
|
||||
type-pools abap .
|
||||
methods constructor
|
||||
importing
|
||||
!delegate type ref to if_csv_parser_delegate
|
||||
!csvstring type string
|
||||
!separator type c
|
||||
!skip_first_line type abap_bool .
|
||||
methods parse
|
||||
raising
|
||||
cx_csv_parse_error .
|
||||
protected section.
|
||||
*"* protected components of class CL_CSV_PARSER
|
||||
*"* do not include other source files here!!!
|
||||
private section.
|
||||
*"* private components of class CL_CSV_PARSER
|
||||
*"* do not include other source files here!!!
|
||||
|
||||
constants _textindicator type c value '"'. "#EC NOTEXT
|
||||
data _delegate type ref to if_csv_parser_delegate .
|
||||
data _csvstring type string .
|
||||
data _separator type c .
|
||||
type-pools abap .
|
||||
data _skip_first_line type abap_bool .
|
||||
|
||||
methods _lines
|
||||
returning
|
||||
value(returning) type stringtab .
|
||||
methods _parse_line
|
||||
importing
|
||||
!line type string
|
||||
returning
|
||||
value(returning) type stringtab
|
||||
raising
|
||||
cx_csv_parse_error .
|
||||
endclass. "CL_CSV_PARSER DEFINITION
|
||||
|
||||
|
||||
|
||||
*----------------------------------------------------------------------*
|
||||
* CLASS CL_CSV_PARSER IMPLEMENTATION
|
||||
*----------------------------------------------------------------------*
|
||||
*
|
||||
*----------------------------------------------------------------------*
|
||||
class cl_csv_parser implementation.
|
||||
|
||||
|
||||
* <SIGNATURE>---------------------------------------------------------------------------------------+
|
||||
* | Instance Public Method CL_CSV_PARSER->CONSTRUCTOR
|
||||
* +-------------------------------------------------------------------------------------------------+
|
||||
* | [--->] DELEGATE TYPE REF TO IF_CSV_PARSER_DELEGATE
|
||||
* | [--->] CSVSTRING TYPE STRING
|
||||
* | [--->] SEPARATOR TYPE C
|
||||
* | [--->] SKIP_FIRST_LINE TYPE ABAP_BOOL
|
||||
* +--------------------------------------------------------------------------------------</SIGNATURE>
|
||||
method constructor.
|
||||
super->constructor( ).
|
||||
_delegate = delegate.
|
||||
_csvstring = csvstring.
|
||||
_separator = separator.
|
||||
_skip_first_line = skip_first_line.
|
||||
endmethod. "constructor
|
||||
|
||||
|
||||
* <SIGNATURE>---------------------------------------------------------------------------------------+
|
||||
* | Instance Public Method CL_CSV_PARSER->PARSE
|
||||
* +-------------------------------------------------------------------------------------------------+
|
||||
* | [!CX!] CX_CSV_PARSE_ERROR
|
||||
* +--------------------------------------------------------------------------------------</SIGNATURE>
|
||||
method parse.
|
||||
data msg type string.
|
||||
if _csvstring is initial.
|
||||
message e002(csv) into msg.
|
||||
raise exception type cx_csv_parse_error
|
||||
exporting
|
||||
message = msg.
|
||||
endif.
|
||||
|
||||
" Get the lines
|
||||
data is_first_line type abap_bool value abap_true.
|
||||
data lines type standard table of string.
|
||||
lines = _lines( ).
|
||||
field-symbols <line> type string.
|
||||
loop at lines assigning <line>.
|
||||
" Should we skip the first line?
|
||||
if _skip_first_line = abap_true and is_first_line = abap_true.
|
||||
is_first_line = abap_false.
|
||||
continue.
|
||||
endif.
|
||||
" Parse the line
|
||||
data values type standard table of string.
|
||||
values = _parse_line( <line> ).
|
||||
" Send values to delegate
|
||||
_delegate->values_found( values ).
|
||||
endloop.
|
||||
endmethod. "parse
|
||||
|
||||
|
||||
* <SIGNATURE>---------------------------------------------------------------------------------------+
|
||||
* | Instance Private Method CL_CSV_PARSER->_LINES
|
||||
* +-------------------------------------------------------------------------------------------------+
|
||||
* | [<-()] RETURNING TYPE STRINGTAB
|
||||
* +--------------------------------------------------------------------------------------</SIGNATURE>
|
||||
method _lines.
|
||||
split _csvstring at cl_abap_char_utilities=>cr_lf into table returning.
|
||||
endmethod. "_lines
|
||||
|
||||
|
||||
* <SIGNATURE>---------------------------------------------------------------------------------------+
|
||||
* | Instance Private Method CL_CSV_PARSER->_PARSE_LINE
|
||||
* +-------------------------------------------------------------------------------------------------+
|
||||
* | [--->] LINE TYPE STRING
|
||||
* | [<-()] RETURNING TYPE STRINGTAB
|
||||
* | [!CX!] CX_CSV_PARSE_ERROR
|
||||
* +--------------------------------------------------------------------------------------</SIGNATURE>
|
||||
method _parse_line.
|
||||
data msg type string.
|
||||
|
||||
data csvvalue type string.
|
||||
data csvvalues type standard table of string.
|
||||
|
||||
data char type c.
|
||||
data pos type i value 0.
|
||||
data len type i.
|
||||
len = strlen( line ).
|
||||
while pos < len.
|
||||
char = line+pos(1).
|
||||
if char <> _separator.
|
||||
if char = _textindicator.
|
||||
data text_ended type abap_bool.
|
||||
text_ended = abap_false.
|
||||
while text_ended = abap_false.
|
||||
pos = pos + 1.
|
||||
if pos < len.
|
||||
char = line+pos(1).
|
||||
if char = _textindicator.
|
||||
text_ended = abap_true.
|
||||
else.
|
||||
if char is initial. " Space
|
||||
concatenate csvvalue ` ` into csvvalue.
|
||||
else.
|
||||
concatenate csvvalue char into csvvalue.
|
||||
endif.
|
||||
endif.
|
||||
else.
|
||||
" Reached the end of the line while inside a text value
|
||||
" This indicates an error in the CSV formatting
|
||||
text_ended = abap_true.
|
||||
message e003(csv) into msg.
|
||||
raise exception type cx_csv_parse_error
|
||||
exporting
|
||||
message = msg.
|
||||
endif.
|
||||
endwhile.
|
||||
" Check if next character is a separator, otherwise the CSV formatting is incorrect
|
||||
data nextpos type i.
|
||||
nextpos = pos + 1.
|
||||
if nextpos < len and line+nextpos(1) <> _separator.
|
||||
message e003(csv) into msg.
|
||||
raise exception type cx_csv_parse_error
|
||||
exporting
|
||||
message = msg.
|
||||
endif.
|
||||
else.
|
||||
if char is initial. " Space
|
||||
concatenate csvvalue ` ` into csvvalue.
|
||||
else.
|
||||
concatenate csvvalue char into csvvalue.
|
||||
endif.
|
||||
endif.
|
||||
else.
|
||||
append csvvalue to csvvalues.
|
||||
clear csvvalue.
|
||||
endif.
|
||||
pos = pos + 1.
|
||||
endwhile.
|
||||
append csvvalue to csvvalues. " Don't forget the last value
|
||||
|
||||
returning = csvvalues.
|
||||
endmethod. "_parse_line
|
||||
endclass. "CL_CSV_PARSER IMPLEMENTATION
|
||||
26
samples/ApacheConf/filenames/.htaccess
Normal file
26
samples/ApacheConf/filenames/.htaccess
Normal file
@@ -0,0 +1,26 @@
|
||||
ServerSignature Off
|
||||
RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC,OR]
|
||||
RewriteCond %{THE_REQUEST} (\\r|\\n|%0A|%0D) [NC,OR]
|
||||
|
||||
RewriteCond %{HTTP_REFERER} (<|>|’|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
|
||||
RewriteCond %{HTTP_COOKIE} (<|>|’|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
|
||||
RewriteCond %{REQUEST_URI} ^/(,|;|:|<|>|”>|”<|/|\\\.\.\\).{0,9999} [NC,OR]
|
||||
|
||||
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} ^(java|curl|wget) [NC,OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} (winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner) [NC,OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} (libwww-perl|curl|wget|python|nikto|scan) [NC,OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} (<|>|’|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
|
||||
|
||||
#Block mySQL injects
|
||||
RewriteCond %{QUERY_STRING} (;|<|>|’|”|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|cast|set|declare|drop|update|md5|benchmark) [NC,OR]
|
||||
|
||||
RewriteCond %{QUERY_STRING} \.\./\.\. [OR]
|
||||
|
||||
RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} \.[a-z0-9] [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} (<|>|’|%0A|%0D|%27|%3C|%3E|%00) [NC]
|
||||
# Note: The final RewriteCond must NOT use the [OR] flag.
|
||||
|
||||
# Return 403 Forbidden error.
|
||||
RewriteRule .* index.php [F]
|
||||
470
samples/ApacheConf/filenames/apache2.conf
Normal file
470
samples/ApacheConf/filenames/apache2.conf
Normal file
@@ -0,0 +1,470 @@
|
||||
# This is the main Apache HTTP server configuration file. It contains the
|
||||
# configuration directives that give the server its instructions.
|
||||
# See <URL:http://httpd.apache.org/docs/2.2> for detailed information.
|
||||
# In particular, see
|
||||
# <URL:http://httpd.apache.org/docs/2.2/mod/directives.html>
|
||||
# for a discussion of each configuration directive.
|
||||
#
|
||||
# Do NOT simply read the instructions in here without understanding
|
||||
# what they do. They're here only as hints or reminders. If you are unsure
|
||||
# consult the online docs. You have been warned.
|
||||
#
|
||||
# Configuration and logfile names: If the filenames you specify for many
|
||||
# of the server's control files begin with "/" (or "drive:/" for Win32), the
|
||||
# server will use that explicit path. If the filenames do *not* begin
|
||||
# with "/", the value of ServerRoot is prepended -- so "/var/log/apache2/foo.log"
|
||||
# with ServerRoot set to "" will be interpreted by the
|
||||
# server as "//var/log/apache2/foo.log".
|
||||
|
||||
#
|
||||
# ServerRoot: The top of the directory tree under which the server's
|
||||
# configuration, error, and log files are kept.
|
||||
#
|
||||
# Do not add a slash at the end of the directory path. If you point
|
||||
# ServerRoot at a non-local disk, be sure to point the LockFile directive
|
||||
# at a local disk. If you wish to share the same ServerRoot for multiple
|
||||
# httpd daemons, you will need to change at least LockFile and PidFile.
|
||||
#
|
||||
ServerRoot ""
|
||||
|
||||
#
|
||||
# Listen: Allows you to bind Apache to specific IP addresses and/or
|
||||
# ports, instead of the default. See also the <VirtualHost>
|
||||
# directive.
|
||||
#
|
||||
# Change this to Listen on specific IP addresses as shown below to
|
||||
# prevent Apache from glomming onto all bound IP addresses.
|
||||
#
|
||||
#Listen 12.34.56.78:80
|
||||
Listen 80
|
||||
|
||||
#
|
||||
# Dynamic Shared Object (DSO) Support
|
||||
#
|
||||
# To be able to use the functionality of a module which was built as a DSO you
|
||||
# have to place corresponding `LoadModule' lines at this location so the
|
||||
# directives contained in it are actually available _before_ they are used.
|
||||
# Statically compiled modules (those listed by `httpd -l') do not need
|
||||
# to be loaded here.
|
||||
#
|
||||
# Example:
|
||||
# LoadModule foo_module modules/mod_foo.so
|
||||
#
|
||||
LoadModule authn_file_module /usr/lib/apache2/modules/mod_authn_file.so
|
||||
LoadModule authn_dbm_module /usr/lib/apache2/modules/mod_authn_dbm.so
|
||||
LoadModule authn_anon_module /usr/lib/apache2/modules/mod_authn_anon.so
|
||||
LoadModule authn_dbd_module /usr/lib/apache2/modules/mod_authn_dbd.so
|
||||
LoadModule authn_default_module /usr/lib/apache2/modules/mod_authn_default.so
|
||||
LoadModule authn_alias_module /usr/lib/apache2/modules/mod_authn_alias.so
|
||||
LoadModule authz_host_module /usr/lib/apache2/modules/mod_authz_host.so
|
||||
LoadModule authz_groupfile_module /usr/lib/apache2/modules/mod_authz_groupfile.so
|
||||
LoadModule authz_user_module /usr/lib/apache2/modules/mod_authz_user.so
|
||||
LoadModule authz_dbm_module /usr/lib/apache2/modules/mod_authz_dbm.so
|
||||
LoadModule authz_owner_module /usr/lib/apache2/modules/mod_authz_owner.so
|
||||
LoadModule authnz_ldap_module /usr/lib/apache2/modules/mod_authnz_ldap.so
|
||||
LoadModule authz_default_module /usr/lib/apache2/modules/mod_authz_default.so
|
||||
LoadModule auth_basic_module /usr/lib/apache2/modules/mod_auth_basic.so
|
||||
LoadModule auth_digest_module /usr/lib/apache2/modules/mod_auth_digest.so
|
||||
LoadModule file_cache_module /usr/lib/apache2/modules/mod_file_cache.so
|
||||
LoadModule cache_module /usr/lib/apache2/modules/mod_cache.so
|
||||
LoadModule disk_cache_module /usr/lib/apache2/modules/mod_disk_cache.so
|
||||
LoadModule mem_cache_module /usr/lib/apache2/modules/mod_mem_cache.so
|
||||
LoadModule dbd_module /usr/lib/apache2/modules/mod_dbd.so
|
||||
LoadModule dumpio_module /usr/lib/apache2/modules/mod_dumpio.so
|
||||
LoadModule ext_filter_module /usr/lib/apache2/modules/mod_ext_filter.so
|
||||
LoadModule include_module /usr/lib/apache2/modules/mod_include.so
|
||||
LoadModule filter_module /usr/lib/apache2/modules/mod_filter.so
|
||||
LoadModule charset_lite_module /usr/lib/apache2/modules/mod_charset_lite.so
|
||||
LoadModule deflate_module /usr/lib/apache2/modules/mod_deflate.so
|
||||
LoadModule ldap_module /usr/lib/apache2/modules/mod_ldap.so
|
||||
LoadModule log_forensic_module /usr/lib/apache2/modules/mod_log_forensic.so
|
||||
LoadModule env_module /usr/lib/apache2/modules/mod_env.so
|
||||
LoadModule mime_magic_module /usr/lib/apache2/modules/mod_mime_magic.so
|
||||
LoadModule cern_meta_module /usr/lib/apache2/modules/mod_cern_meta.so
|
||||
LoadModule expires_module /usr/lib/apache2/modules/mod_expires.so
|
||||
LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
|
||||
LoadModule ident_module /usr/lib/apache2/modules/mod_ident.so
|
||||
LoadModule usertrack_module /usr/lib/apache2/modules/mod_usertrack.so
|
||||
LoadModule unique_id_module /usr/lib/apache2/modules/mod_unique_id.so
|
||||
LoadModule setenvif_module /usr/lib/apache2/modules/mod_setenvif.so
|
||||
LoadModule version_module /usr/lib/apache2/modules/mod_version.so
|
||||
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
|
||||
LoadModule proxy_connect_module /usr/lib/apache2/modules/mod_proxy_connect.so
|
||||
LoadModule proxy_ftp_module /usr/lib/apache2/modules/mod_proxy_ftp.so
|
||||
LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
|
||||
LoadModule proxy_ajp_module /usr/lib/apache2/modules/mod_proxy_ajp.so
|
||||
LoadModule proxy_balancer_module /usr/lib/apache2/modules/mod_proxy_balancer.so
|
||||
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
|
||||
LoadModule mime_module /usr/lib/apache2/modules/mod_mime.so
|
||||
LoadModule dav_module /usr/lib/apache2/modules/mod_dav.so
|
||||
LoadModule status_module /usr/lib/apache2/modules/mod_status.so
|
||||
LoadModule autoindex_module /usr/lib/apache2/modules/mod_autoindex.so
|
||||
LoadModule asis_module /usr/lib/apache2/modules/mod_asis.so
|
||||
LoadModule info_module /usr/lib/apache2/modules/mod_info.so
|
||||
LoadModule suexec_module /usr/lib/apache2/modules/mod_suexec.so
|
||||
LoadModule cgid_module /usr/lib/apache2/modules/mod_cgid.so
|
||||
LoadModule cgi_module /usr/lib/apache2/modules/mod_cgi.so
|
||||
LoadModule dav_fs_module /usr/lib/apache2/modules/mod_dav_fs.so
|
||||
LoadModule dav_lock_module /usr/lib/apache2/modules/mod_dav_lock.so
|
||||
LoadModule vhost_alias_module /usr/lib/apache2/modules/mod_vhost_alias.so
|
||||
LoadModule negotiation_module /usr/lib/apache2/modules/mod_negotiation.so
|
||||
LoadModule dir_module /usr/lib/apache2/modules/mod_dir.so
|
||||
LoadModule imagemap_module /usr/lib/apache2/modules/mod_imagemap.so
|
||||
LoadModule actions_module /usr/lib/apache2/modules/mod_actions.so
|
||||
LoadModule speling_module /usr/lib/apache2/modules/mod_speling.so
|
||||
LoadModule userdir_module /usr/lib/apache2/modules/mod_userdir.so
|
||||
LoadModule alias_module /usr/lib/apache2/modules/mod_alias.so
|
||||
LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so
|
||||
|
||||
<IfModule !mpm_netware_module>
|
||||
#
|
||||
# If you wish httpd to run as a different user or group, you must run
|
||||
# httpd as root initially and it will switch.
|
||||
#
|
||||
# User/Group: The name (or #number) of the user/group to run httpd as.
|
||||
# It is usually good practice to create a dedicated user and group for
|
||||
# running httpd, as with most system services.
|
||||
#
|
||||
User daemon
|
||||
Group daemon
|
||||
</IfModule>
|
||||
|
||||
# 'Main' server configuration
|
||||
#
|
||||
# The directives in this section set up the values used by the 'main'
|
||||
# server, which responds to any requests that aren't handled by a
|
||||
# <VirtualHost> definition. These values also provide defaults for
|
||||
# any <VirtualHost> containers you may define later in the file.
|
||||
#
|
||||
# All of these directives may appear inside <VirtualHost> containers,
|
||||
# in which case these default settings will be overridden for the
|
||||
# virtual host being defined.
|
||||
#
|
||||
|
||||
#
|
||||
# ServerAdmin: Your address, where problems with the server should be
|
||||
# e-mailed. This address appears on some server-generated pages, such
|
||||
# as error documents. e.g. admin@your-domain.com
|
||||
#
|
||||
ServerAdmin you@example.com
|
||||
|
||||
#
|
||||
# ServerName gives the name and port that the server uses to identify itself.
|
||||
# This can often be determined automatically, but we recommend you specify
|
||||
# it explicitly to prevent problems during startup.
|
||||
#
|
||||
# If your host doesn't have a registered DNS name, enter its IP address here.
|
||||
#
|
||||
#ServerName www.example.com:80
|
||||
|
||||
#
|
||||
# DocumentRoot: The directory out of which you will serve your
|
||||
# documents. By default, all requests are taken from this directory, but
|
||||
# symbolic links and aliases may be used to point to other locations.
|
||||
#
|
||||
DocumentRoot "/usr/share/apache2/default-site/htdocs"
|
||||
|
||||
#
|
||||
# Each directory to which Apache has access can be configured with respect
|
||||
# to which services and features are allowed and/or disabled in that
|
||||
# directory (and its subdirectories).
|
||||
#
|
||||
# First, we configure the "default" to be a very restrictive set of
|
||||
# features.
|
||||
#
|
||||
<Directory />
|
||||
Options FollowSymLinks
|
||||
AllowOverride None
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</Directory>
|
||||
|
||||
#
|
||||
# Note that from this point forward you must specifically allow
|
||||
# particular features to be enabled - so if something's not working as
|
||||
# you might expect, make sure that you have specifically enabled it
|
||||
# below.
|
||||
#
|
||||
|
||||
#
|
||||
# This should be changed to whatever you set DocumentRoot to.
|
||||
#
|
||||
<Directory "/usr/share/apache2/default-site/htdocs">
|
||||
#
|
||||
# Possible values for the Options directive are "None", "All",
|
||||
# or any combination of:
|
||||
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
|
||||
#
|
||||
# Note that "MultiViews" must be named *explicitly* --- "Options All"
|
||||
# doesn't give it to you.
|
||||
#
|
||||
# The Options directive is both complicated and important. Please see
|
||||
# http://httpd.apache.org/docs/2.2/mod/core.html#options
|
||||
# for more information.
|
||||
#
|
||||
Options Indexes FollowSymLinks
|
||||
|
||||
#
|
||||
# AllowOverride controls what directives may be placed in .htaccess files.
|
||||
# It can be "All", "None", or any combination of the keywords:
|
||||
# Options FileInfo AuthConfig Limit
|
||||
#
|
||||
AllowOverride None
|
||||
|
||||
#
|
||||
# Controls who can get stuff from this server.
|
||||
#
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
|
||||
</Directory>
|
||||
|
||||
#
|
||||
# DirectoryIndex: sets the file that Apache will serve if a directory
|
||||
# is requested.
|
||||
#
|
||||
<IfModule dir_module>
|
||||
DirectoryIndex index.html
|
||||
</IfModule>
|
||||
|
||||
#
|
||||
# The following lines prevent .htaccess and .htpasswd files from being
|
||||
# viewed by Web clients.
|
||||
#
|
||||
<FilesMatch "^\.ht">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
Satisfy All
|
||||
</FilesMatch>
|
||||
|
||||
#
|
||||
# ErrorLog: The location of the error log file.
|
||||
# If you do not specify an ErrorLog directive within a <VirtualHost>
|
||||
# container, error messages relating to that virtual host will be
|
||||
# logged here. If you *do* define an error logfile for a <VirtualHost>
|
||||
# container, that host's errors will be logged there and not here.
|
||||
#
|
||||
ErrorLog /var/log/apache2/error_log
|
||||
|
||||
#
|
||||
# LogLevel: Control the number of messages logged to the error_log.
|
||||
# Possible values include: debug, info, notice, warn, error, crit,
|
||||
# alert, emerg.
|
||||
#
|
||||
LogLevel warn
|
||||
|
||||
<IfModule log_config_module>
|
||||
#
|
||||
# The following directives define some format nicknames for use with
|
||||
# a CustomLog directive (see below).
|
||||
#
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||
|
||||
<IfModule logio_module>
|
||||
# You need to enable mod_logio.c to use %I and %O
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
|
||||
</IfModule>
|
||||
|
||||
#
|
||||
# The location and format of the access logfile (Common Logfile Format).
|
||||
# If you do not define any access logfiles within a <VirtualHost>
|
||||
# container, they will be logged here. Contrariwise, if you *do*
|
||||
# define per-<VirtualHost> access logfiles, transactions will be
|
||||
# logged therein and *not* in this file.
|
||||
#
|
||||
CustomLog /var/log/apache2/access_log common
|
||||
|
||||
#
|
||||
# If you prefer a logfile with access, agent, and referer information
|
||||
# (Combined Logfile Format) you can use the following directive.
|
||||
#
|
||||
#CustomLog /var/log/apache2/access_log combined
|
||||
</IfModule>
|
||||
|
||||
<IfModule alias_module>
|
||||
#
|
||||
# Redirect: Allows you to tell clients about documents that used to
|
||||
# exist in your server's namespace, but do not anymore. The client
|
||||
# will make a new request for the document at its new location.
|
||||
# Example:
|
||||
# Redirect permanent /foo http://www.example.com/bar
|
||||
|
||||
#
|
||||
# Alias: Maps web paths into filesystem paths and is used to
|
||||
# access content that does not live under the DocumentRoot.
|
||||
# Example:
|
||||
# Alias /webpath /full/filesystem/path
|
||||
#
|
||||
# If you include a trailing / on /webpath then the server will
|
||||
# require it to be present in the URL. You will also likely
|
||||
# need to provide a <Directory> section to allow access to
|
||||
# the filesystem path.
|
||||
|
||||
#
|
||||
# ScriptAlias: This controls which directories contain server scripts.
|
||||
# ScriptAliases are essentially the same as Aliases, except that
|
||||
# documents in the target directory are treated as applications and
|
||||
# run by the server when requested rather than as documents sent to the
|
||||
# client. The same rules about trailing "/" apply to ScriptAlias
|
||||
# directives as to Alias.
|
||||
#
|
||||
ScriptAlias /cgi-bin/ "/usr/lib/cgi-bin/"
|
||||
|
||||
</IfModule>
|
||||
|
||||
<IfModule cgid_module>
|
||||
#
|
||||
# ScriptSock: On threaded servers, designate the path to the UNIX
|
||||
# socket used to communicate with the CGI daemon of mod_cgid.
|
||||
#
|
||||
#Scriptsock /var/run/apache2/cgisock
|
||||
</IfModule>
|
||||
|
||||
#
|
||||
# "/usr/lib/cgi-bin" should be changed to whatever your ScriptAliased
|
||||
# CGI directory exists, if you have that configured.
|
||||
#
|
||||
<Directory "/usr/lib/cgi-bin">
|
||||
AllowOverride None
|
||||
Options None
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
#
|
||||
# DefaultType: the default MIME type the server will use for a document
|
||||
# if it cannot otherwise determine one, such as from filename extensions.
|
||||
# If your server contains mostly text or HTML documents, "text/plain" is
|
||||
# a good value. If most of your content is binary, such as applications
|
||||
# or images, you may want to use "application/octet-stream" instead to
|
||||
# keep browsers from trying to display binary files as though they are
|
||||
# text.
|
||||
#
|
||||
DefaultType text/plain
|
||||
|
||||
<IfModule mime_module>
|
||||
#
|
||||
# TypesConfig points to the file containing the list of mappings from
|
||||
# filename extension to MIME-type.
|
||||
#
|
||||
TypesConfig /etc/apache2/mime.types
|
||||
|
||||
#
|
||||
# AddType allows you to add to or override the MIME configuration
|
||||
# file specified in TypesConfig for specific file types.
|
||||
#
|
||||
#AddType application/x-gzip .tgz
|
||||
#
|
||||
# AddEncoding allows you to have certain browsers uncompress
|
||||
# information on the fly. Note: Not all browsers support this.
|
||||
#
|
||||
#AddEncoding x-compress .Z
|
||||
#AddEncoding x-gzip .gz .tgz
|
||||
#
|
||||
# If the AddEncoding directives above are commented-out, then you
|
||||
# probably should define those extensions to indicate media types:
|
||||
#
|
||||
AddType application/x-compress .Z
|
||||
AddType application/x-gzip .gz .tgz
|
||||
|
||||
#
|
||||
# AddHandler allows you to map certain file extensions to "handlers":
|
||||
# actions unrelated to filetype. These can be either built into the server
|
||||
# or added with the Action directive (see below)
|
||||
#
|
||||
# To use CGI scripts outside of ScriptAliased directories:
|
||||
# (You will also need to add "ExecCGI" to the "Options" directive.)
|
||||
#
|
||||
#AddHandler cgi-script .cgi
|
||||
|
||||
# For type maps (negotiated resources):
|
||||
#AddHandler type-map var
|
||||
|
||||
#
|
||||
# Filters allow you to process content before it is sent to the client.
|
||||
#
|
||||
# To parse .shtml files for server-side includes (SSI):
|
||||
# (You will also need to add "Includes" to the "Options" directive.)
|
||||
#
|
||||
#AddType text/html .shtml
|
||||
#AddOutputFilter INCLUDES .shtml
|
||||
</IfModule>
|
||||
|
||||
#
|
||||
# The mod_mime_magic module allows the server to use various hints from the
|
||||
# contents of the file itself to determine its type. The MIMEMagicFile
|
||||
# directive tells the module where the hint definitions are located.
|
||||
#
|
||||
#MIMEMagicFile /etc/apache2/magic
|
||||
|
||||
#
|
||||
# Customizable error responses come in three flavors:
|
||||
# 1) plain text 2) local redirects 3) external redirects
|
||||
#
|
||||
# Some examples:
|
||||
#ErrorDocument 500 "The server made a boo boo."
|
||||
#ErrorDocument 404 /missing.html
|
||||
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
|
||||
#ErrorDocument 402 http://www.example.com/subscription_info.html
|
||||
#
|
||||
|
||||
#
|
||||
# EnableMMAP and EnableSendfile: On systems that support it,
|
||||
# memory-mapping or the sendfile syscall is used to deliver
|
||||
# files. This usually improves server performance, but must
|
||||
# be turned off when serving from networked-mounted
|
||||
# filesystems or if support for these functions is otherwise
|
||||
# broken on your system.
|
||||
#
|
||||
#EnableMMAP off
|
||||
#EnableSendfile off
|
||||
|
||||
# Supplemental configuration
|
||||
#
|
||||
# The configuration files in the /etc/apache2/extra/ directory can be
|
||||
# included to add extra features or to modify the default configuration of
|
||||
# the server, or you may simply copy their contents here and change as
|
||||
# necessary.
|
||||
|
||||
# Server-pool management (MPM specific)
|
||||
#Include /etc/apache2/extra/httpd-mpm.conf
|
||||
|
||||
# Multi-language error messages
|
||||
#Include /etc/apache2/extra/httpd-multilang-errordoc.conf
|
||||
|
||||
# Fancy directory listings
|
||||
#Include /etc/apache2/extra/httpd-autoindex.conf
|
||||
|
||||
# Language settings
|
||||
#Include /etc/apache2/extra/httpd-languages.conf
|
||||
|
||||
# User home directories
|
||||
#Include /etc/apache2/extra/httpd-userdir.conf
|
||||
|
||||
# Real-time info on requests and configuration
|
||||
#Include /etc/apache2/extra/httpd-info.conf
|
||||
|
||||
# Virtual hosts
|
||||
#Include /etc/apache2/extra/httpd-vhosts.conf
|
||||
|
||||
# Local access to the Apache HTTP Server Manual
|
||||
#Include /etc/apache2/extra/httpd-manual.conf
|
||||
|
||||
# Distributed authoring and versioning (WebDAV)
|
||||
#Include /etc/apache2/extra/httpd-dav.conf
|
||||
|
||||
# Various default settings
|
||||
#Include /etc/apache2/extra/httpd-default.conf
|
||||
|
||||
# Secure (SSL/TLS) connections
|
||||
#Include /etc/apache2/extra/httpd-ssl.conf
|
||||
#
|
||||
# Note: The following must must be present to support
|
||||
# starting without SSL on platforms with no /dev/random equivalent
|
||||
# but a statically compiled-in mod_ssl.
|
||||
#
|
||||
<IfModule ssl_module>
|
||||
SSLRandomSeed startup builtin
|
||||
SSLRandomSeed connect builtin
|
||||
</IfModule>
|
||||
500
samples/ApacheConf/filenames/httpd.conf
Normal file
500
samples/ApacheConf/filenames/httpd.conf
Normal file
@@ -0,0 +1,500 @@
|
||||
#
|
||||
# This is the main Apache HTTP server configuration file. It contains the
|
||||
# configuration directives that give the server its instructions.
|
||||
# See <URL:http://httpd.apache.org/docs/2.2> for detailed information.
|
||||
# In particular, see
|
||||
# <URL:http://httpd.apache.org/docs/2.2/mod/directives.html>
|
||||
# for a discussion of each configuration directive.
|
||||
#
|
||||
# Do NOT simply read the instructions in here without understanding
|
||||
# what they do. They're here only as hints or reminders. If you are unsure
|
||||
# consult the online docs. You have been warned.
|
||||
#
|
||||
# Configuration and logfile names: If the filenames you specify for many
|
||||
# of the server's control files begin with "/" (or "drive:/" for Win32), the
|
||||
# server will use that explicit path. If the filenames do *not* begin
|
||||
# with "/", the value of ServerRoot is prepended -- so "log/foo_log"
|
||||
# with ServerRoot set to "/usr" will be interpreted by the
|
||||
# server as "/usr/log/foo_log".
|
||||
|
||||
#
|
||||
# ServerRoot: The top of the directory tree under which the server's
|
||||
# configuration, error, and log files are kept.
|
||||
#
|
||||
# Do not add a slash at the end of the directory path. If you point
|
||||
# ServerRoot at a non-local disk, be sure to point the LockFile directive
|
||||
# at a local disk. If you wish to share the same ServerRoot for multiple
|
||||
# httpd daemons, you will need to change at least LockFile and PidFile.
|
||||
#
|
||||
ServerRoot "/usr"
|
||||
|
||||
#
|
||||
# Listen: Allows you to bind Apache to specific IP addresses and/or
|
||||
# ports, instead of the default. See also the <VirtualHost>
|
||||
# directive.
|
||||
#
|
||||
# Change this to Listen on specific IP addresses as shown below to
|
||||
# prevent Apache from glomming onto all bound IP addresses.
|
||||
#
|
||||
#Listen 12.34.56.78:80
|
||||
Listen 80
|
||||
|
||||
#
|
||||
# Dynamic Shared Object (DSO) Support
|
||||
#
|
||||
# To be able to use the functionality of a module which was built as a DSO you
|
||||
# have to place corresponding `LoadModule' lines at this location so the
|
||||
# directives contained in it are actually available _before_ they are used.
|
||||
# Statically compiled modules (those listed by `httpd -l') do not need
|
||||
# to be loaded here.
|
||||
#
|
||||
# Example:
|
||||
# LoadModule foo_module modules/mod_foo.so
|
||||
#
|
||||
LoadModule authn_file_module libexec/apache2/mod_authn_file.so
|
||||
LoadModule authn_dbm_module libexec/apache2/mod_authn_dbm.so
|
||||
LoadModule authn_anon_module libexec/apache2/mod_authn_anon.so
|
||||
LoadModule authn_dbd_module libexec/apache2/mod_authn_dbd.so
|
||||
LoadModule authn_default_module libexec/apache2/mod_authn_default.so
|
||||
LoadModule authz_host_module libexec/apache2/mod_authz_host.so
|
||||
LoadModule authz_groupfile_module libexec/apache2/mod_authz_groupfile.so
|
||||
LoadModule authz_user_module libexec/apache2/mod_authz_user.so
|
||||
LoadModule authz_dbm_module libexec/apache2/mod_authz_dbm.so
|
||||
LoadModule authz_owner_module libexec/apache2/mod_authz_owner.so
|
||||
LoadModule authz_default_module libexec/apache2/mod_authz_default.so
|
||||
LoadModule auth_basic_module libexec/apache2/mod_auth_basic.so
|
||||
LoadModule auth_digest_module libexec/apache2/mod_auth_digest.so
|
||||
LoadModule cache_module libexec/apache2/mod_cache.so
|
||||
LoadModule disk_cache_module libexec/apache2/mod_disk_cache.so
|
||||
LoadModule mem_cache_module libexec/apache2/mod_mem_cache.so
|
||||
LoadModule dbd_module libexec/apache2/mod_dbd.so
|
||||
LoadModule dumpio_module libexec/apache2/mod_dumpio.so
|
||||
LoadModule reqtimeout_module libexec/apache2/mod_reqtimeout.so
|
||||
LoadModule ext_filter_module libexec/apache2/mod_ext_filter.so
|
||||
LoadModule include_module libexec/apache2/mod_include.so
|
||||
LoadModule filter_module libexec/apache2/mod_filter.so
|
||||
LoadModule substitute_module libexec/apache2/mod_substitute.so
|
||||
LoadModule deflate_module libexec/apache2/mod_deflate.so
|
||||
LoadModule log_config_module libexec/apache2/mod_log_config.so
|
||||
LoadModule log_forensic_module libexec/apache2/mod_log_forensic.so
|
||||
LoadModule logio_module libexec/apache2/mod_logio.so
|
||||
LoadModule env_module libexec/apache2/mod_env.so
|
||||
LoadModule mime_magic_module libexec/apache2/mod_mime_magic.so
|
||||
LoadModule cern_meta_module libexec/apache2/mod_cern_meta.so
|
||||
LoadModule expires_module libexec/apache2/mod_expires.so
|
||||
LoadModule headers_module libexec/apache2/mod_headers.so
|
||||
LoadModule ident_module libexec/apache2/mod_ident.so
|
||||
LoadModule usertrack_module libexec/apache2/mod_usertrack.so
|
||||
#LoadModule unique_id_module libexec/apache2/mod_unique_id.so
|
||||
LoadModule setenvif_module libexec/apache2/mod_setenvif.so
|
||||
LoadModule version_module libexec/apache2/mod_version.so
|
||||
LoadModule proxy_module libexec/apache2/mod_proxy.so
|
||||
LoadModule proxy_connect_module libexec/apache2/mod_proxy_connect.so
|
||||
LoadModule proxy_ftp_module libexec/apache2/mod_proxy_ftp.so
|
||||
LoadModule proxy_http_module libexec/apache2/mod_proxy_http.so
|
||||
LoadModule proxy_scgi_module libexec/apache2/mod_proxy_scgi.so
|
||||
LoadModule proxy_ajp_module libexec/apache2/mod_proxy_ajp.so
|
||||
LoadModule proxy_balancer_module libexec/apache2/mod_proxy_balancer.so
|
||||
LoadModule ssl_module libexec/apache2/mod_ssl.so
|
||||
LoadModule mime_module libexec/apache2/mod_mime.so
|
||||
LoadModule dav_module libexec/apache2/mod_dav.so
|
||||
LoadModule status_module libexec/apache2/mod_status.so
|
||||
LoadModule autoindex_module libexec/apache2/mod_autoindex.so
|
||||
LoadModule asis_module libexec/apache2/mod_asis.so
|
||||
LoadModule info_module libexec/apache2/mod_info.so
|
||||
LoadModule cgi_module libexec/apache2/mod_cgi.so
|
||||
LoadModule dav_fs_module libexec/apache2/mod_dav_fs.so
|
||||
LoadModule vhost_alias_module libexec/apache2/mod_vhost_alias.so
|
||||
LoadModule negotiation_module libexec/apache2/mod_negotiation.so
|
||||
LoadModule dir_module libexec/apache2/mod_dir.so
|
||||
LoadModule imagemap_module libexec/apache2/mod_imagemap.so
|
||||
LoadModule actions_module libexec/apache2/mod_actions.so
|
||||
LoadModule speling_module libexec/apache2/mod_speling.so
|
||||
LoadModule userdir_module libexec/apache2/mod_userdir.so
|
||||
LoadModule alias_module libexec/apache2/mod_alias.so
|
||||
LoadModule rewrite_module libexec/apache2/mod_rewrite.so
|
||||
#LoadModule perl_module libexec/apache2/mod_perl.so
|
||||
#LoadModule php5_module libexec/apache2/libphp5.so
|
||||
#LoadModule hfs_apple_module libexec/apache2/mod_hfs_apple.so
|
||||
|
||||
<IfModule !mpm_netware_module>
|
||||
<IfModule !mpm_winnt_module>
|
||||
#
|
||||
# If you wish httpd to run as a different user or group, you must run
|
||||
# httpd as root initially and it will switch.
|
||||
#
|
||||
# User/Group: The name (or #number) of the user/group to run httpd as.
|
||||
# It is usually good practice to create a dedicated user and group for
|
||||
# running httpd, as with most system services.
|
||||
#
|
||||
User _www
|
||||
Group _www
|
||||
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
# 'Main' server configuration
|
||||
#
|
||||
# The directives in this section set up the values used by the 'main'
|
||||
# server, which responds to any requests that aren't handled by a
|
||||
# <VirtualHost> definition. These values also provide defaults for
|
||||
# any <VirtualHost> containers you may define later in the file.
|
||||
#
|
||||
# All of these directives may appear inside <VirtualHost> containers,
|
||||
# in which case these default settings will be overridden for the
|
||||
# virtual host being defined.
|
||||
#
|
||||
|
||||
#
|
||||
# ServerAdmin: Your address, where problems with the server should be
|
||||
# e-mailed. This address appears on some server-generated pages, such
|
||||
# as error documents. e.g. admin@your-domain.com
|
||||
#
|
||||
ServerAdmin you@example.com
|
||||
|
||||
#
|
||||
# ServerName gives the name and port that the server uses to identify itself.
|
||||
# This can often be determined automatically, but we recommend you specify
|
||||
# it explicitly to prevent problems during startup.
|
||||
#
|
||||
# If your host doesn't have a registered DNS name, enter its IP address here.
|
||||
#
|
||||
#ServerName www.example.com:80
|
||||
|
||||
#
|
||||
# DocumentRoot: The directory out of which you will serve your
|
||||
# documents. By default, all requests are taken from this directory, but
|
||||
# symbolic links and aliases may be used to point to other locations.
|
||||
#
|
||||
DocumentRoot "/Library/WebServer/Documents"
|
||||
|
||||
#
|
||||
# Each directory to which Apache has access can be configured with respect
|
||||
# to which services and features are allowed and/or disabled in that
|
||||
# directory (and its subdirectories).
|
||||
#
|
||||
# First, we configure the "default" to be a very restrictive set of
|
||||
# features.
|
||||
#
|
||||
<Directory />
|
||||
Options FollowSymLinks
|
||||
AllowOverride None
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</Directory>
|
||||
|
||||
#
|
||||
# Note that from this point forward you must specifically allow
|
||||
# particular features to be enabled - so if something's not working as
|
||||
# you might expect, make sure that you have specifically enabled it
|
||||
# below.
|
||||
#
|
||||
|
||||
#
|
||||
# This should be changed to whatever you set DocumentRoot to.
|
||||
#
|
||||
<Directory "/Library/WebServer/Documents">
|
||||
#
|
||||
# Possible values for the Options directive are "None", "All",
|
||||
# or any combination of:
|
||||
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
|
||||
#
|
||||
# Note that "MultiViews" must be named *explicitly* --- "Options All"
|
||||
# doesn't give it to you.
|
||||
#
|
||||
# The Options directive is both complicated and important. Please see
|
||||
# http://httpd.apache.org/docs/2.2/mod/core.html#options
|
||||
# for more information.
|
||||
#
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
|
||||
#
|
||||
# AllowOverride controls what directives may be placed in .htaccess files.
|
||||
# It can be "All", "None", or any combination of the keywords:
|
||||
# Options FileInfo AuthConfig Limit
|
||||
#
|
||||
AllowOverride None
|
||||
|
||||
#
|
||||
# Controls who can get stuff from this server.
|
||||
#
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
|
||||
</Directory>
|
||||
|
||||
#
|
||||
# DirectoryIndex: sets the file that Apache will serve if a directory
|
||||
# is requested.
|
||||
#
|
||||
<IfModule dir_module>
|
||||
DirectoryIndex index.html
|
||||
</IfModule>
|
||||
|
||||
#
|
||||
# The following lines prevent .htaccess and .htpasswd files from being
|
||||
# viewed by Web clients.
|
||||
#
|
||||
<FilesMatch "^\.([Hh][Tt]|[Dd][Ss]_[Ss])">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
Satisfy All
|
||||
</FilesMatch>
|
||||
|
||||
#
|
||||
# Apple specific filesystem protection.
|
||||
#
|
||||
<Files "rsrc">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
Satisfy All
|
||||
</Files>
|
||||
<DirectoryMatch ".*\.\.namedfork">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
Satisfy All
|
||||
</DirectoryMatch>
|
||||
|
||||
#
|
||||
# ErrorLog: The location of the error log file.
|
||||
# If you do not specify an ErrorLog directive within a <VirtualHost>
|
||||
# container, error messages relating to that virtual host will be
|
||||
# logged here. If you *do* define an error logfile for a <VirtualHost>
|
||||
# container, that host's errors will be logged there and not here.
|
||||
#
|
||||
ErrorLog "/private/var/log/apache2/error_log"
|
||||
|
||||
#
|
||||
# LogLevel: Control the number of messages logged to the error_log.
|
||||
# Possible values include: debug, info, notice, warn, error, crit,
|
||||
# alert, emerg.
|
||||
#
|
||||
LogLevel warn
|
||||
|
||||
<IfModule log_config_module>
|
||||
#
|
||||
# The following directives define some format nicknames for use with
|
||||
# a CustomLog directive (see below).
|
||||
#
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||
|
||||
<IfModule logio_module>
|
||||
# You need to enable mod_logio.c to use %I and %O
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
|
||||
</IfModule>
|
||||
|
||||
#
|
||||
# The location and format of the access logfile (Common Logfile Format).
|
||||
# If you do not define any access logfiles within a <VirtualHost>
|
||||
# container, they will be logged here. Contrariwise, if you *do*
|
||||
# define per-<VirtualHost> access logfiles, transactions will be
|
||||
# logged therein and *not* in this file.
|
||||
#
|
||||
CustomLog "/private/var/log/apache2/access_log" common
|
||||
|
||||
#
|
||||
# If you prefer a logfile with access, agent, and referer information
|
||||
# (Combined Logfile Format) you can use the following directive.
|
||||
#
|
||||
#CustomLog "/private/var/log/apache2/access_log" combined
|
||||
</IfModule>
|
||||
|
||||
<IfModule alias_module>
|
||||
#
|
||||
# Redirect: Allows you to tell clients about documents that used to
|
||||
# exist in your server's namespace, but do not anymore. The client
|
||||
# will make a new request for the document at its new location.
|
||||
# Example:
|
||||
# Redirect permanent /foo http://www.example.com/bar
|
||||
|
||||
#
|
||||
# Alias: Maps web paths into filesystem paths and is used to
|
||||
# access content that does not live under the DocumentRoot.
|
||||
# Example:
|
||||
# Alias /webpath /full/filesystem/path
|
||||
#
|
||||
# If you include a trailing / on /webpath then the server will
|
||||
# require it to be present in the URL. You will also likely
|
||||
# need to provide a <Directory> section to allow access to
|
||||
# the filesystem path.
|
||||
|
||||
#
|
||||
# ScriptAlias: This controls which directories contain server scripts.
|
||||
# ScriptAliases are essentially the same as Aliases, except that
|
||||
# documents in the target directory are treated as applications and
|
||||
# run by the server when requested rather than as documents sent to the
|
||||
# client. The same rules about trailing "/" apply to ScriptAlias
|
||||
# directives as to Alias.
|
||||
#
|
||||
ScriptAliasMatch ^/cgi-bin/((?!(?i:webobjects)).*$) "/Library/WebServer/CGI-Executables/$1"
|
||||
|
||||
</IfModule>
|
||||
|
||||
<IfModule cgid_module>
|
||||
#
|
||||
# ScriptSock: On threaded servers, designate the path to the UNIX
|
||||
# socket used to communicate with the CGI daemon of mod_cgid.
|
||||
#
|
||||
#Scriptsock /private/var/run/cgisock
|
||||
</IfModule>
|
||||
|
||||
#
|
||||
# "/Library/WebServer/CGI-Executables" should be changed to whatever your ScriptAliased
|
||||
# CGI directory exists, if you have that configured.
|
||||
#
|
||||
<Directory "/Library/WebServer/CGI-Executables">
|
||||
AllowOverride None
|
||||
Options None
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
#
|
||||
# DefaultType: the default MIME type the server will use for a document
|
||||
# if it cannot otherwise determine one, such as from filename extensions.
|
||||
# If your server contains mostly text or HTML documents, "text/plain" is
|
||||
# a good value. If most of your content is binary, such as applications
|
||||
# or images, you may want to use "application/octet-stream" instead to
|
||||
# keep browsers from trying to display binary files as though they are
|
||||
# text.
|
||||
#
|
||||
DefaultType text/plain
|
||||
|
||||
<IfModule mime_module>
|
||||
#
|
||||
# TypesConfig points to the file containing the list of mappings from
|
||||
# filename extension to MIME-type.
|
||||
#
|
||||
TypesConfig /private/etc/apache2/mime.types
|
||||
|
||||
#
|
||||
# AddType allows you to add to or override the MIME configuration
|
||||
# file specified in TypesConfig for specific file types.
|
||||
#
|
||||
#AddType application/x-gzip .tgz
|
||||
#
|
||||
# AddEncoding allows you to have certain browsers uncompress
|
||||
# information on the fly. Note: Not all browsers support this.
|
||||
#
|
||||
#AddEncoding x-compress .Z
|
||||
#AddEncoding x-gzip .gz .tgz
|
||||
#
|
||||
# If the AddEncoding directives above are commented-out, then you
|
||||
# probably should define those extensions to indicate media types:
|
||||
#
|
||||
AddType application/x-compress .Z
|
||||
AddType application/x-gzip .gz .tgz
|
||||
|
||||
#
|
||||
# AddHandler allows you to map certain file extensions to "handlers":
|
||||
# actions unrelated to filetype. These can be either built into the server
|
||||
# or added with the Action directive (see below)
|
||||
#
|
||||
# To use CGI scripts outside of ScriptAliased directories:
|
||||
# (You will also need to add "ExecCGI" to the "Options" directive.)
|
||||
#
|
||||
#AddHandler cgi-script .cgi
|
||||
|
||||
# For type maps (negotiated resources):
|
||||
#AddHandler type-map var
|
||||
|
||||
#
|
||||
# Filters allow you to process content before it is sent to the client.
|
||||
#
|
||||
# To parse .shtml files for server-side includes (SSI):
|
||||
# (You will also need to add "Includes" to the "Options" directive.)
|
||||
#
|
||||
#AddType text/html .shtml
|
||||
#AddOutputFilter INCLUDES .shtml
|
||||
</IfModule>
|
||||
|
||||
#
|
||||
# The mod_mime_magic module allows the server to use various hints from the
|
||||
# contents of the file itself to determine its type. The MIMEMagicFile
|
||||
# directive tells the module where the hint definitions are located.
|
||||
#
|
||||
#MIMEMagicFile /private/etc/apache2/magic
|
||||
|
||||
#
|
||||
# Customizable error responses come in three flavors:
|
||||
# 1) plain text 2) local redirects 3) external redirects
|
||||
#
|
||||
# Some examples:
|
||||
#ErrorDocument 500 "The server made a boo boo."
|
||||
#ErrorDocument 404 /missing.html
|
||||
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
|
||||
#ErrorDocument 402 http://www.example.com/subscription_info.html
|
||||
#
|
||||
|
||||
#
|
||||
# MaxRanges: Maximum number of Ranges in a request before
|
||||
# returning the entire resource, or one of the special
|
||||
# values 'default', 'none' or 'unlimited'.
|
||||
# Default setting is to accept 200 Ranges.
|
||||
#MaxRanges unlimited
|
||||
|
||||
#
|
||||
# EnableMMAP and EnableSendfile: On systems that support it,
|
||||
# memory-mapping or the sendfile syscall is used to deliver
|
||||
# files. This usually improves server performance, but must
|
||||
# be turned off when serving from networked-mounted
|
||||
# filesystems or if support for these functions is otherwise
|
||||
# broken on your system.
|
||||
#
|
||||
#EnableMMAP off
|
||||
#EnableSendfile off
|
||||
|
||||
# 6894961
|
||||
TraceEnable off
|
||||
|
||||
# Supplemental configuration
|
||||
#
|
||||
# The configuration files in the /private/etc/apache2/extra/ directory can be
|
||||
# included to add extra features or to modify the default configuration of
|
||||
# the server, or you may simply copy their contents here and change as
|
||||
# necessary.
|
||||
|
||||
# Server-pool management (MPM specific)
|
||||
Include /private/etc/apache2/extra/httpd-mpm.conf
|
||||
|
||||
# Multi-language error messages
|
||||
#Include /private/etc/apache2/extra/httpd-multilang-errordoc.conf
|
||||
|
||||
# Fancy directory listings
|
||||
Include /private/etc/apache2/extra/httpd-autoindex.conf
|
||||
|
||||
# Language settings
|
||||
Include /private/etc/apache2/extra/httpd-languages.conf
|
||||
|
||||
# User home directories
|
||||
Include /private/etc/apache2/extra/httpd-userdir.conf
|
||||
|
||||
# Real-time info on requests and configuration
|
||||
#Include /private/etc/apache2/extra/httpd-info.conf
|
||||
|
||||
# Virtual hosts
|
||||
#Include /private/etc/apache2/extra/httpd-vhosts.conf
|
||||
|
||||
# Local access to the Apache HTTP Server Manual
|
||||
Include /private/etc/apache2/extra/httpd-manual.conf
|
||||
|
||||
# Distributed authoring and versioning (WebDAV)
|
||||
#Include /private/etc/apache2/extra/httpd-dav.conf
|
||||
|
||||
# Various default settings
|
||||
#Include /private/etc/apache2/extra/httpd-default.conf
|
||||
|
||||
# Secure (SSL/TLS) connections
|
||||
#Include /private/etc/apache2/extra/httpd-ssl.conf
|
||||
#
|
||||
# Note: The following must must be present to support
|
||||
# starting without SSL on platforms with no /dev/random equivalent
|
||||
# but a statically compiled-in mod_ssl.
|
||||
#
|
||||
<IfModule ssl_module>
|
||||
SSLRandomSeed startup builtin
|
||||
SSLRandomSeed connect builtin
|
||||
</IfModule>
|
||||
|
||||
Include /private/etc/apache2/other/*.conf
|
||||
458
samples/Apex/ArrayUtils.cls
Normal file
458
samples/Apex/ArrayUtils.cls
Normal file
@@ -0,0 +1,458 @@
|
||||
/* ============================================================
|
||||
* This code is part of the "apex-lang" open source project avaiable at:
|
||||
*
|
||||
* http://code.google.com/p/apex-lang/
|
||||
*
|
||||
* This code is licensed under the Apache License, Version 2.0. You may obtain a
|
||||
* copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* ============================================================
|
||||
*/
|
||||
global class ArrayUtils {
|
||||
|
||||
global static String[] EMPTY_STRING_ARRAY = new String[]{};
|
||||
global static Integer MAX_NUMBER_OF_ELEMENTS_IN_LIST {get{return 1000;}}
|
||||
|
||||
global static List<String> objectToString(List<Object> objects){
|
||||
List<String> strings = null;
|
||||
if(objects != null){
|
||||
strings = new List<String>();
|
||||
if(objects.size() > 0){
|
||||
for(Object obj : objects){
|
||||
if(obj instanceof String){
|
||||
strings.add((String)obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
global static Object[] reverse(Object[] anArray) {
|
||||
if (anArray == null) {
|
||||
return null;
|
||||
}
|
||||
Integer i = 0;
|
||||
Integer j = anArray.size() - 1;
|
||||
Object tmp;
|
||||
while (j > i) {
|
||||
tmp = anArray[j];
|
||||
anArray[j] = anArray[i];
|
||||
anArray[i] = tmp;
|
||||
j--;
|
||||
i++;
|
||||
}
|
||||
return anArray;
|
||||
}
|
||||
|
||||
global static SObject[] reverse(SObject[] anArray) {
|
||||
if (anArray == null) {
|
||||
return null;
|
||||
}
|
||||
Integer i = 0;
|
||||
Integer j = anArray.size() - 1;
|
||||
SObject tmp;
|
||||
while (j > i) {
|
||||
tmp = anArray[j];
|
||||
anArray[j] = anArray[i];
|
||||
anArray[i] = tmp;
|
||||
j--;
|
||||
i++;
|
||||
}
|
||||
return anArray;
|
||||
}
|
||||
|
||||
global static List<String> lowerCase(List<String> strs){
|
||||
List<String> returnValue = null;
|
||||
if(strs != null){
|
||||
returnValue = new List<String>();
|
||||
if(strs.size() > 0){
|
||||
for(String str : strs){
|
||||
returnValue.add(str == null ? null : str.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
global static List<String> upperCase(List<String> strs){
|
||||
List<String> returnValue = null;
|
||||
if(strs != null){
|
||||
returnValue = new List<String>();
|
||||
if(strs.size() > 0){
|
||||
for(String str : strs){
|
||||
returnValue.add(str == null ? null : str.toUpperCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
global static List<String> trim(List<String> strs){
|
||||
List<String> returnValue = null;
|
||||
if(strs != null){
|
||||
returnValue = new List<String>();
|
||||
if(strs.size() > 0){
|
||||
for(String str : strs){
|
||||
returnValue.add(str == null ? null : str.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
global static Object[] mergex(Object[] array1, Object[] array2){
|
||||
if(array1 == null){ return array2; }
|
||||
if(array2 == null){ return array1; }
|
||||
Object[] merged = new Object[array1.size() + array2.size()];
|
||||
for(Integer i = 0; i < array1.size(); i++){
|
||||
merged[i] = array1[i];
|
||||
}
|
||||
for(Integer i = 0; i < array2.size(); i++){
|
||||
merged[i+array1.size()] = array2[i];
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
global static SObject[] mergex(SObject[] array1, SObject[] array2){
|
||||
if(array1 == null){ return array2; }
|
||||
if(array2 == null){ return array1; }
|
||||
if(array1.size() <= 0){ return array2; }
|
||||
List<SObject> merged = new List<SObject>();
|
||||
for(SObject sObj : array1){ merged.add(sObj); }
|
||||
for(SObject sObj : array2){ merged.add(sObj); }
|
||||
return merged;
|
||||
}
|
||||
|
||||
global static Boolean isEmpty(Object[] objectArray){
|
||||
if(objectArray == null){
|
||||
return true;
|
||||
}
|
||||
return objectArray.size() == 0;
|
||||
}
|
||||
|
||||
global static Boolean isEmpty(SObject[] objectArray){
|
||||
if(objectArray == null){
|
||||
return true;
|
||||
}
|
||||
return objectArray.size() == 0;
|
||||
}
|
||||
|
||||
global static Boolean isNotEmpty(Object[] objectArray){
|
||||
return !isEmpty(objectArray);
|
||||
}
|
||||
|
||||
global static Boolean isNotEmpty(SObject[] objectArray){
|
||||
return !isEmpty(objectArray);
|
||||
}
|
||||
|
||||
global static Object[] pluck(SObject[] objectArray, String fieldName){
|
||||
if(isEmpty(objectArray) || fieldName == null || fieldName.trim() == null || fieldName.trim().length() == 0){
|
||||
return new Object[]{};
|
||||
}
|
||||
Object[] plucked = new Object[objectArray.size()];
|
||||
for(Integer i = 0; i < objectArray.size(); i++){
|
||||
plucked[i] = objectArray[i].get(fieldName);
|
||||
}
|
||||
return plucked;
|
||||
}
|
||||
|
||||
|
||||
global static String toString(Object[] objectArray){
|
||||
if(objectArray == null){
|
||||
return 'null';
|
||||
}
|
||||
String returnValue = '{';
|
||||
for(Integer i = 0; i < objectArray.size(); i++){
|
||||
if(i!=0){ returnValue += ','; }
|
||||
returnValue += '\'' + objectArray[i] + '\'';
|
||||
}
|
||||
returnValue += '}';
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
global static String toString(SObject[] objectArray){
|
||||
if(objectArray == null){
|
||||
return 'null';
|
||||
}
|
||||
String returnValue = '{';
|
||||
for(Integer i = 0; i < objectArray.size(); i++){
|
||||
if(i!=0){ returnValue += ','; }
|
||||
returnValue += '\'' + objectArray[i] + '\'';
|
||||
}
|
||||
returnValue += '}';
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
global static void assertArraysAreEqual(Object[] expected, Object[] actual){
|
||||
//check to see if one param is null but the other is not
|
||||
System.assert((expected == null && actual == null)|| (expected != null && actual != null),
|
||||
'Assertion failed, the following two arrays are not equal. Expected: '
|
||||
+ ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual));
|
||||
if(expected != null && actual != null){
|
||||
System.assert(expected.size() == actual.size(), 'Assertion failed, the following two arrays are not equal. Expected: '
|
||||
+ ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual));
|
||||
for(Integer i = 0; i < expected.size(); i++){
|
||||
System.assert(expected[i] == actual[i], 'Assertion failed, the following two arrays are not equal. Expected: '
|
||||
+ ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global static void assertArraysAreEqual(SObject[] expected, SObject[] actual){
|
||||
//check to see if one param is null but the other is not
|
||||
System.assert((expected == null && actual == null)|| (expected != null && actual != null),
|
||||
'Assertion failed, the following two arrays are not equal. Expected: '
|
||||
+ ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual));
|
||||
if(expected != null && actual != null){
|
||||
System.assert(expected.size() == actual.size(), 'Assertion failed, the following two arrays are not equal. Expected: '
|
||||
+ ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual));
|
||||
for(Integer i = 0; i < expected.size(); i++){
|
||||
System.assert(expected[i] == actual[i], 'Assertion failed, the following two arrays are not equal. Expected: '
|
||||
+ ArrayUtils.toString(expected) + ', Actual: ' + ArrayUtils.toString(actual));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global static List<Object> merg(List<Object> list1, List<Object> list2) {
|
||||
List<Object> returnList = new List<Object>();
|
||||
if(list1 != null && list2 != null && (list1.size()+list2.size()) > MAX_NUMBER_OF_ELEMENTS_IN_LIST){
|
||||
throw new IllegalArgumentException('Lists cannot be merged because new list would be greater than maximum number of elements in a list: ' + MAX_NUMBER_OF_ELEMENTS_IN_LIST);
|
||||
}
|
||||
if(isNotEmpty(list1)){
|
||||
for(Object elmt : list1){
|
||||
returnList.add(elmt);
|
||||
}
|
||||
}
|
||||
if(isNotEmpty(list2)){
|
||||
for(Object elmt : list2){
|
||||
returnList.add(elmt);
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
|
||||
global static List<SObject> merg(List<SObject> list1, List<SObject> list2) {
|
||||
if(list1 != null && list2 != null && (list1.size()+list2.size()) > MAX_NUMBER_OF_ELEMENTS_IN_LIST){
|
||||
throw new IllegalArgumentException('Lists cannot be merged because new list would be greater than maximum number of elements in a list: ' + MAX_NUMBER_OF_ELEMENTS_IN_LIST);
|
||||
}
|
||||
if(isEmpty(list1) && isEmpty(list2)){
|
||||
return null;
|
||||
}
|
||||
List<SObject> returnList = new List<SObject>();
|
||||
if(list1 != null){
|
||||
for(SObject elmt : list1){
|
||||
returnList.add(elmt);
|
||||
}
|
||||
}
|
||||
if(list2 != null){
|
||||
for(SObject elmt : list2){
|
||||
returnList.add(elmt);
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
global static List<Object> subset(List<Object> aList, Integer count) {
|
||||
return subset(aList,0,count);
|
||||
}
|
||||
|
||||
global static List<Object> subset(List<Object> list1, Integer startIndex, Integer count) {
|
||||
List<Object> returnList = new List<Object>();
|
||||
if(list1 != null && list1.size() > 0 && startIndex >= 0 && startIndex <= list1.size()-1 && count > 0){
|
||||
for(Integer i = startIndex; i < list1.size() && i - startIndex < count; i++){
|
||||
returnList.add(list1.get(i));
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
|
||||
global static List<SObject> subset(List<SObject> aList, Integer count) {
|
||||
return subset(aList,0,count);
|
||||
}
|
||||
|
||||
global static List<SObject> subset(List<SObject> list1, Integer startIndex, Integer count) {
|
||||
List<SObject> returnList = null;
|
||||
if(list1 != null && list1.size() > 0 && startIndex <= list1.size()-1 && count > 0){
|
||||
returnList = new List<SObject>();
|
||||
for(Integer i = startIndex; i < list1.size() && i - startIndex < count; i++){
|
||||
returnList.add(list1.get(i));
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
//===============================================
|
||||
//LIST/ARRAY SORTING
|
||||
//===============================================
|
||||
|
||||
//FOR FORCE.COM PRIMITIVES (Double,Integer,ID,etc.):
|
||||
global static List<Object> qsort(List<Object> theList) {
|
||||
return qsort(theList,new PrimitiveComparator());
|
||||
}
|
||||
|
||||
global static List<Object> qsort(List<Object> theList, Boolean sortAsc) {
|
||||
return qsort(theList,new PrimitiveComparator(),sortAsc);
|
||||
}
|
||||
|
||||
global static List<Object> qsort(List<Object> theList, ObjectComparator comparator) {
|
||||
return qsort(theList,comparator,true);
|
||||
}
|
||||
|
||||
global static List<Object> qsort(List<Object> theList, ObjectComparator comparator, Boolean sortAsc) {
|
||||
return qsort(theList, 0, (theList == null ? 0 : theList.size()-1),comparator,sortAsc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//FOR SALESFORCE OBJECTS (sObjects):
|
||||
global static List<SObject> qsort(List<SObject> theList, ISObjectComparator comparator) {
|
||||
return qsort(theList,comparator,true);
|
||||
}
|
||||
|
||||
global static List<SObject> qsort(List<SObject> theList, ISObjectComparator comparator,Boolean sortAsc ) {
|
||||
return qsort(theList, 0, (theList == null ? 0 : theList.size()-1),comparator,sortAsc);
|
||||
}
|
||||
|
||||
private static List<Object> qsort(List<Object> theList,
|
||||
Integer lo0,
|
||||
Integer hi0,
|
||||
ObjectComparator comparator,
|
||||
Boolean sortAsc){
|
||||
Integer lo = lo0;
|
||||
Integer hi = hi0;
|
||||
|
||||
if (lo >= hi) {
|
||||
return theList;
|
||||
} else if( lo == hi - 1 ) {
|
||||
|
||||
if (( comparator.compare(theList[lo],theList[hi])>0 && sortAsc) ||
|
||||
(comparator.compare(theList[lo],theList[hi])<0 && !sortAsc)
|
||||
) {
|
||||
Object prs = theList[lo];
|
||||
theList[lo] = theList[hi];
|
||||
theList[hi] = prs;
|
||||
}
|
||||
return theList;
|
||||
}
|
||||
|
||||
Object pivot = theList[(lo + hi) / 2];
|
||||
theList[(lo + hi) / 2] = theList[hi];
|
||||
theList[hi] = pivot;
|
||||
|
||||
while( lo < hi ) {
|
||||
while ((comparator.compare(theList[lo], pivot)<=0 && lo < hi && sortAsc) ||
|
||||
(comparator.compare(theList[lo], pivot)>=0 && lo < hi && !sortAsc)
|
||||
) { lo++; }
|
||||
while (( comparator.compare(pivot,theList[hi])<=0 && lo < hi && sortAsc) ||
|
||||
( comparator.compare(pivot,theList[hi])>=0 && lo < hi && !sortAsc)
|
||||
) { hi--; }
|
||||
|
||||
if( lo < hi ){
|
||||
Object prs = theList[lo];
|
||||
theList[lo] = theList[hi];
|
||||
theList[hi] = prs;
|
||||
}
|
||||
}
|
||||
|
||||
theList[hi0] = theList[hi];
|
||||
theList[hi] = pivot;
|
||||
|
||||
qsort(theList, lo0, lo-1,comparator,sortAsc);
|
||||
qsort(theList, hi+1, hi0,comparator,sortAsc);
|
||||
return theList;
|
||||
}
|
||||
|
||||
|
||||
private static List<SObject> qsort(List<SObject> theList,
|
||||
Integer lo0,
|
||||
Integer hi0,
|
||||
ISObjectComparator comparator,
|
||||
Boolean sortAsc){
|
||||
Integer lo = lo0;
|
||||
Integer hi = hi0;
|
||||
|
||||
if (lo >= hi) {
|
||||
return theList;
|
||||
} else if( lo == hi - 1 ) {
|
||||
|
||||
if (( comparator.compare(theList[lo],theList[hi])>0 && sortAsc) ||
|
||||
(comparator.compare(theList[lo],theList[hi])<0 && !sortAsc)
|
||||
) {
|
||||
SObject prs = theList[lo];
|
||||
theList[lo] = theList[hi];
|
||||
theList[hi] = prs;
|
||||
}
|
||||
return theList;
|
||||
}
|
||||
|
||||
SObject pivot = theList[(lo + hi) / 2];
|
||||
theList[(lo + hi) / 2] = theList[hi];
|
||||
theList[hi] = pivot;
|
||||
|
||||
while( lo < hi ) {
|
||||
while ((comparator.compare(theList[lo], pivot)<=0 && lo < hi && sortAsc) ||
|
||||
(comparator.compare(theList[lo], pivot)>=0 && lo < hi && !sortAsc)
|
||||
) { lo++; }
|
||||
while (( comparator.compare(pivot,theList[hi])<=0 && lo < hi && sortAsc) ||
|
||||
( comparator.compare(pivot,theList[hi])>=0 && lo < hi && !sortAsc)
|
||||
) { hi--; }
|
||||
|
||||
if( lo < hi ){
|
||||
SObject prs = theList[lo];
|
||||
theList[lo] = theList[hi];
|
||||
theList[hi] = prs;
|
||||
}
|
||||
}
|
||||
|
||||
theList[hi0] = theList[hi];
|
||||
theList[hi] = pivot;
|
||||
|
||||
qsort(theList, lo0, lo-1,comparator,sortAsc);
|
||||
qsort(theList, hi+1, hi0,comparator,sortAsc);
|
||||
return theList;
|
||||
}
|
||||
/*
|
||||
global static List<Object> unique(List<Object> theList) {
|
||||
List<Object> uniques = new List<Object>();
|
||||
Set<Object> keys = new Set<Object>();
|
||||
if(theList != null && theList.size() > 0){
|
||||
for(Object obj : theList){
|
||||
if(keys.contains(obj)){
|
||||
continue;
|
||||
} else {
|
||||
keys.add(obj);
|
||||
uniques.add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return uniques;
|
||||
}
|
||||
|
||||
global static List<SObject> unique(List<SObject> theList) {
|
||||
if(theList == null){
|
||||
return null;
|
||||
}
|
||||
List<SObject> uniques = createEmptySObjectList(theList.get(0));
|
||||
Set<String> keys = new Set<String>();
|
||||
if(theList != null && theList.size() > 0){
|
||||
String key = null;
|
||||
for(SObject obj : theList){
|
||||
key = obj == null ? null : ''+obj;
|
||||
if(keys.contains(key)){
|
||||
continue;
|
||||
} else {
|
||||
keys.add(key);
|
||||
uniques.add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return uniques;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
185
samples/Apex/BooleanUtils.cls
Normal file
185
samples/Apex/BooleanUtils.cls
Normal file
@@ -0,0 +1,185 @@
|
||||
/* ============================================================
|
||||
* This code is part of the "apex-lang" open source project avaiable at:
|
||||
*
|
||||
* http://code.google.com/p/apex-lang/
|
||||
*
|
||||
* This code is licensed under the Apache License, Version 2.0. You may obtain a
|
||||
* copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* ============================================================
|
||||
*/
|
||||
global class BooleanUtils {
|
||||
|
||||
global static Boolean isFalse(Boolean bool)
|
||||
{
|
||||
if(bool==null)
|
||||
return false;
|
||||
else
|
||||
return !bool;
|
||||
}
|
||||
|
||||
global static Boolean isNotFalse(Boolean bool)
|
||||
{
|
||||
if(bool==null)
|
||||
return true;
|
||||
else
|
||||
return bool;
|
||||
}
|
||||
|
||||
global static Boolean isNotTrue(Boolean bool)
|
||||
{
|
||||
if(bool==null)
|
||||
return true;
|
||||
else
|
||||
return !bool;
|
||||
}
|
||||
|
||||
global static Boolean isTrue(Boolean bool)
|
||||
{
|
||||
if(bool==null)
|
||||
return false;
|
||||
else
|
||||
return bool;
|
||||
}
|
||||
|
||||
global static Boolean negate(Boolean bool)
|
||||
{
|
||||
if(bool==null)
|
||||
return null;
|
||||
else
|
||||
return !bool;
|
||||
}
|
||||
|
||||
global static Boolean toBooleanDefaultIfNull(Boolean bool, Boolean defaultVal)
|
||||
{
|
||||
if(bool==null)
|
||||
return defaultVal;
|
||||
else
|
||||
return bool;
|
||||
}
|
||||
|
||||
global static Boolean toBoolean(Integer value)
|
||||
{
|
||||
if(value==null)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
if(value==0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
global static Boolean strToBoolean(String value)
|
||||
{
|
||||
if(value==null)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
if(StringUtils.equalsIgnoreCase(value,'true'))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************/
|
||||
//Converts an int to a boolean specifying
|
||||
//the conversion values.
|
||||
// Parameters:
|
||||
// value - the Integer to convert, may be null
|
||||
// trueValue - the value to match for true, may be null
|
||||
// falseValue - the value to match for false, may be null
|
||||
//Returns:
|
||||
// true or false
|
||||
//Throws:
|
||||
// java.lang.IllegalArgumentException - if no match
|
||||
/************************************/
|
||||
global static Boolean toBoolean(Integer value,
|
||||
Integer trueValue,
|
||||
Integer falseValue)
|
||||
{
|
||||
if(value==trueValue)
|
||||
return true;
|
||||
else if(value==falseValue)
|
||||
return false;
|
||||
else
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
|
||||
global static Integer toInteger(Boolean bool)
|
||||
{
|
||||
if(bool==null)
|
||||
throw new IllegalArgumentException();
|
||||
else
|
||||
{
|
||||
if(bool)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
global static String toStringYesNo(Boolean bool)
|
||||
{
|
||||
if(bool==null)
|
||||
return null;
|
||||
else
|
||||
{
|
||||
if(bool)
|
||||
return 'yes';
|
||||
else
|
||||
return 'no';
|
||||
}
|
||||
}
|
||||
|
||||
global static String toStringYN(Boolean bool)
|
||||
{
|
||||
if(bool==null)
|
||||
return null;
|
||||
else
|
||||
{
|
||||
if(bool)
|
||||
return 'Y';
|
||||
else
|
||||
return 'N';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
global static String toString(Boolean bool,
|
||||
String trueString,
|
||||
String falseString)
|
||||
{
|
||||
if(bool==null)
|
||||
return null;
|
||||
else
|
||||
{
|
||||
if(bool)
|
||||
return trueString;
|
||||
else
|
||||
return falseString;
|
||||
}
|
||||
}
|
||||
|
||||
global static Boolean xor(Boolean[] boolArray)
|
||||
{
|
||||
if(boolArray==null || boolArray.size()==0)
|
||||
throw new IllegalArgumentException();
|
||||
else
|
||||
{
|
||||
Boolean firstItem=boolArray[0];
|
||||
for(Boolean bool:boolArray)
|
||||
{
|
||||
if(bool!=firstItem)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
98
samples/Apex/EmailUtils.cls
Normal file
98
samples/Apex/EmailUtils.cls
Normal file
@@ -0,0 +1,98 @@
|
||||
/* ============================================================
|
||||
* Contributor: Caleb Sidel
|
||||
*
|
||||
* This code is part of the "apex-lang" open source project avaiable at:
|
||||
*
|
||||
* http://code.google.com/p/apex-lang/
|
||||
*
|
||||
* This code is licensed under the Apache License, Version 2.0. You may obtain a
|
||||
* copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* ============================================================
|
||||
*/
|
||||
global class EmailUtils {
|
||||
|
||||
global static void sendEmailWithStandardAttachments(List<String> recipients,String emailSubject,String body,Boolean useHTML,List<Id> attachmentIDs) {
|
||||
List<Attachment> stdAttachments = [SELECT id, name, body FROM Attachment WHERE Id IN:attachmentIDs];
|
||||
sendEmailWithStandardAttachments(recipients, emailSubject, body, useHTML, stdAttachments);
|
||||
}
|
||||
|
||||
global static void sendEmailWithStandardAttachments(List<String> recipients,String emailSubject,String body,Boolean useHTML,List<Attachment> stdAttachments) {
|
||||
List<Messaging.EmailFileAttachment> fileAttachments = new List<Messaging.EmailFileAttachment>();
|
||||
|
||||
for(Attachment attachment : stdAttachments) {
|
||||
Messaging.EmailFileAttachment fileAttachment = new Messaging.EmailFileAttachment();
|
||||
fileAttachment.setFileName(attachment.Name);
|
||||
fileAttachment.setBody(attachment.Body);
|
||||
fileAttachments.add(fileAttachment);
|
||||
}
|
||||
sendEmail(recipients, emailSubject, body, useHTML, fileAttachments);
|
||||
}
|
||||
|
||||
global static void sendTextEmail(List<String> recipients,String emailSubject,String textBody) {
|
||||
sendEmail(recipients, emailSubject, textBody, false, null);
|
||||
}
|
||||
|
||||
global static void sendHTMLEmail(List<String> recipients,String emailSubject,String htmlBody) {
|
||||
sendEmail(recipients, emailSubject, htmlBody, true, null);
|
||||
}
|
||||
|
||||
global static void sendEmail(List<String> recipients,String emailSubject,String body,Boolean useHTML,List<Messaging.EmailFileAttachment> fileAttachments) {
|
||||
if(recipients == null) return;
|
||||
if(recipients.size() == 0) return;
|
||||
// Create a new single email message object
|
||||
// that will send out a single email to the addresses in the To, CC & BCC list.
|
||||
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
|
||||
//the email is not saved as an activity.
|
||||
mail.setSaveAsActivity(false);
|
||||
// Assign the addresses for the To lists to the mail object.
|
||||
mail.setToAddresses(recipients);
|
||||
// Specify the subject line for your email address.
|
||||
mail.setSubject(emailSubject);
|
||||
// Set to True if you want to BCC yourself on the email.
|
||||
mail.setBccSender(false);
|
||||
// The email address of the user executing the Apex Code will be used.
|
||||
mail.setUseSignature(false);
|
||||
if (useHTML) {
|
||||
// Specify the html content of the email.
|
||||
mail.setHtmlBody(body);
|
||||
} else {
|
||||
// Specify the text content of the email.
|
||||
mail.setPlainTextBody(body);
|
||||
}
|
||||
// Specify FileAttachments
|
||||
if(fileAttachments != null && fileAttachments.size() > 0) {
|
||||
mail.setFileAttachments(fileAttachments);
|
||||
}
|
||||
// Send the email you have created.
|
||||
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
|
||||
}
|
||||
|
||||
/**
|
||||
* null => false
|
||||
* '' => false
|
||||
* ' ' => false
|
||||
* 'x' => false
|
||||
* 'x@' => false
|
||||
* 'x@x' => false
|
||||
* 'x@x.x' => true
|
||||
*/
|
||||
global static Boolean isValidEmailAddress(String str){
|
||||
if(str != null && str.trim() != null && str.trim().length() > 0){
|
||||
String[] split = str.split('@');
|
||||
if(split != null && split.size() == 2){
|
||||
split = split[1].split('\\.');
|
||||
if(split != null && split.size() >= 2){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
global static Boolean isNotValidEmailAddress(String str){
|
||||
return !isValidEmailAddress(str);
|
||||
}
|
||||
|
||||
}
|
||||
55
samples/Apex/GeoUtils.cls
Normal file
55
samples/Apex/GeoUtils.cls
Normal file
@@ -0,0 +1,55 @@
|
||||
public class GeoUtils {
|
||||
// generate a KML string given a page reference, call getContent()
|
||||
// then cleanup the output.
|
||||
public static string generateFromContent(PageReference pr) {
|
||||
string ret = '';
|
||||
try {
|
||||
ret = (string) pr.getContent().toString();
|
||||
|
||||
ret = ret.replaceAll('"','\'' ); // get content produces quote chars \"
|
||||
ret = ret.replaceAll( '&','&');// we need to escape these in the node value
|
||||
} catch (exception e ) {
|
||||
system.debug( 'ERROR '+e);
|
||||
}
|
||||
|
||||
ret = ret.replaceAll('\n',' '); // must use ALL since many new line may get
|
||||
ret = ret.replaceAll('\r',' '); // get these also!
|
||||
// system.debug( ret); // dump the KML
|
||||
return ret ;
|
||||
}
|
||||
|
||||
public static Map<String, String> geo_response = new Map<String, String>{'200'=>'G_GEO_SUCCESS',
|
||||
'400'=>'G_GEO_BAD_REQUEST',
|
||||
'500'=>'G_GEO_SERVER_ERROR',
|
||||
'601'=>'G_GEO_MISSING_ADDRESS',
|
||||
'602'=>'G_GEO_UNKNOWN_ADDRESS',
|
||||
'603'=>'G_GEO_UNAVAILABLE_ADDRESS',
|
||||
'604'=>'G_GEO_UNKNOWN_DIRECTIONS',
|
||||
'610'=>'G_GEO_BAD_KEY',
|
||||
'620'=>'G_GEO_TOO_MANY_QUERIES'
|
||||
};
|
||||
|
||||
public static string accountAddressString ( account acct ) {
|
||||
// form an address string given an account object
|
||||
string adr = acct.billingstreet + ',' + acct.billingcity + ',' + acct.billingstate;
|
||||
if ( acct.billingpostalcode != null ) adr += ',' + acct.billingpostalcode;
|
||||
if ( acct.billingcountry != null ) adr += ',' + acct.billingcountry;
|
||||
adr = adr.replaceAll('\"', '' );
|
||||
adr = adr.replaceAll('\'', '' );
|
||||
adr = adr.replaceAll( '\n', ' ' );
|
||||
adr = adr.replaceAll( '\r', ' ' );
|
||||
system.debug( adr );
|
||||
return adr;
|
||||
}
|
||||
|
||||
public static testmethod void t1() {
|
||||
PageReference pageRef = Page.kmlPreviewTemplate;
|
||||
Test.setCurrentPage(pageRef);
|
||||
system.assert ( GeoUtils.generateFromContent( pageRef ) != null );
|
||||
Account a = new Account( name='foo', billingstreet='main', billingcity='springfield',billingstate='il',
|
||||
billingpostalcode='9',billingcountry='us');
|
||||
insert a;
|
||||
system.assertEquals( 'main,springfield,il,9,us',accountAddressString( a) );
|
||||
|
||||
}
|
||||
}
|
||||
740
samples/Apex/LanguageUtils.cls
Normal file
740
samples/Apex/LanguageUtils.cls
Normal file
@@ -0,0 +1,740 @@
|
||||
/* ============================================================
|
||||
* This code is part of the "apex-lang" open source project avaiable at:
|
||||
*
|
||||
* http://code.google.com/p/apex-lang/
|
||||
*
|
||||
* This code is licensed under the Apache License, Version 2.0. You may obtain a
|
||||
* copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* ============================================================
|
||||
*/
|
||||
global class LanguageUtils {
|
||||
|
||||
global static final String HTTP_LANGUAGE_CODE_PARAMETER_KEY = 'l';
|
||||
global static final String DEFAULT_LANGUAGE_CODE = 'en_us';
|
||||
|
||||
global static Set<String> SUPPORTED_LANGUAGE_CODES = new Set<String>{
|
||||
'zh-cn' //Chinese (Simplified)
|
||||
,'zh-tw' //Chinese (Traditional)
|
||||
,'nl-nl' //Dutch
|
||||
,'en-us' //English
|
||||
,'fi' //Finnish
|
||||
,'fr' //French
|
||||
,'de' //German
|
||||
,'it' //Italian
|
||||
,'ja' //Japanese
|
||||
,'ko' //Korean
|
||||
,'pl' //Polish
|
||||
,'pt-br' //Portuguese (Brazilian)
|
||||
,'ru' //Russian
|
||||
,'es' //Spanish
|
||||
,'sv' //Swedish
|
||||
,'th' //Thai
|
||||
,'cs' //Czech
|
||||
,'da' //Danish
|
||||
,'hu' //Hungarian
|
||||
,'in' //Indonesian
|
||||
,'tr' //Turkish
|
||||
};
|
||||
|
||||
private static Map<String,String> DEFAULTS = new Map<String,String>{
|
||||
'en'=>'en-us'
|
||||
,'zh'=>'zh-cn'
|
||||
,'nl'=>'nl-nl'
|
||||
,'pt'=>'pt-br'
|
||||
};
|
||||
|
||||
|
||||
global static String getLangCodeByHttpParam(){
|
||||
String returnValue = null;
|
||||
final Set<String> LANGUAGE_CODE_SET = getSuppLangCodeSet();
|
||||
if(ApexPages.currentPage() != null && ApexPages.currentPage().getParameters() != null){
|
||||
String LANGUAGE_HTTP_PARAMETER =
|
||||
StringUtils.lowerCase(
|
||||
StringUtils.replaceChars(
|
||||
ApexPages.currentPage().getParameters().get(HTTP_LANGUAGE_CODE_PARAMETER_KEY)
|
||||
, '_' //underscore
|
||||
, '-' //dash
|
||||
)
|
||||
);
|
||||
if(DEFAULTS.containsKey(LANGUAGE_HTTP_PARAMETER)){
|
||||
LANGUAGE_HTTP_PARAMETER = DEFAULTS.get(LANGUAGE_HTTP_PARAMETER);
|
||||
}
|
||||
if(StringUtils.isNotBlank(LANGUAGE_HTTP_PARAMETER)
|
||||
&& SUPPORTED_LANGUAGE_CODES.contains(LANGUAGE_HTTP_PARAMETER)){
|
||||
returnValue = LANGUAGE_HTTP_PARAMETER;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
global static String getLangCodeByBrowser(){
|
||||
final String LANGUAGES_FROM_BROWSER_AS_STRING = ApexPages.currentPage().getHeaders().get('Accept-Language');
|
||||
final List<String> LANGUAGES_FROM_BROWSER_AS_LIST = splitAndFilterAcceptLanguageHeader(LANGUAGES_FROM_BROWSER_AS_STRING);
|
||||
if(LANGUAGES_FROM_BROWSER_AS_LIST != null && LANGUAGES_FROM_BROWSER_AS_LIST.size() > 0){
|
||||
for(String languageFromBrowser : LANGUAGES_FROM_BROWSER_AS_LIST){
|
||||
if(DEFAULTS.containsKey(languageFromBrowser)){
|
||||
languageFromBrowser = DEFAULTS.get(languageFromBrowser);
|
||||
}
|
||||
if(SUPPORTED_LANGUAGE_CODES.contains(languageFromBrowser)){
|
||||
return languageFromBrowser;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
global static String getLangCodeByUser(){
|
||||
return UserInfo.getLanguage();
|
||||
}
|
||||
|
||||
global static String getLangCodeByHttpParamOrIfNullThenBrowser(){
|
||||
return StringUtils.defaultString(getLangCodeByHttpParam(),getLangCodeByBrowser());
|
||||
}
|
||||
|
||||
global static String getLangCodeByHttpParamOrIfNullThenUser(){
|
||||
return StringUtils.defaultString(getLangCodeByHttpParam(),getLangCodeByUser());
|
||||
}
|
||||
|
||||
global static String getLangCodeByBrowserOrIfNullThenHttpParam(){
|
||||
return StringUtils.defaultString(getLangCodeByBrowser(),getLangCodeByHttpParam());
|
||||
}
|
||||
|
||||
global static String getLangCodeByBrowserOrIfNullThenUser(){
|
||||
return StringUtils.defaultString(getLangCodeByBrowser(),getLangCodeByUser());
|
||||
}
|
||||
|
||||
private static List<String> splitAndFilterAcceptLanguageHeader(String header){
|
||||
List<String> returnList = new List<String>();
|
||||
String[] tokens = StringUtils.split(header,',');
|
||||
if(tokens != null){
|
||||
for(String token : tokens){
|
||||
if(token != null ){
|
||||
if(token.contains(';')){
|
||||
token = token.substring(0,token.indexOf(';',0));
|
||||
}
|
||||
returnList.add(token);
|
||||
if(StringUtils.length(token) > 2){
|
||||
returnList.add(StringUtils.substring(token,0,2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private static Set<String> getSuppLangCodeSet(){
|
||||
Set<String> langCodes = new Set<String>();
|
||||
for(String langCode : SUPPORTED_LANGUAGE_CODES){
|
||||
if(langCode != null){
|
||||
langCodes.add(StringUtils.lowerCase(langCode));
|
||||
}
|
||||
}
|
||||
return langCodes;
|
||||
}
|
||||
|
||||
|
||||
global static String getLanguageName(String displayLanguageCode, String languageCode){
|
||||
return translatedLanguageNames.get(filterLanguageCode(displayLanguageCode)).get(filterLanguageCode(languageCode));
|
||||
}
|
||||
|
||||
global static Map<String,String> getAllLanguages(){
|
||||
return getAllLanguages(DEFAULT_LANGUAGE_CODE);
|
||||
}
|
||||
|
||||
global static Map<String,String> getAllLanguages(String displayLanguageCode){
|
||||
return translatedLanguageNames.get(filterLanguageCode(displayLanguageCode));
|
||||
}
|
||||
|
||||
private static String filterLanguageCode(String displayLanguageCode){
|
||||
displayLanguageCode = StringUtils.lowerCase(displayLanguageCode);
|
||||
if(DEFAULTS.containsKey(displayLanguageCode)){
|
||||
displayLanguageCode = StringUtils.replaceChars(DEFAULTS.get(displayLanguageCode),'-','_');
|
||||
}
|
||||
if(!translatedLanguageNames.containsKey(displayLanguageCode)){
|
||||
displayLanguageCode = DEFAULT_LANGUAGE_CODE;
|
||||
}
|
||||
return displayLanguageCode;
|
||||
}
|
||||
|
||||
private static final Map<String,Map<String,String>> translatedLanguageNames = new Map<String,Map<String,String>>{
|
||||
'cs'=> new Map<String,String>{
|
||||
'cs'=>'Čeština'
|
||||
,'da'=>'Dánština'
|
||||
,'de'=>'Němčina'
|
||||
,'en_us'=>'Angličtina (Spojené státy)'
|
||||
,'es'=>'Španělština'
|
||||
,'es_mx'=>'Mexická španělština'
|
||||
,'fi'=>'Finština'
|
||||
,'fr'=>'Francouzština'
|
||||
,'hu'=>'Maďarština'
|
||||
,'in'=>'Indonéština'
|
||||
,'it'=>'Italština'
|
||||
,'ja'=>'Japonština'
|
||||
,'ko'=>'Korejština'
|
||||
,'nl_nl'=>'Nizozemština'
|
||||
,'pl'=>'Polština'
|
||||
,'pt_br'=>'Portugalština (Brazílie)'
|
||||
,'ro'=>'Rumunština'
|
||||
,'ru'=>'Ruština'
|
||||
,'sv'=>'Švédština'
|
||||
,'th'=>'Thajská'
|
||||
,'tr'=>'Turečtina'
|
||||
,'zh_cn'=>'Čínština (zjednodušená)'
|
||||
,'zh_tw'=>'Čínština (tradiční)'
|
||||
}
|
||||
,'da'=> new Map<String,String>{
|
||||
'cs'=>'Tjekkisk'
|
||||
,'da'=>'Dansk'
|
||||
,'de'=>'Tysk'
|
||||
,'en_us'=>'Engelsk (USA)'
|
||||
,'es'=>'Spansk'
|
||||
,'es_mx'=>'Mexicansk spansk'
|
||||
,'fi'=>'Finsk'
|
||||
,'fr'=>'Fransk'
|
||||
,'hu'=>'Ungarsk'
|
||||
,'in'=>'Indonesisk'
|
||||
,'it'=>'Italiensk'
|
||||
,'ja'=>'Japansk'
|
||||
,'ko'=>'Koreansk'
|
||||
,'nl_nl'=>'Hollandsk'
|
||||
,'pl'=>'Polsk'
|
||||
,'pt_br'=>'Portugisisk (Brasilien)'
|
||||
,'ro'=>'Rumænsk'
|
||||
,'ru'=>'Russisk'
|
||||
,'sv'=>'Svensk'
|
||||
,'th'=>'Thai'
|
||||
,'tr'=>'Tyrkisk'
|
||||
,'zh_cn'=>'Kinesisk (forenklet)'
|
||||
,'zh_tw'=>'Kinesisk (traditionelt)'
|
||||
}
|
||||
,'de'=> new Map<String,String>{
|
||||
'cs'=>'Tschechisch'
|
||||
,'da'=>'Dänisch'
|
||||
,'de'=>'Deutsch'
|
||||
,'en_us'=>'Englisch (Vereinigte Staaten)'
|
||||
,'es'=>'Spanisch'
|
||||
,'es_mx'=>'Mexican Spanish'
|
||||
,'fi'=>'Finnisch'
|
||||
,'fr'=>'Französisch'
|
||||
,'hu'=>'Ungarisch'
|
||||
,'in'=>'Indonesisch'
|
||||
,'it'=>'Italienisch'
|
||||
,'ja'=>'Japanisch'
|
||||
,'ko'=>'Koreanisch'
|
||||
,'nl_nl'=>'Niederländisch'
|
||||
,'pl'=>'Polnisch'
|
||||
,'pt_br'=>'Portugiesisch (Brasilien)'
|
||||
,'ro'=>'Rumänisch'
|
||||
,'ru'=>'Russisch'
|
||||
,'sv'=>'Schwedisch'
|
||||
,'th'=>'Thai'
|
||||
,'tr'=>'Türkisch'
|
||||
,'zh_cn'=>'Chinesisch (Taiwan)'
|
||||
,'zh_tw'=>'Chinesisch (traditionell)'
|
||||
}
|
||||
,'en_us'=> new Map<String,String>{
|
||||
'cs'=>'Czech'
|
||||
,'da'=>'Danish'
|
||||
,'de'=>'German'
|
||||
,'en_us'=>'English (United States)'
|
||||
,'es'=>'Spanish'
|
||||
,'es_mx'=>'Mexican Spanish'
|
||||
,'fi'=>'Finnish'
|
||||
,'fr'=>'French'
|
||||
,'hu'=>'Hungarian'
|
||||
,'in'=>'Indonesian'
|
||||
,'it'=>'Italian'
|
||||
,'ja'=>'Japanese'
|
||||
,'ko'=>'Korean'
|
||||
,'nl_nl'=>'Dutch'
|
||||
,'pl'=>'Polish'
|
||||
,'pt_br'=>'Portuguese (Brazilian)'
|
||||
,'ro'=>'Romanian'
|
||||
,'ru'=>'Russian'
|
||||
,'sv'=>'Swedish'
|
||||
,'th'=>'Thai'
|
||||
,'tr'=>'Turkish'
|
||||
,'zh_cn'=>'Chinese (Simplified)'
|
||||
,'zh_tw'=>'Chinese (Traditional)'
|
||||
}
|
||||
,'es'=> new Map<String,String>{
|
||||
'cs'=>'Checa'
|
||||
,'da'=>'Danés'
|
||||
,'de'=>'Alemán'
|
||||
,'en_us'=>'Inglés (Estados Unidos)'
|
||||
,'es'=>'Español'
|
||||
,'es_mx'=>'El español de México'
|
||||
,'fi'=>'Finlandés'
|
||||
,'fr'=>'Francés'
|
||||
,'hu'=>'Húngaro'
|
||||
,'in'=>'Indonesia'
|
||||
,'it'=>'Italiano'
|
||||
,'ja'=>'Japonés'
|
||||
,'ko'=>'Corea'
|
||||
,'nl_nl'=>'Neerlandés'
|
||||
,'pl'=>'Polaco'
|
||||
,'pt_br'=>'Portugués (brasileño)'
|
||||
,'ro'=>'Rumano'
|
||||
,'ru'=>'Rusia'
|
||||
,'sv'=>'Sueco'
|
||||
,'th'=>'Tailandia'
|
||||
,'tr'=>'Turquía'
|
||||
,'zh_cn'=>'Chino (simplificado)'
|
||||
,'zh_tw'=>'Chino (tradicional)'
|
||||
}
|
||||
,'es_mx'=> new Map<String,String>{
|
||||
'cs'=>'Checa'
|
||||
,'da'=>'Danés'
|
||||
,'de'=>'Alemán'
|
||||
,'en_us'=>'Inglés (Estados Unidos)'
|
||||
,'es'=>'Español'
|
||||
,'es_mx'=>'El español de México'
|
||||
,'fi'=>'Finlandés'
|
||||
,'fr'=>'Francés'
|
||||
,'hu'=>'Húngaro'
|
||||
,'in'=>'Indonesia'
|
||||
,'it'=>'Italiano'
|
||||
,'ja'=>'Japonés'
|
||||
,'ko'=>'Corea'
|
||||
,'nl_nl'=>'Neerlandés'
|
||||
,'pl'=>'Polaco'
|
||||
,'pt_br'=>'Portugués (brasileño)'
|
||||
,'ro'=>'Rumano'
|
||||
,'ru'=>'Rusia'
|
||||
,'sv'=>'Sueco'
|
||||
,'th'=>'Tailandia'
|
||||
,'tr'=>'Turquía'
|
||||
,'zh_cn'=>'Chino (simplificado)'
|
||||
,'zh_tw'=>'Chino (tradicional)'
|
||||
}
|
||||
,'fi'=> new Map<String,String>{
|
||||
'cs'=>'Tšekki'
|
||||
,'da'=>'Tanska'
|
||||
,'de'=>'Saksa'
|
||||
,'en_us'=>'Englanti (Yhdysvallat)'
|
||||
,'es'=>'Espanja'
|
||||
,'es_mx'=>'Meksikon espanja'
|
||||
,'fi'=>'Suomen'
|
||||
,'fr'=>'Ranska'
|
||||
,'hu'=>'Unkari'
|
||||
,'in'=>'Indonesia'
|
||||
,'it'=>'Italia'
|
||||
,'ja'=>'Japani'
|
||||
,'ko'=>'Korea'
|
||||
,'nl_nl'=>'Hollanti'
|
||||
,'pl'=>'Puola'
|
||||
,'pt_br'=>'Portugali (Brasilia)'
|
||||
,'ro'=>'Romania'
|
||||
,'ru'=>'Venäjä'
|
||||
,'sv'=>'Ruotsi'
|
||||
,'th'=>'Thaimaalaisen'
|
||||
,'tr'=>'Turkki'
|
||||
,'zh_cn'=>'Kiina (yksinkertaistettu)'
|
||||
,'zh_tw'=>'Kiina (perinteinen)'
|
||||
}
|
||||
,'fr'=> new Map<String,String>{
|
||||
'cs'=>'Tchèque'
|
||||
,'da'=>'Danois'
|
||||
,'de'=>'Allemand'
|
||||
,'en_us'=>'Anglais (Etats Unis)'
|
||||
,'es'=>'Espagnol'
|
||||
,'es_mx'=>'Espagnol mexicain'
|
||||
,'fi'=>'Finnois'
|
||||
,'fr'=>'Français'
|
||||
,'hu'=>'Hongrois'
|
||||
,'in'=>'Indonésien'
|
||||
,'it'=>'Italien'
|
||||
,'ja'=>'Japonais'
|
||||
,'ko'=>'Coréen'
|
||||
,'nl_nl'=>'Néerlandais'
|
||||
,'pl'=>'Polonais'
|
||||
,'pt_br'=>'Portugais (brésilien)'
|
||||
,'ro'=>'Roumain'
|
||||
,'ru'=>'Russe'
|
||||
,'sv'=>'Suédois'
|
||||
,'th'=>'Thai'
|
||||
,'tr'=>'Turc'
|
||||
,'zh_cn'=>'Chinois (simplifié)'
|
||||
,'zh_tw'=>'Chinois (Traditionnel)'
|
||||
}
|
||||
,'hu'=> new Map<String,String>{
|
||||
'cs'=>'Cseh'
|
||||
,'da'=>'Dán'
|
||||
,'de'=>'Német'
|
||||
,'en_us'=>'Angol (Egyesült Államok)'
|
||||
,'es'=>'Spanyol'
|
||||
,'es_mx'=>'Mexikói spanyol'
|
||||
,'fi'=>'Finn'
|
||||
,'fr'=>'Francia'
|
||||
,'hu'=>'Magyar'
|
||||
,'in'=>'Indonéz'
|
||||
,'it'=>'Olasz'
|
||||
,'ja'=>'Japán'
|
||||
,'ko'=>'Koreai'
|
||||
,'nl_nl'=>'Holland'
|
||||
,'pl'=>'Lengyel'
|
||||
,'pt_br'=>'Portugál (brazíliai)'
|
||||
,'ro'=>'Román'
|
||||
,'ru'=>'Orosz'
|
||||
,'sv'=>'Svéd'
|
||||
,'th'=>'Thaiföldi'
|
||||
,'tr'=>'Török'
|
||||
,'zh_cn'=>'Kínai (egyszerűsített)'
|
||||
,'zh_tw'=>'Kínai (hagyományos)'
|
||||
}
|
||||
,'in'=> new Map<String,String>{
|
||||
'cs'=>'Ceko'
|
||||
,'da'=>'Denmark'
|
||||
,'de'=>'Jerman'
|
||||
,'en_us'=>'Inggris (Amerika Serikat)'
|
||||
,'es'=>'Spanyol'
|
||||
,'es_mx'=>'Meksiko Spanyol'
|
||||
,'fi'=>'Finlandia'
|
||||
,'fr'=>'Prancis'
|
||||
,'hu'=>'Hungaria'
|
||||
,'in'=>'Indonesia'
|
||||
,'it'=>'Italia'
|
||||
,'ja'=>'Jepang'
|
||||
,'ko'=>'Korea'
|
||||
,'nl_nl'=>'Belanda'
|
||||
,'pl'=>'Polish'
|
||||
,'pt_br'=>'Portugis (Brasil)'
|
||||
,'ro'=>'Romanian'
|
||||
,'ru'=>'Russian'
|
||||
,'sv'=>'Swedia'
|
||||
,'th'=>'Thai'
|
||||
,'tr'=>'Turkish'
|
||||
,'zh_cn'=>'Cina (Sederhana)'
|
||||
,'zh_tw'=>'Cina (Tradisional)'
|
||||
}
|
||||
,'it'=> new Map<String,String>{
|
||||
'cs'=>'Ceco'
|
||||
,'da'=>'Danese'
|
||||
,'de'=>'Tedesco'
|
||||
,'en_us'=>'Inglese (Stati Uniti)'
|
||||
,'es'=>'Spagnolo'
|
||||
,'es_mx'=>'Spagnolo messicano'
|
||||
,'fi'=>'Finlandese'
|
||||
,'fr'=>'Francese'
|
||||
,'hu'=>'Ungherese'
|
||||
,'in'=>'Indonesiano'
|
||||
,'it'=>'Italiano'
|
||||
,'ja'=>'Giapponese'
|
||||
,'ko'=>'Coreano'
|
||||
,'nl_nl'=>'Olandese'
|
||||
,'pl'=>'Polacco'
|
||||
,'pt_br'=>'Portoghese (brasiliano)'
|
||||
,'ro'=>'Rumeno'
|
||||
,'ru'=>'Russo'
|
||||
,'sv'=>'Svedese'
|
||||
,'th'=>'Thai'
|
||||
,'tr'=>'Turco'
|
||||
,'zh_cn'=>'Cinese (semplificato)'
|
||||
,'zh_tw'=>'Cinese (tradizionale)'
|
||||
}
|
||||
,'ja'=> new Map<String,String>{
|
||||
'cs'=>'チェコ語'
|
||||
,'da'=>'デンマーク語'
|
||||
,'de'=>'ドイツ語'
|
||||
,'en_us'=>'英語(アメリカ合衆国)'
|
||||
,'es'=>'スペイン語'
|
||||
,'es_mx'=>'メキシコのスペイン語'
|
||||
,'fi'=>'フィンランド語'
|
||||
,'fr'=>'フランス語'
|
||||
,'hu'=>'ハンガリー語'
|
||||
,'in'=>'インドネシア語'
|
||||
,'it'=>'イタリア語'
|
||||
,'ja'=>'日本語'
|
||||
,'ko'=>'韓国語'
|
||||
,'nl_nl'=>'オランダ語'
|
||||
,'pl'=>'ポーランド語'
|
||||
,'pt_br'=>'ポルトガル語(ブラジル)'
|
||||
,'ro'=>'ルーマニア語'
|
||||
,'ru'=>'ロシア語'
|
||||
,'sv'=>'スウェーデン語'
|
||||
,'th'=>'タイ'
|
||||
,'tr'=>'トルコ語'
|
||||
,'zh_cn'=>'中国語(簡体字)'
|
||||
,'zh_tw'=>'中国語(繁体字)'
|
||||
}
|
||||
,'ko'=> new Map<String,String>{
|
||||
'cs'=>'체코어'
|
||||
,'da'=>'덴마크어'
|
||||
,'de'=>'독일어'
|
||||
,'en_us'=>'영어 (미국)'
|
||||
,'es'=>'스페인어'
|
||||
,'es_mx'=>'멕시코 스페인'
|
||||
,'fi'=>'핀란드어'
|
||||
,'fr'=>'프랑스어'
|
||||
,'hu'=>'헝가리어'
|
||||
,'in'=>'인도네시 아어'
|
||||
,'it'=>'이탈리아어'
|
||||
,'ja'=>'일본어'
|
||||
,'ko'=>'한국어'
|
||||
,'nl_nl'=>'네덜란드'
|
||||
,'pl'=>'폴란드어'
|
||||
,'pt_br'=>'포르투갈어 (브라질)'
|
||||
,'ro'=>'루마니아어'
|
||||
,'ru'=>'러시아어'
|
||||
,'sv'=>'스웨덴어'
|
||||
,'th'=>'타이어'
|
||||
,'tr'=>'터키어'
|
||||
,'zh_cn'=>'중국어 (간체)'
|
||||
,'zh_tw'=>'중국어 (번체)'
|
||||
}
|
||||
,'nl_nl'=> new Map<String,String>{
|
||||
'cs'=>'Tsjechisch'
|
||||
,'da'=>'Deens'
|
||||
,'de'=>'Duits'
|
||||
,'en_us'=>'Engels (Verenigde Staten)'
|
||||
,'es'=>'Spaans'
|
||||
,'es_mx'=>'Mexicaans Spaans'
|
||||
,'fi'=>'Fins'
|
||||
,'fr'=>'Frans'
|
||||
,'hu'=>'Hongaars'
|
||||
,'in'=>'Indonesisch'
|
||||
,'it'=>'Italiaans'
|
||||
,'ja'=>'Japans'
|
||||
,'ko'=>'Koreaans'
|
||||
,'nl_nl'=>'Nederlandse'
|
||||
,'pl'=>'Pools'
|
||||
,'pt_br'=>'Portugees (Braziliaans)'
|
||||
,'ro'=>'Roemeens'
|
||||
,'ru'=>'Russisch'
|
||||
,'sv'=>'Zweeds'
|
||||
,'th'=>'Thais'
|
||||
,'tr'=>'Turks'
|
||||
,'zh_cn'=>'Chinese (Simplified)'
|
||||
,'zh_tw'=>'Chinees (traditioneel)'
|
||||
}
|
||||
,'pl'=> new Map<String,String>{
|
||||
'cs'=>'Czeski'
|
||||
,'da'=>'Duński'
|
||||
,'de'=>'Niemiecki'
|
||||
,'en_us'=>'Angielski (Stany Zjednoczone)'
|
||||
,'es'=>'Hiszpański'
|
||||
,'es_mx'=>'Mexican hiszpański'
|
||||
,'fi'=>'Fiński'
|
||||
,'fr'=>'Francuski'
|
||||
,'hu'=>'Węgierski'
|
||||
,'in'=>'Indonezyjski'
|
||||
,'it'=>'Włoski'
|
||||
,'ja'=>'Japoński'
|
||||
,'ko'=>'Koreański'
|
||||
,'nl_nl'=>'Niderlandzki'
|
||||
,'pl'=>'Polska'
|
||||
,'pt_br'=>'Portugalski (Brazylia)'
|
||||
,'ro'=>'Rumuński'
|
||||
,'ru'=>'Rosyjski'
|
||||
,'sv'=>'Szwedzki'
|
||||
,'th'=>'Taj'
|
||||
,'tr'=>'Turecki'
|
||||
,'zh_cn'=>'Chiński (uproszczony)'
|
||||
,'zh_tw'=>'Chiński (tradycyjny)'
|
||||
}
|
||||
,'pt_br'=> new Map<String,String>{
|
||||
'cs'=>'Tcheco'
|
||||
,'da'=>'Dinamarquês'
|
||||
,'de'=>'Alemão'
|
||||
,'en_us'=>'Inglês (Estados Unidos)'
|
||||
,'es'=>'Espanhol'
|
||||
,'es_mx'=>'Espanhol mexicano'
|
||||
,'fi'=>'Finlandês'
|
||||
,'fr'=>'Francês'
|
||||
,'hu'=>'Húngaro'
|
||||
,'in'=>'Indonésio'
|
||||
,'it'=>'Italiano'
|
||||
,'ja'=>'Japonês'
|
||||
,'ko'=>'Coreano'
|
||||
,'nl_nl'=>'Holandês'
|
||||
,'pl'=>'Polonês'
|
||||
,'pt_br'=>'Português (Brasil)'
|
||||
,'ro'=>'Romeno'
|
||||
,'ru'=>'Russo'
|
||||
,'sv'=>'Sueco'
|
||||
,'th'=>'Tailandês'
|
||||
,'tr'=>'Turco'
|
||||
,'zh_cn'=>'Chinês (simplificado)'
|
||||
,'zh_tw'=>'Chinês (Tradicional)'
|
||||
}
|
||||
,'ro'=> new Map<String,String>{
|
||||
'cs'=>'Cehă'
|
||||
,'da'=>'Daneză'
|
||||
,'de'=>'Germană'
|
||||
,'en_us'=>'În limba engleză (Statele Unite)'
|
||||
,'es'=>'Spaniolă'
|
||||
,'es_mx'=>'Mexicane Spanish'
|
||||
,'fi'=>'Finlandeză'
|
||||
,'fr'=>'Franţuzesc'
|
||||
,'hu'=>'Maghiară'
|
||||
,'in'=>'Indoneziană'
|
||||
,'it'=>'Italiană'
|
||||
,'ja'=>'Japoneză'
|
||||
,'ko'=>'Coreeană'
|
||||
,'nl_nl'=>'Olandeză'
|
||||
,'pl'=>'Poloneză'
|
||||
,'pt_br'=>'Portuguese (Brazilian)'
|
||||
,'ro'=>'Român'
|
||||
,'ru'=>'Rus'
|
||||
,'sv'=>'Suedez'
|
||||
,'th'=>'Thai'
|
||||
,'tr'=>'Turcă'
|
||||
,'zh_cn'=>'Chineză (simplificată)'
|
||||
,'zh_tw'=>'Chineză (Tradiţională)'
|
||||
}
|
||||
,'ru'=> new Map<String,String>{
|
||||
'cs'=>'Чешский'
|
||||
,'da'=>'Датский'
|
||||
,'de'=>'Немецкий'
|
||||
,'en_us'=>'Английский (США)'
|
||||
,'es'=>'Испанский'
|
||||
,'es_mx'=>'Мексиканские Испанский'
|
||||
,'fi'=>'Финский'
|
||||
,'fr'=>'Французский'
|
||||
,'hu'=>'Венгерский'
|
||||
,'in'=>'Индонезийский'
|
||||
,'it'=>'Итальянский'
|
||||
,'ja'=>'Японский'
|
||||
,'ko'=>'Корейский'
|
||||
,'nl_nl'=>'Голландский'
|
||||
,'pl'=>'Польский'
|
||||
,'pt_br'=>'Португальский (бразильский)'
|
||||
,'ro'=>'Румынский'
|
||||
,'ru'=>'Русский'
|
||||
,'sv'=>'Шведский'
|
||||
,'th'=>'Тайский'
|
||||
,'tr'=>'Турецкий'
|
||||
,'zh_cn'=>'Китайский (упрощенный)'
|
||||
,'zh_tw'=>'Китайский (традиционный)'
|
||||
}
|
||||
,'sv'=> new Map<String,String>{
|
||||
'cs'=>'Tjeckiska'
|
||||
,'da'=>'Danska'
|
||||
,'de'=>'Tyska'
|
||||
,'en_us'=>'Engelska (USA)'
|
||||
,'es'=>'Spanska'
|
||||
,'es_mx'=>'Mexikansk spanska'
|
||||
,'fi'=>'Finska'
|
||||
,'fr'=>'Franska'
|
||||
,'hu'=>'Ungerska'
|
||||
,'in'=>'Indonesiska'
|
||||
,'it'=>'Italienska'
|
||||
,'ja'=>'Japanska'
|
||||
,'ko'=>'Koreanska'
|
||||
,'nl_nl'=>'Nederländska'
|
||||
,'pl'=>'Polska'
|
||||
,'pt_br'=>'Portugisiska (Brasilien)'
|
||||
,'ro'=>'Rumänska'
|
||||
,'ru'=>'Ryska'
|
||||
,'sv'=>'Svenska'
|
||||
,'th'=>'Thai'
|
||||
,'tr'=>'Turkiska'
|
||||
,'zh_cn'=>'Kinesiska (förenklad)'
|
||||
,'zh_tw'=>'Kinesiska (traditionell)'
|
||||
}
|
||||
,'th'=> new Map<String,String>{
|
||||
'cs'=>'สาธารณรัฐ เช็ ก'
|
||||
,'da'=>'เดนมาร์ก'
|
||||
,'de'=>'เยอรมัน'
|
||||
,'en_us'=>'ภาษา อังกฤษ States (United)'
|
||||
,'es'=>'สเปน'
|
||||
,'es_mx'=>'สเปน เม็ก ซิ กัน'
|
||||
,'fi'=>'ฟินแลนด์'
|
||||
,'fr'=>'ฝรั่งเศส'
|
||||
,'hu'=>'ฮังการี'
|
||||
,'in'=>'อินโดนีเซีย'
|
||||
,'it'=>'อิตาเลียน'
|
||||
,'ja'=>'ญี่ปุ่น'
|
||||
,'ko'=>'เกาหลี'
|
||||
,'nl_nl'=>'ดัตช์'
|
||||
,'pl'=>'เงา'
|
||||
,'pt_br'=>'โปรตุเกส (บราซิล)'
|
||||
,'ro'=>'โรมาเนีย'
|
||||
,'ru'=>'ภาษา รัสเซีย'
|
||||
,'sv'=>'สวีเดน'
|
||||
,'th'=>'ไทย'
|
||||
,'tr'=>'ภาษา ตุรกี'
|
||||
,'zh_cn'=>'จีน (ประยุกต์)'
|
||||
,'zh_tw'=>'ภาษา จีน (ดั้งเดิม)'
|
||||
}
|
||||
,'tr'=> new Map<String,String>{
|
||||
'cs'=>'Çekçe'
|
||||
,'da'=>'Danca'
|
||||
,'de'=>'Almanca'
|
||||
,'en_us'=>'İngilizce (ABD)'
|
||||
,'es'=>'İspanyolca'
|
||||
,'es_mx'=>'Mexican İspanyolca'
|
||||
,'fi'=>'Fince'
|
||||
,'fr'=>'Fransızca'
|
||||
,'hu'=>'Macarca'
|
||||
,'in'=>'Endonezya Dili'
|
||||
,'it'=>'İtalyanca'
|
||||
,'ja'=>'Japonca'
|
||||
,'ko'=>'Korece'
|
||||
,'nl_nl'=>'Hollanda Dili'
|
||||
,'pl'=>'Lehçe'
|
||||
,'pt_br'=>'Portekizce (Brezilya)'
|
||||
,'ro'=>'Romence'
|
||||
,'ru'=>'Rusça'
|
||||
,'sv'=>'İsveççe'
|
||||
,'th'=>'Tay'
|
||||
,'tr'=>'Türkçe'
|
||||
,'zh_cn'=>'Çince (Basitleştirilmiş)'
|
||||
,'zh_tw'=>'Çince (Geleneksel)'
|
||||
}
|
||||
,'zh_cn'=> new Map<String,String>{
|
||||
'cs'=>'捷克文'
|
||||
,'da'=>'丹麦文'
|
||||
,'de'=>'德语'
|
||||
,'en_us'=>'英语(美国)'
|
||||
,'es'=>'西班牙语'
|
||||
,'es_mx'=>'墨西哥西班牙语'
|
||||
,'fi'=>'芬兰文'
|
||||
,'fr'=>'法语'
|
||||
,'hu'=>'匈牙利文'
|
||||
,'in'=>'印度尼西亚文'
|
||||
,'it'=>'意大利语'
|
||||
,'ja'=>'日语'
|
||||
,'ko'=>'韩文'
|
||||
,'nl_nl'=>'荷兰文'
|
||||
,'pl'=>'波兰文'
|
||||
,'pt_br'=>'葡萄牙语(巴西)'
|
||||
,'ro'=>'罗马尼亚文'
|
||||
,'ru'=>'俄文'
|
||||
,'sv'=>'瑞典文'
|
||||
,'th'=>'泰国'
|
||||
,'tr'=>'土耳其文'
|
||||
,'zh_cn'=>'中文(简体)'
|
||||
,'zh_tw'=>'中文(繁体)'
|
||||
}
|
||||
,'zh_tw'=> new Map<String,String>{
|
||||
'cs'=>'捷克文'
|
||||
,'da'=>'丹麥文'
|
||||
,'de'=>'德語'
|
||||
,'en_us'=>'英語(美國)'
|
||||
,'es'=>'西班牙語'
|
||||
,'es_mx'=>'墨西哥西班牙語'
|
||||
,'fi'=>'芬蘭文'
|
||||
,'fr'=>'法語'
|
||||
,'hu'=>'匈牙利文'
|
||||
,'in'=>'印度尼西亞文'
|
||||
,'it'=>'意大利語'
|
||||
,'ja'=>'日語'
|
||||
,'ko'=>'韓文'
|
||||
,'nl_nl'=>'荷蘭文'
|
||||
,'pl'=>'波蘭文'
|
||||
,'pt_br'=>'葡萄牙語(巴西)'
|
||||
,'ro'=>'羅馬尼亞文'
|
||||
,'ru'=>'俄文'
|
||||
,'sv'=>'瑞典文'
|
||||
,'th'=>'泰國'
|
||||
,'tr'=>'土耳其文'
|
||||
,'zh_cn'=>'中文(簡體)'
|
||||
,'zh_tw'=>'中文(繁體)'
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
114
samples/Apex/TwilioAPI.cls
Normal file
114
samples/Apex/TwilioAPI.cls
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright (c) 2012 Twilio, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
/**
|
||||
* Entry point for accessing Twilio resources that are pre-configured
|
||||
* with credentials from the Twilio Config custom setting (TwilioConfig__c).
|
||||
*
|
||||
* To set up your Twilio credentials:
|
||||
* 1. Get a Twilio account at http://www.twilio.com/try-twilio
|
||||
* 2. Find your Twilio Account Sid and Auth Token at https://www.twilio.com/user/account
|
||||
* 3. Log into Salesforce and go to: Setup | Develop | Custom Settings | Manage Twilio Config
|
||||
* 4. Create a new Twilo Config instance
|
||||
* 5. Copy and paste your Account Sid and Auth Token and click Save
|
||||
*
|
||||
* NOTE: The Application Sid field is for use with the Twilio Client softphone
|
||||
* SDK for Javascript. It is not required for the rest of the Twilio API.
|
||||
*
|
||||
* Now you can get easy access to Twilio from your Apex code by calling:
|
||||
*
|
||||
* TwilioRestClient restClient = TwilioAPI.getDefaultClient();
|
||||
* restClient.getAccount().getCalls();
|
||||
* // etc.
|
||||
*/
|
||||
global class TwilioAPI {
|
||||
|
||||
private class MissingTwilioConfigCustomSettingsException extends Exception {}
|
||||
|
||||
private static TwilioRestClient client;
|
||||
|
||||
private TwilioAPI() {}
|
||||
|
||||
/**
|
||||
* Get a TwilioRestClient pre-populated with your TwilioConfig credentials
|
||||
*/
|
||||
public static TwilioRestClient getDefaultClient() {
|
||||
if (client==null) {
|
||||
TwilioConfig__c twilioCfg = getTwilioConfig();
|
||||
TwilioAPI.client = new TwilioRestClient(twilioCfg.AccountSid__c, twilioCfg.AuthToken__c);
|
||||
}
|
||||
return TwilioAPI.client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get your primary account using your TwilioConfig credentials
|
||||
*/
|
||||
public static TwilioAccount getDefaultAccount() {
|
||||
return getDefaultClient().getAccount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new Twilio Client capability token generator pre-populated
|
||||
* with your TwilioConfig credentials
|
||||
*/
|
||||
public static TwilioCapability createCapability() {
|
||||
TwilioConfig__c twilioCfg = getTwilioConfig();
|
||||
return new TwilioCapability(twilioCfg.AccountSid__c, twilioCfg.AuthToken__c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new TwilioRestClient authorized with the credentials provided
|
||||
*/
|
||||
public static TwilioRestClient createClient(String accountSid, String authToken) {
|
||||
return new TwilioRestClient(accountSid, authToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the org default TwilioConfig record
|
||||
*/
|
||||
public static TwilioConfig__c getTwilioConfig() {
|
||||
TwilioConfig__c twilioCfg;
|
||||
if (Test.isRunningTest()) {
|
||||
twilioCfg = new TwilioConfig__c();
|
||||
twilioCfg.AccountSid__c = 'ACba8bc05eacf94afdae398e642c9cc32d'; // dummy sid
|
||||
twilioCfg.AuthToken__c = '12345678901234567890123456789012'; // dummy token
|
||||
} else {
|
||||
twilioCfg = TwilioConfig__c.getOrgDefaults();
|
||||
if (twilioCfg==null)
|
||||
throw new MissingTwilioConfigCustomSettingsException('Please enter your Twilio account credentials under Twilio Config custom settings (go to Setup | Develop | Custom Settings | Manage Twilio Config)');
|
||||
}
|
||||
return twilioCfg;
|
||||
}
|
||||
|
||||
|
||||
@isTest
|
||||
static void test_TwilioAPI() {
|
||||
System.assertEquals('ACba8bc05eacf94afdae398e642c9cc32d', TwilioAPI.getTwilioConfig().AccountSid__c);
|
||||
System.assertEquals('12345678901234567890123456789012', TwilioAPI.getTwilioConfig().AuthToken__c);
|
||||
System.assertEquals('ACba8bc05eacf94afdae398e642c9cc32d', TwilioAPI.getDefaultClient().getAccountSid());
|
||||
System.assertEquals('ACba8bc05eacf94afdae398e642c9cc32d', TwilioAPI.getDefaultClient().getAccount().getSid());
|
||||
System.assertEquals('ACba8bc05eacf94afdae398e642c9cc32d', TwilioAPI.getDefaultAccount().getSid());
|
||||
}
|
||||
|
||||
}
|
||||
87
samples/AppleScript/Convert To PDF.applescript
Normal file
87
samples/AppleScript/Convert To PDF.applescript
Normal file
@@ -0,0 +1,87 @@
|
||||
(*
|
||||
Copyright 2003 Apple Computer, Inc.
|
||||
|
||||
You may incorporate this Apple sample code into your program(s) without
|
||||
restriction. This Apple sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is yours. You are not permitted to
|
||||
redistribute this Apple sample code as "Apple sample code" after having
|
||||
made changes. If you're going to redistribute the code, we require
|
||||
that you make it clear that the code was descended from Apple sample
|
||||
code, but that you've made changes.
|
||||
*)
|
||||
|
||||
property type_list : {"JPEG", "GIFf", "PICT", "TIFF", "PDF", "TEXT"}
|
||||
property extension_list : {"jpg", "gif", "pct", "tif", "pdf", "rtf"}
|
||||
--html is not currently handled
|
||||
|
||||
on run {}
|
||||
tell application "Finder" to set FinderSelection to the selection as alias list
|
||||
|
||||
set FS to FinderSelection
|
||||
--Ideally, this list could be passed to the open handler
|
||||
|
||||
set SelectionCount to number of FS -- count
|
||||
if SelectionCount is 0 then
|
||||
set FS to userPicksFolder()
|
||||
else if the SelectionCount is 1 then
|
||||
set MyPath to path to me
|
||||
if MyPath is item 1 of FS then
|
||||
--If I'm a droplet then I was double-clicked
|
||||
set FS to userPicksFolder()
|
||||
end if
|
||||
else
|
||||
--I'm not a double-clicked droplet
|
||||
end if
|
||||
open FS
|
||||
end run
|
||||
|
||||
on userPicksFolder()
|
||||
set these_items to {}
|
||||
set these_items to (choose file with prompt "Select a file to convert to PDF:" of type {"JPEG", "GIFf", "PICT", "TIFF", "TEXT", "RTF"}) as list
|
||||
end userPicksFolder
|
||||
|
||||
on open these_items
|
||||
set thesefiles to {}
|
||||
set the item_info to {}
|
||||
repeat with i from 1 to the count of these_items
|
||||
set this_item to (item i of these_items)
|
||||
set the item_info to info for this_item
|
||||
|
||||
if folder of the item_info is true then --if the item is a folder
|
||||
processFolder(this_item)
|
||||
else if ((folder of the item_info is false) and (alias of the item_info is false)) and (the file type of the item_info is in the type_list) or ((the name extension of the item_info) is in the extension_list) then
|
||||
|
||||
set theFilePath to (item i of these_items as string)
|
||||
set thePOSIXFilePath to POSIX path of theFilePath as string
|
||||
processFile(thePOSIXFilePath)
|
||||
end if
|
||||
end repeat
|
||||
end open
|
||||
|
||||
--process folders
|
||||
on processFolder(theFolder)
|
||||
set these_items to list folder theFolder without invisibles
|
||||
repeat with i from 1 to the count of these_items
|
||||
set this_item to alias ((theFolder as text) & (item i of these_items))
|
||||
set the item_info to info for this_item
|
||||
if folder of the item_info is true then
|
||||
processFolder(this_item)
|
||||
else if (alias of the item_info is false) and ((the file type of the item_info is in the type_list) or the name extension of the item_info is in the extension_list) then
|
||||
set theFilePath to (this_item as string)
|
||||
set thePOSIXFilePath to POSIX path of theFilePath as string
|
||||
processFile(thePOSIXFilePath)
|
||||
end if
|
||||
end repeat
|
||||
end processFolder
|
||||
|
||||
on processFile(thePOSIXFileName)
|
||||
try
|
||||
set terminalCommand to ""
|
||||
set convertCommand to "/System/Library/Printers/Libraries/./convert "
|
||||
set newFileName to thePOSIXFileName & ".pdf"
|
||||
set terminalCommand to convertCommand & "-f " & "\"" & thePOSIXFileName & "\"" & " -o " & "\"" & newFileName & "\"" & " -j \"application/pdf\""
|
||||
|
||||
do shell script terminalCommand
|
||||
end try
|
||||
end processFile
|
||||
|
||||
91
samples/AppleScript/Convert To PostScript.applescript
Normal file
91
samples/AppleScript/Convert To PostScript.applescript
Normal file
@@ -0,0 +1,91 @@
|
||||
(*
|
||||
|
||||
Copyright 2003 Apple Computer, Inc.
|
||||
|
||||
You may incorporate this Apple sample code into your program(s) without
|
||||
restriction. This Apple sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is yours. You are not permitted to
|
||||
redistribute this Apple sample code as "Apple sample code" after having
|
||||
made changes. If you're going to redistribute the code, we require
|
||||
that you make it clear that the code was descended from Apple sample
|
||||
code, but that you've made changes.
|
||||
*)
|
||||
|
||||
property type_list : {"JPEG", "GIFf", "PICT", "TIFF", "PDF", "TEXT"}
|
||||
property extension_list : {"jpg", "gif", "pct", "tif", "pdf", "rtf"}
|
||||
--html is not currently handled
|
||||
|
||||
on run {}
|
||||
tell application "Finder" to set FinderSelection to the selection as alias list
|
||||
|
||||
set FS to FinderSelection
|
||||
--Ideally, this list could be passed to the open handler
|
||||
|
||||
set SelectionCount to number of FS -- count
|
||||
if SelectionCount is 0 then
|
||||
set FS to userPicksFolder()
|
||||
else if the SelectionCount is 1 then
|
||||
set MyPath to path to me
|
||||
if MyPath is item 1 of FS then
|
||||
--If I'm a droplet then I was double-clicked
|
||||
set FS to userPicksFolder()
|
||||
end if
|
||||
else
|
||||
--I'm not a double-clicked droplet
|
||||
end if
|
||||
open FS
|
||||
end run
|
||||
|
||||
on userPicksFolder()
|
||||
set these_items to {}
|
||||
set these_items to (choose file with prompt "Select a file to convert to PostScript:" of type {"JPEG", "GIFf", "PICT", "TIFF", "TEXT", "RTF"}) as list
|
||||
end userPicksFolder
|
||||
|
||||
|
||||
on open these_items
|
||||
set thesefiles to {}
|
||||
set the item_info to {}
|
||||
repeat with i from 1 to the count of these_items
|
||||
set this_item to (item i of these_items)
|
||||
set the item_info to info for this_item
|
||||
|
||||
if folder of the item_info is true then --if the item is a folder
|
||||
processFolder(this_item)
|
||||
else if ((folder of the item_info is false) and (alias of the item_info is false)) and (the file type of the item_info is in the type_list) or ((the name extension of the item_info) is in the extension_list) then
|
||||
|
||||
set theFilePath to (item i of these_items as string)
|
||||
set thePOSIXFilePath to POSIX path of theFilePath as string
|
||||
processFile(thePOSIXFilePath)
|
||||
end if
|
||||
end repeat
|
||||
end open
|
||||
|
||||
--process folders
|
||||
on processFolder(theFolder)
|
||||
set these_items to list folder theFolder without invisibles
|
||||
repeat with i from 1 to the count of these_items
|
||||
set this_item to alias ((theFolder as text) & (item i of these_items))
|
||||
set the item_info to info for this_item
|
||||
if folder of the item_info is true then
|
||||
processFolder(this_item)
|
||||
else if (alias of the item_info is false) and ((the file type of the item_info is in the type_list) or the name extension of the item_info is in the extension_list) then
|
||||
set theFilePath to (this_item as string)
|
||||
set thePOSIXFilePath to POSIX path of theFilePath as string
|
||||
processFile(thePOSIXFilePath)
|
||||
end if
|
||||
end repeat
|
||||
end processFolder
|
||||
|
||||
--need to pass the URL to Terminal
|
||||
on processFile(thePOSIXFileName)
|
||||
try
|
||||
set terminalCommand to ""
|
||||
set convertCommand to "/System/Library/Printers/Libraries/./convert "
|
||||
set newFileName to thePOSIXFileName & ".ps"
|
||||
set terminalCommand to convertCommand & "-f " & "\"" & thePOSIXFileName & "\"" & " -o " & "\"" & newFileName & "\"" & " -j \"application/postscript\""
|
||||
|
||||
do shell script terminalCommand
|
||||
end try
|
||||
end processFile
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
(*
|
||||
Count Messages in All Mailboxes
|
||||
|
||||
Copyright 2002-2012 Apple Inc. All rights reserved.
|
||||
|
||||
You may incorporate this Apple sample code into your program(s) without
|
||||
restriction. This Apple sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is yours. You are not permitted to
|
||||
redistribute this Apple sample code as "Apple sample code" after having
|
||||
made changes. If you're going to redistribute the code, we require
|
||||
that you make it clear that the code was descended from Apple sample
|
||||
code, but that you've made changes.
|
||||
*)
|
||||
|
||||
(*
|
||||
This script goes through each mailbox, gets the total message count and
|
||||
the unread count, then displays the final output in a new email message.
|
||||
*)
|
||||
|
||||
tell application "Mail"
|
||||
set localMailboxes to every mailbox
|
||||
if (count of localMailboxes) is greater than 0 then
|
||||
set messageCountDisplay to "Local mailboxes (On My Mac)" & return & my getMessageCountsForMailboxes(localMailboxes)
|
||||
else
|
||||
set messageCountDisplay to ""
|
||||
end if
|
||||
|
||||
set everyAccount to every account
|
||||
repeat with eachAccount in everyAccount
|
||||
set accountMailboxes to every mailbox of eachAccount
|
||||
if (count of accountMailboxes) is greater than 0 then
|
||||
set messageCountDisplay to messageCountDisplay & return & "Mailboxes for Account: " & name of eachAccount & return & my getMessageCountsForMailboxes(accountMailboxes)
|
||||
end if
|
||||
end repeat
|
||||
|
||||
set outputMessage to make new outgoing message with properties {content:messageCountDisplay, subject:"Message counts for all my mailboxes", visible:true}
|
||||
tell outputMessage
|
||||
set font to "Courier"
|
||||
set size to 12
|
||||
end tell
|
||||
end tell
|
||||
|
||||
on getMessageCountsForMailboxes(theMailboxes)
|
||||
-- (list of mailboxes)
|
||||
-- returns string
|
||||
|
||||
set displayString to ""
|
||||
|
||||
tell application "Mail"
|
||||
repeat with eachMailbox in theMailboxes
|
||||
set mailboxName to name of eachMailbox
|
||||
set messageCount to (count of (messages of eachMailbox)) as string
|
||||
set unreadCount to unread count of eachMailbox as string
|
||||
|
||||
set displayString to displayString & " " & my padString(mailboxName, 40) & " " & messageCount & " (" & unreadCount & " unread)" & return
|
||||
end repeat
|
||||
end tell
|
||||
|
||||
return displayString
|
||||
end getMessageCountsForMailboxes
|
||||
|
||||
on padString(theString, fieldLength)
|
||||
-- (string, integer)
|
||||
-- returns string
|
||||
|
||||
set stringLength to length of theString
|
||||
|
||||
if stringLength is greater than fieldLength then
|
||||
set paddedString to (text from character 1 to character (fieldLength - 3) of theString) & "..."
|
||||
else -- stringLength is less than or equal to fieldLength
|
||||
set paddedString to theString
|
||||
|
||||
set paddingLength to fieldLength - stringLength
|
||||
repeat paddingLength times
|
||||
set paddedString to paddedString & space
|
||||
end repeat
|
||||
end if
|
||||
|
||||
return paddedString
|
||||
end padString
|
||||
68
samples/AppleScript/Crazy Message Text.applescript
Normal file
68
samples/AppleScript/Crazy Message Text.applescript
Normal file
@@ -0,0 +1,68 @@
|
||||
(*
|
||||
Crazy Message Text
|
||||
|
||||
Copyright 2002-2012 Apple Inc. All rights reserved.
|
||||
|
||||
You may incorporate this Apple sample code into your program(s) without
|
||||
restriction. This Apple sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is yours. You are not permitted to
|
||||
redistribute this Apple sample code as "Apple sample code" after having
|
||||
made changes. If you're going to redistribute the code, we require
|
||||
that you make it clear that the code was descended from Apple sample
|
||||
code, but that you've made changes.
|
||||
*)
|
||||
|
||||
(*
|
||||
This script takes a string from the user and then makes a new message
|
||||
where each letter has a different font, size, and color.
|
||||
*)
|
||||
|
||||
property lowFontSize : 36
|
||||
property highFontSize : 72
|
||||
property messageText : "Happy Birthday!"
|
||||
|
||||
repeat
|
||||
set userInput to display dialog "Enter some message text:" & return & return & "Minimum Character Size: " & (lowFontSize as string) & return & "Maximum Character Size: " & (highFontSize as string) default answer messageText buttons {"Cancel", "Set Prefs", "Continue"} default button 3
|
||||
|
||||
if the button returned of userInput is "Set Prefs" then
|
||||
set minimumFontSize to 9
|
||||
|
||||
display dialog "Enter the minimum font size to use:" & return & return & "(Must be at least " & (minimumFontSize as string) & ")" default answer lowFontSize buttons {"OK"}
|
||||
set newFontSize to text returned of the result as integer
|
||||
if newFontSize is greater than or equal to minimumFontSize then
|
||||
set lowFontSize to newFontSize
|
||||
else
|
||||
set lowFontSize to minimumFontSize
|
||||
end if
|
||||
|
||||
display dialog "Enter the maximum font size to use:" & return & return & "(Must be greater than " & (lowFontSize as string) & ")" default answer highFontSize buttons {"OK"}
|
||||
set newFontSize to text returned of the result as integer
|
||||
if newFontSize is greater than lowFontSize then
|
||||
set highFontSize to newFontSize
|
||||
else
|
||||
set highFontSize to lowFontSize
|
||||
end if
|
||||
|
||||
else -- button returned of userInput is "Continue"
|
||||
set theText to text returned of userInput
|
||||
if theText is not "" then
|
||||
set messageText to theText
|
||||
end if
|
||||
exit repeat
|
||||
end if
|
||||
end repeat
|
||||
|
||||
set fontList to {"American Typewriter", "American Typewriter Light", "American Typewriter Bold", "American Typewriter Condensed", "American Typewriter Condensed Light", "American Typewriter Condensed Bold", "Arial", "Arial Italic", "Arial Bold", "Arial Bold Italic", "Arial Black", "Baskerville", "Baskerville Italic", "Baskerville SemiBold", "Baskerville Bold", "Baskerville SemiBold Italic", "Baskerville Bold Italic", "Big Caslon Medium", "Comic Sans MS", "Comic Sans MS Bold", "Copperplate", "Copperplate Light", "Copperplate Bold", "Didot", "Didot Italic", "Didot Bold", "Futura Medium", "Futura Medium Italic", "Futura Condensed Medium", "Futura Condensed ExtraBold", "Geneva", "Gill Sans", "Gill Sans Italic", "Gill Sans Light", "Gill Sans Light Italic", "Gill Sans Bold", "Gill Sans Bold Italic", "Herculanum", "Lucida Grande", "Lucida Grande Bold", "Marker Felt Thin", "Marker Felt Wide", "Optima Regular", "Optima Italic", "Optima Bold", "Optima Bold Italic", "Optima ExtraBlack", "Papyrus", "Verdana", "Verdana Italic", "Verdana Bold", "Verdana Bold Italic", "Zapfino"}
|
||||
|
||||
tell application "Mail"
|
||||
activate
|
||||
set crazyTextMessage to make new outgoing message with properties {content:messageText, visible:true}
|
||||
|
||||
tell crazyTextMessage
|
||||
repeat with eachCharacter in characters
|
||||
set font of eachCharacter to (some item of fontList)
|
||||
set size of eachCharacter to (random number from lowFontSize to highFontSize)
|
||||
set color of eachCharacter to {random number from 0 to 65535, random number from 0 to 65535, random number from 0 to 65535}
|
||||
end repeat
|
||||
end tell
|
||||
end tell
|
||||
41
samples/AppleScript/Get User Name.applescript
Normal file
41
samples/AppleScript/Get User Name.applescript
Normal file
@@ -0,0 +1,41 @@
|
||||
(*
|
||||
Get User Name
|
||||
|
||||
This script uses UI element scripting to get the name for the
|
||||
current user.
|
||||
|
||||
If "Enable access for assistive devices" is not checked,
|
||||
this script will open the Universal Access System Preference and ask
|
||||
the user to check the checkbox.
|
||||
|
||||
Copyright 2007 Apple Inc.
|
||||
|
||||
You may incorporate this Apple sample code into your program(s) without
|
||||
restriction. This Apple sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is yours. You are not permitted to
|
||||
redistribute this Apple sample code as "Apple sample code" after having
|
||||
made changes. If you're going to redistribute the code, we require
|
||||
that you make it clear that the code was descended from Apple sample
|
||||
code, but that you've made changes.
|
||||
*)
|
||||
|
||||
tell application "System Preferences"
|
||||
activate
|
||||
set current pane to pane "com.apple.preferences.users"
|
||||
end tell
|
||||
|
||||
tell application "System Events"
|
||||
if UI elements enabled then
|
||||
tell tab group 1 of window "Accounts" of process "System Preferences"
|
||||
click radio button 1
|
||||
delay 2
|
||||
get value of text field 1
|
||||
end tell
|
||||
else
|
||||
tell application "System Preferences"
|
||||
activate
|
||||
set current pane to pane "com.apple.preference.universalaccess"
|
||||
display dialog "UI element scripting is not enabled. Check \"Enable access for assistive devices\""
|
||||
end tell
|
||||
end if
|
||||
end tell
|
||||
75
samples/AppleScript/Time Of Day.applescript
Normal file
75
samples/AppleScript/Time Of Day.applescript
Normal file
@@ -0,0 +1,75 @@
|
||||
(*
|
||||
Speaks the date and time of day
|
||||
|
||||
Copyright 2008 Apple Inc. All rights reserved.
|
||||
|
||||
You may incorporate this Apple sample code into your program(s) without
|
||||
restriction. This Apple sample code has been provided "AS IS" and the
|
||||
responsibility for its operation is yours. You are not permitted to
|
||||
redistribute this Apple sample code as "Apple sample code" after having
|
||||
made changes. If you're going to redistribute the code, we require
|
||||
that you make it clear that the code was descended from Apple sample
|
||||
code, but that you've made changes.
|
||||
*)
|
||||
|
||||
on isVoiceOverRunning()
|
||||
set isRunning to false
|
||||
tell application "System Events"
|
||||
set isRunning to (name of processes) contains "VoiceOver"
|
||||
end tell
|
||||
return isRunning
|
||||
end isVoiceOverRunning
|
||||
|
||||
on isVoiceOverRunningWithAppleScript()
|
||||
if isVoiceOverRunning() then
|
||||
set isRunningWithAppleScript to true
|
||||
|
||||
-- is AppleScript enabled on VoiceOver --
|
||||
tell application "VoiceOver"
|
||||
try
|
||||
set x to bounds of vo cursor
|
||||
on error
|
||||
set isRunningWithAppleScript to false
|
||||
end try
|
||||
end tell
|
||||
return isRunningWithAppleScript
|
||||
end if
|
||||
return false
|
||||
end isVoiceOverRunningWithAppleScript
|
||||
|
||||
set currentDate to current date
|
||||
set amPM to "AM"
|
||||
set currentHour to (currentDate's hours)
|
||||
set currentMinutes to currentDate's minutes
|
||||
|
||||
if (currentHour > 12 and currentHour < 24) then
|
||||
set amPM to "PM"
|
||||
else
|
||||
set amPM to "AM"
|
||||
end if
|
||||
|
||||
-- make minutes below 10 sound nice
|
||||
if currentMinutes < 10 then
|
||||
set currentMinutes to ("0" & currentMinutes) as text
|
||||
end if
|
||||
|
||||
-- ensure 0:nn gets set to 12:nn AM
|
||||
if currentHour is equal to 0 then
|
||||
set currentHour to 12
|
||||
end if
|
||||
|
||||
-- readjust for 12 hour time
|
||||
if (currentHour > 12) then
|
||||
set currentHour to (currentHour - 12)
|
||||
end if
|
||||
|
||||
set currentTime to ((currentDate's month) as text) & " " & ((currentDate's day) as text) & ", " & (currentHour as text) & ":" & ((currentMinutes) as text) & " " & amPM as text
|
||||
|
||||
if isVoiceOverRunningWithAppleScript() then
|
||||
tell application "VoiceOver"
|
||||
output currentTime
|
||||
end tell
|
||||
else
|
||||
say currentTime
|
||||
delay 2
|
||||
end if
|
||||
50
samples/AppleScript/center.applescript
Normal file
50
samples/AppleScript/center.applescript
Normal file
@@ -0,0 +1,50 @@
|
||||
set windowWidth to 800
|
||||
set windowHeight to 600
|
||||
delay 0.1
|
||||
|
||||
set AppleScript's text item delimiters to "x"
|
||||
|
||||
set res to text returned of (display dialog "Enter the width x height:" default answer ((windowWidth & windowHeight) as text))
|
||||
|
||||
if res is "" then
|
||||
display dialog "You need to enter a correct response"
|
||||
return
|
||||
end if
|
||||
set {windowWidth, windowHeight} to text items of res
|
||||
|
||||
set AppleScript's text item delimiters to ""
|
||||
|
||||
tell application "Safari"
|
||||
set screen_width to (do JavaScript "screen.availWidth" in document 1)
|
||||
set screen_height to (do JavaScript "screen.availHeight" in document 1)
|
||||
end tell
|
||||
|
||||
tell application "System Events"
|
||||
set myFrontMost to name of first item of (processes whose frontmost is true)
|
||||
end tell
|
||||
|
||||
tell application "Finder"
|
||||
set {desktopTop, desktopLeft, desktopRight, desktopBottom} to bounds of desktop
|
||||
end tell
|
||||
|
||||
try
|
||||
tell application "System Events"
|
||||
tell process myFrontMost
|
||||
set {{w, h}} to size of drawer of window 1
|
||||
end tell
|
||||
end tell
|
||||
on error
|
||||
set {w, h} to {0, 0}
|
||||
end try
|
||||
|
||||
tell application "System Events"
|
||||
tell process myFrontMost
|
||||
try
|
||||
set {{w, h}} to size of drawer of window 1
|
||||
on error
|
||||
set {w, h} to {0, 0}
|
||||
end try
|
||||
set position of window 1 to {((screen_width - windowWidth) / 2), ((screen_height - windowHeight) / 2.0) - desktopTop}
|
||||
set size of window 1 to {windowWidth -w, windowHeight}
|
||||
end tell
|
||||
end tell
|
||||
7
samples/Arduino/hello.ino
Normal file
7
samples/Arduino/hello.ino
Normal file
@@ -0,0 +1,7 @@
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print("Hello");
|
||||
}
|
||||
1
samples/AutoHotkey/hello.ahk
Normal file
1
samples/AutoHotkey/hello.ahk
Normal file
@@ -0,0 +1 @@
|
||||
MsgBox, Hello`, World!
|
||||
121
samples/Awk/test.awk
Normal file
121
samples/Awk/test.awk
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/bin/awk -f
|
||||
|
||||
BEGIN {
|
||||
# It is not possible to define output file names here because
|
||||
# FILENAME is not define in the BEGIN section
|
||||
n = "";
|
||||
printf "Generating data files ...";
|
||||
network_max_bandwidth_in_byte = 10000000;
|
||||
network_max_packet_per_second = 1000000;
|
||||
last3 = 0;
|
||||
last4 = 0;
|
||||
last5 = 0;
|
||||
last6 = 0;
|
||||
}
|
||||
{
|
||||
if ($1 ~ /Average/)
|
||||
{ # Skip the Average values
|
||||
n = "";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($2 ~ /all/)
|
||||
{ # This is the cpu info
|
||||
print $3 > FILENAME".cpu.user.dat";
|
||||
# print $4 > FILENAME".cpu.nice.dat";
|
||||
print $5 > FILENAME".cpu.system.dat";
|
||||
# print $6 > FILENAME".cpu.iowait.dat";
|
||||
print $7 > FILENAME".cpu.idle.dat";
|
||||
print 100-$7 > FILENAME".cpu.busy.dat";
|
||||
}
|
||||
if ($2 ~ /eth0/)
|
||||
{ # This is the eth0 network info
|
||||
if ($3 > network_max_packet_per_second)
|
||||
print last3 > FILENAME".net.rxpck.dat"; # Total number of packets received per second.
|
||||
else
|
||||
{
|
||||
last3 = $3;
|
||||
print $3 > FILENAME".net.rxpck.dat"; # Total number of packets received per second.
|
||||
}
|
||||
if ($4 > network_max_packet_per_second)
|
||||
print last4 > FILENAME".net.txpck.dat"; # Total number of packets transmitted per second.
|
||||
else
|
||||
{
|
||||
last4 = $4;
|
||||
print $4 > FILENAME".net.txpck.dat"; # Total number of packets transmitted per second.
|
||||
}
|
||||
if ($5 > network_max_bandwidth_in_byte)
|
||||
print last5 > FILENAME".net.rxbyt.dat"; # Total number of bytes received per second.
|
||||
else
|
||||
{
|
||||
last5 = $5;
|
||||
print $5 > FILENAME".net.rxbyt.dat"; # Total number of bytes received per second.
|
||||
}
|
||||
if ($6 > network_max_bandwidth_in_byte)
|
||||
print last6 > FILENAME".net.txbyt.dat"; # Total number of bytes transmitted per second.
|
||||
else
|
||||
{
|
||||
last6 = $6;
|
||||
print $6 > FILENAME".net.txbyt.dat"; # Total number of bytes transmitted per second.
|
||||
}
|
||||
# print $7 > FILENAME".net.rxcmp.dat"; # Number of compressed packets received per second (for cslip etc.).
|
||||
# print $8 > FILENAME".net.txcmp.dat"; # Number of compressed packets transmitted per second.
|
||||
# print $9 > FILENAME".net.rxmcst.dat"; # Number of multicast packets received per second.
|
||||
}
|
||||
|
||||
# Detect which is the next info to be parsed
|
||||
if ($2 ~ /proc|cswch|tps|kbmemfree|totsck/)
|
||||
{
|
||||
n = $2;
|
||||
}
|
||||
|
||||
# Only get lines with numbers (real data !)
|
||||
if ($2 ~ /[0-9]/)
|
||||
{
|
||||
if (n == "proc/s")
|
||||
{ # This is the proc/s info
|
||||
print $2 > FILENAME".proc.dat";
|
||||
# n = "";
|
||||
}
|
||||
if (n == "cswch/s")
|
||||
{ # This is the context switches per second info
|
||||
print $2 > FILENAME".ctxsw.dat";
|
||||
# n = "";
|
||||
}
|
||||
if (n == "tps")
|
||||
{ # This is the disk info
|
||||
print $2 > FILENAME".disk.tps.dat"; # total transfers per second
|
||||
print $3 > FILENAME".disk.rtps.dat"; # read requests per second
|
||||
print $4 > FILENAME".disk.wtps.dat"; # write requests per second
|
||||
print $5 > FILENAME".disk.brdps.dat"; # block reads per second
|
||||
print $6 > FILENAME".disk.bwrps.dat"; # block writes per second
|
||||
# n = "";
|
||||
}
|
||||
if (n == "kbmemfree")
|
||||
{ # This is the mem info
|
||||
print $2 > FILENAME".mem.kbmemfree.dat"; # Amount of free memory available in kilobytes.
|
||||
print $3 > FILENAME".mem.kbmemused.dat"; # Amount of used memory in kilobytes. This does not take into account memory used by the kernel itself.
|
||||
print $4 > FILENAME".mem.memused.dat"; # Percentage of used memory.
|
||||
# It appears the kbmemshrd has been removed from the sysstat output - ntolia
|
||||
# print $X > FILENAME".mem.kbmemshrd.dat"; # Amount of memory shared by the system in kilobytes. Always zero with 2.4 kernels.
|
||||
# print $5 > FILENAME".mem.kbbuffers.dat"; # Amount of memory used as buffers by the kernel in kilobytes.
|
||||
print $6 > FILENAME".mem.kbcached.dat"; # Amount of memory used to cache data by the kernel in kilobytes.
|
||||
# print $7 > FILENAME".mem.kbswpfree.dat"; # Amount of free swap space in kilobytes.
|
||||
# print $8 > FILENAME".mem.kbswpused.dat"; # Amount of used swap space in kilobytes.
|
||||
print $9 > FILENAME".mem.swpused.dat"; # Percentage of used swap space.
|
||||
# n = "";
|
||||
}
|
||||
if (n == "totsck")
|
||||
{ # This is the socket info
|
||||
print $2 > FILENAME".sock.totsck.dat"; # Total number of used sockets.
|
||||
print $3 > FILENAME".sock.tcpsck.dat"; # Number of TCP sockets currently in use.
|
||||
# print $4 > FILENAME".sock.udpsck.dat"; # Number of UDP sockets currently in use.
|
||||
# print $5 > FILENAME".sock.rawsck.dat"; # Number of RAW sockets currently in use.
|
||||
# print $6 > FILENAME".sock.ip-frag.dat"; # Number of IP fragments currently in use.
|
||||
# n = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
END {
|
||||
print " '" FILENAME "' done.";
|
||||
}
|
||||
BIN
samples/Binary/cube.stl
Normal file
BIN
samples/Binary/cube.stl
Normal file
Binary file not shown.
BIN
samples/Binary/dog.o
Executable file
BIN
samples/Binary/dog.o
Executable file
Binary file not shown.
BIN
samples/Binary/foo bar.jar
Normal file
BIN
samples/Binary/foo bar.jar
Normal file
Binary file not shown.
BIN
samples/Binary/foo.bin
Normal file
BIN
samples/Binary/foo.bin
Normal file
Binary file not shown.
BIN
samples/Binary/foo.pdf
Normal file
BIN
samples/Binary/foo.pdf
Normal file
Binary file not shown.
BIN
samples/Binary/foo.png
Normal file
BIN
samples/Binary/foo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
BIN
samples/Binary/git.deb
Normal file
BIN
samples/Binary/git.deb
Normal file
Binary file not shown.
BIN
samples/Binary/git.exe
Executable file
BIN
samples/Binary/git.exe
Executable file
Binary file not shown.
21
samples/Binary/github.po
Normal file
21
samples/Binary/github.po
Normal file
@@ -0,0 +1,21 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: x\n"
|
||||
"POT-Creation-Date: 2009-02-15 09:22+0100\n"
|
||||
"PO-Revision-Date: 2009-02-15 09:22+0100\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
||||
|
||||
#: tools/files/simple_translation.rb:1
|
||||
msgid "a translation"
|
||||
msgstr ""
|
||||
BIN
samples/Binary/hello.pbc
Normal file
BIN
samples/Binary/hello.pbc
Normal file
Binary file not shown.
BIN
samples/Binary/linguist.gem
Normal file
BIN
samples/Binary/linguist.gem
Normal file
Binary file not shown.
4424
samples/Binary/octocat.ai
Normal file
4424
samples/Binary/octocat.ai
Normal file
File diff suppressed because one or more lines are too long
BIN
samples/Binary/octocat.png
Normal file
BIN
samples/Binary/octocat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
BIN
samples/Binary/octocat.psd
Normal file
BIN
samples/Binary/octocat.psd
Normal file
Binary file not shown.
BIN
samples/Binary/zip
Normal file
BIN
samples/Binary/zip
Normal file
Binary file not shown.
10
samples/C++/bar.h
Normal file
10
samples/C++/bar.h
Normal file
@@ -0,0 +1,10 @@
|
||||
class Bar
|
||||
{
|
||||
protected:
|
||||
|
||||
char *name;
|
||||
|
||||
public:
|
||||
|
||||
void hello();
|
||||
}
|
||||
10
samples/C++/bar.hpp
Normal file
10
samples/C++/bar.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
class Bar
|
||||
{
|
||||
protected:
|
||||
|
||||
char *name;
|
||||
|
||||
public:
|
||||
|
||||
void hello();
|
||||
}
|
||||
39
samples/C++/cuda.cu
Normal file
39
samples/C++/cuda.cu
Normal file
@@ -0,0 +1,39 @@
|
||||
void foo()
|
||||
{
|
||||
cudaArray* cu_array;
|
||||
texture<float, 2, cudaReadModeElementType> tex;
|
||||
|
||||
// Allocate array
|
||||
cudaChannelFormatDesc description = cudaCreateChannelDesc<float>();
|
||||
cudaMallocArray(&cu_array, &description, width, height);
|
||||
|
||||
// Copy image data to array
|
||||
cudaMemcpyToArray(cu_array, image, width*height*sizeof(float), cudaMemcpyHostToDevice);
|
||||
|
||||
// Set texture parameters (default)
|
||||
tex.addressMode[0] = cudaAddressModeClamp;
|
||||
tex.addressMode[1] = cudaAddressModeClamp;
|
||||
tex.filterMode = cudaFilterModePoint;
|
||||
tex.normalized = false; // do not normalize coordinates
|
||||
|
||||
// Bind the array to the texture
|
||||
cudaBindTextureToArray(tex, cu_array);
|
||||
|
||||
// Run kernel
|
||||
dim3 blockDim(16, 16, 1);
|
||||
dim3 gridDim((width + blockDim.x - 1)/ blockDim.x, (height + blockDim.y - 1) / blockDim.y, 1);
|
||||
kernel<<< gridDim, blockDim, 0 >>>(d_data, height, width);
|
||||
|
||||
// Unbind the array from the texture
|
||||
cudaUnbindTexture(tex);
|
||||
} //end foo()
|
||||
|
||||
__global__ void kernel(float* odata, int height, int width)
|
||||
{
|
||||
unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
|
||||
unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
|
||||
if (x < width && y < height) {
|
||||
float c = tex2D(tex, x, y);
|
||||
odata[y*width+x] = c;
|
||||
}
|
||||
}
|
||||
81
samples/C++/env.cpp
Normal file
81
samples/C++/env.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
This file is part of the PhantomJS project from Ofi Labs.
|
||||
|
||||
Copyright (C) 2012 execjosh, http://execjosh.blogspot.com
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "env.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QString>
|
||||
#include <QVariantMap>
|
||||
|
||||
static Env *env_instance = (Env *)NULL;
|
||||
|
||||
Env *Env::instance()
|
||||
{
|
||||
if ((Env *)NULL == env_instance)
|
||||
env_instance = new Env();
|
||||
|
||||
return env_instance;
|
||||
}
|
||||
|
||||
Env::Env()
|
||||
: QObject(QCoreApplication::instance())
|
||||
{
|
||||
}
|
||||
|
||||
// public:
|
||||
|
||||
void Env::parse(const char **envp)
|
||||
{
|
||||
const char **env = (const char **)NULL;
|
||||
QString envvar, name, value;
|
||||
int indexOfEquals;
|
||||
// Loop for each of the <NAME>=<VALUE> pairs and split them into a map
|
||||
for (env = envp; *env != (const char *)NULL; env++) {
|
||||
envvar = QString(*env);
|
||||
indexOfEquals = envvar.indexOf('=');
|
||||
if (0 >= indexOfEquals) {
|
||||
// Should never happen because names cannot contain "=" and cannot
|
||||
// be empty. If it does happen, then just ignore this record.
|
||||
// See: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html
|
||||
continue;
|
||||
}
|
||||
// Extract name and value (if it exists) from envvar
|
||||
// NOTE:
|
||||
// QString::mid() will gracefully return an empty QString when the
|
||||
// specified position index is >= the length() of the string
|
||||
name = envvar.left(indexOfEquals);
|
||||
value = envvar.mid(indexOfEquals + 1);
|
||||
m_map.insert(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap Env::asVariantMap() const
|
||||
{
|
||||
return m_map;
|
||||
}
|
||||
52
samples/C++/env.h
Normal file
52
samples/C++/env.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
This file is part of the PhantomJS project from Ofi Labs.
|
||||
|
||||
Copyright (C) 2012 execjosh, http://execjosh.blogspot.com
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ENV_H
|
||||
#define ENV_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
class Env : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static Env *instance();
|
||||
|
||||
void parse(const char ** envp);
|
||||
QVariantMap asVariantMap() const;
|
||||
|
||||
private:
|
||||
Env();
|
||||
|
||||
QVariantMap m_map;
|
||||
};
|
||||
|
||||
#endif // ENV_H
|
||||
69
samples/C++/gdsdbreader.h
Normal file
69
samples/C++/gdsdbreader.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef GDSDBREADER_H
|
||||
#define GDSDBREADER_H
|
||||
|
||||
// This file contains core structures, classes and types for the entire gds app
|
||||
// WARNING: DO NOT MODIFY UNTIL IT'S STRICTLY NECESSARY
|
||||
|
||||
#include <QDir>
|
||||
#include "diagramwidget/qgldiagramwidget.h"
|
||||
|
||||
#define GDS_DIR "gdsdata"
|
||||
|
||||
enum level {LEVEL_ONE, LEVEL_TWO, LEVEL_THREE};
|
||||
|
||||
// The internal structure of the db to store information about each node (each level)
|
||||
// this will be serialized before being written to file
|
||||
class dbDataStructure
|
||||
{
|
||||
public:
|
||||
QString label;
|
||||
quint32 depth;
|
||||
quint32 userIndex;
|
||||
QByteArray data; // This is COMPRESSED data, optimize ram and disk space, is decompressed
|
||||
// just when needed (to display the comments)
|
||||
|
||||
// The following ID is used to create second-third level files
|
||||
quint64 uniqueID;
|
||||
// All the next items linked to this one
|
||||
QVector<dbDataStructure*> nextItems;
|
||||
// Corresponding indices vector (used to store data)
|
||||
QVector<quint32> nextItemsIndices;
|
||||
// The father element (or NULL if it's root)
|
||||
dbDataStructure* father;
|
||||
// Corresponding indices vector (used to store data)
|
||||
quint32 fatherIndex;
|
||||
bool noFatherRoot; // Used to tell if this node is the root (so hasn't a father)
|
||||
|
||||
// These fields will be useful for levels 2 and 3
|
||||
QString fileName; // Relative filename for the associated code file
|
||||
QByteArray firstLineData; // Compressed first line data, this will be used with the line number to retrieve info
|
||||
QVector<quint32> linesNumbers; // First and next lines (next are relative to the first) numbers
|
||||
|
||||
// -- Generic system data not to be stored on disk
|
||||
void *glPointer; // GL pointer
|
||||
|
||||
// These operator overrides prevent the glPointer and other non-disk-necessary data serialization
|
||||
friend QDataStream& operator<<(QDataStream& stream, const dbDataStructure& myclass)
|
||||
// Notice: this function has to be "friend" because it cannot be a member function, member functions
|
||||
// have an additional parameter "this" which isn't in the argument list of an operator overload. A friend
|
||||
// function has full access to private data of the class without having the "this" argument
|
||||
{
|
||||
// Don't write glPointer and every pointer-dependent structure
|
||||
return stream << myclass.label << myclass.depth << myclass.userIndex << qCompress(myclass.data)
|
||||
<< myclass.uniqueID << myclass.nextItemsIndices << myclass.fatherIndex << myclass.noFatherRoot
|
||||
<< myclass.fileName << qCompress(myclass.firstLineData) << myclass.linesNumbers;
|
||||
}
|
||||
friend QDataStream& operator>>(QDataStream& stream, dbDataStructure& myclass)
|
||||
{
|
||||
//Don't read it, either
|
||||
stream >> myclass.label >> myclass.depth >> myclass.userIndex >> myclass.data
|
||||
>> myclass.uniqueID >> myclass.nextItemsIndices >> myclass.fatherIndex >> myclass.noFatherRoot
|
||||
>> myclass.fileName >> myclass.firstLineData >> myclass.linesNumbers;
|
||||
myclass.data = qUncompress(myclass.data);
|
||||
myclass.firstLineData = qUncompress(myclass.firstLineData);
|
||||
return stream;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // GDSDBREADER_H
|
||||
8
samples/C++/hello.cpp
Normal file
8
samples/C++/hello.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
cout << "Hello World" << endl;
|
||||
}
|
||||
382
samples/C++/key.cpp
Normal file
382
samples/C++/key.cpp
Normal file
@@ -0,0 +1,382 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#include "key.h"
|
||||
|
||||
// Generate a private key from just the secret parameter
|
||||
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
|
||||
{
|
||||
int ok = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
EC_POINT *pub_key = NULL;
|
||||
|
||||
if (!eckey) return 0;
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
pub_key = EC_POINT_new(group);
|
||||
|
||||
if (pub_key == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
|
||||
goto err;
|
||||
|
||||
EC_KEY_set_private_key(eckey,priv_key);
|
||||
EC_KEY_set_public_key(eckey,pub_key);
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
|
||||
if (pub_key)
|
||||
EC_POINT_free(pub_key);
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return(ok);
|
||||
}
|
||||
|
||||
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
|
||||
// recid selects which key is recovered
|
||||
// if check is nonzero, additional checks are performed
|
||||
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
|
||||
{
|
||||
if (!eckey) return 0;
|
||||
|
||||
int ret = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
BIGNUM *x = NULL;
|
||||
BIGNUM *e = NULL;
|
||||
BIGNUM *order = NULL;
|
||||
BIGNUM *sor = NULL;
|
||||
BIGNUM *eor = NULL;
|
||||
BIGNUM *field = NULL;
|
||||
EC_POINT *R = NULL;
|
||||
EC_POINT *O = NULL;
|
||||
EC_POINT *Q = NULL;
|
||||
BIGNUM *rr = NULL;
|
||||
BIGNUM *zero = NULL;
|
||||
int n = 0;
|
||||
int i = recid / 2;
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
|
||||
BN_CTX_start(ctx);
|
||||
order = BN_CTX_get(ctx);
|
||||
if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
|
||||
x = BN_CTX_get(ctx);
|
||||
if (!BN_copy(x, order)) { ret=-1; goto err; }
|
||||
if (!BN_mul_word(x, i)) { ret=-1; goto err; }
|
||||
if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
|
||||
field = BN_CTX_get(ctx);
|
||||
if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
|
||||
if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
|
||||
if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
|
||||
if (check)
|
||||
{
|
||||
if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
|
||||
if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
|
||||
}
|
||||
if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
n = EC_GROUP_get_degree(group);
|
||||
e = BN_CTX_get(ctx);
|
||||
if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
|
||||
if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
|
||||
zero = BN_CTX_get(ctx);
|
||||
if (!BN_zero(zero)) { ret=-1; goto err; }
|
||||
if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
|
||||
rr = BN_CTX_get(ctx);
|
||||
if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
|
||||
sor = BN_CTX_get(ctx);
|
||||
if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
|
||||
eor = BN_CTX_get(ctx);
|
||||
if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
|
||||
if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
|
||||
if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (R != NULL) EC_POINT_free(R);
|
||||
if (O != NULL) EC_POINT_free(O);
|
||||
if (Q != NULL) EC_POINT_free(Q);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CKey::SetCompressedPubKey()
|
||||
{
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fCompressedPubKey = true;
|
||||
}
|
||||
|
||||
void CKey::Reset()
|
||||
{
|
||||
fCompressedPubKey = false;
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||
fSet = false;
|
||||
}
|
||||
|
||||
CKey::CKey()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
CKey::CKey(const CKey& b)
|
||||
{
|
||||
pkey = EC_KEY_dup(b.pkey);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
||||
fSet = b.fSet;
|
||||
}
|
||||
|
||||
CKey& CKey::operator=(const CKey& b)
|
||||
{
|
||||
if (!EC_KEY_copy(pkey, b.pkey))
|
||||
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
|
||||
fSet = b.fSet;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
CKey::~CKey()
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
}
|
||||
|
||||
bool CKey::IsNull() const
|
||||
{
|
||||
return !fSet;
|
||||
}
|
||||
|
||||
bool CKey::IsCompressed() const
|
||||
{
|
||||
return fCompressedPubKey;
|
||||
}
|
||||
|
||||
void CKey::MakeNewKey(bool fCompressed)
|
||||
{
|
||||
if (!EC_KEY_generate_key(pkey))
|
||||
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
||||
if (fCompressed)
|
||||
SetCompressedPubKey();
|
||||
fSet = true;
|
||||
}
|
||||
|
||||
bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
|
||||
if (vchSecret.size() != 32)
|
||||
throw key_error("CKey::SetSecret() : secret must be 32 bytes");
|
||||
BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::SetSecret() : BN_bin2bn failed");
|
||||
if (!EC_KEY_regenerate_key(pkey,bn))
|
||||
{
|
||||
BN_clear_free(bn);
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
|
||||
}
|
||||
BN_clear_free(bn);
|
||||
fSet = true;
|
||||
if (fCompressed || fCompressedPubKey)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
CSecret CKey::GetSecret(bool &fCompressed) const
|
||||
{
|
||||
CSecret vchRet;
|
||||
vchRet.resize(32);
|
||||
const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
|
||||
int nBytes = BN_num_bytes(bn);
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
|
||||
int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
|
||||
if (n != nBytes)
|
||||
throw key_error("CKey::GetSecret(): BN_bn2bin failed");
|
||||
fCompressed = fCompressedPubKey;
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
CPrivKey CKey::GetPrivKey() const
|
||||
{
|
||||
int nSize = i2d_ECPrivateKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
|
||||
CPrivKey vchPrivKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
|
||||
return vchPrivKey;
|
||||
}
|
||||
|
||||
bool CKey::SetPubKey(const CPubKey& vchPubKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPubKey.vchPubKey[0];
|
||||
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
if (vchPubKey.vchPubKey.size() == 33)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
CPubKey CKey::GetPubKey() const
|
||||
{
|
||||
int nSize = i2o_ECPublicKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
|
||||
std::vector<unsigned char> vchPubKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPubKey[0];
|
||||
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
|
||||
return CPubKey(vchPubKey);
|
||||
}
|
||||
|
||||
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
unsigned int nSize = ECDSA_size(pkey);
|
||||
vchSig.resize(nSize); // Make sure it is big enough
|
||||
if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
|
||||
{
|
||||
vchSig.clear();
|
||||
return false;
|
||||
}
|
||||
vchSig.resize(nSize); // Shrink to fit actual size
|
||||
return true;
|
||||
}
|
||||
|
||||
// create a compact signature (65 bytes), which allows reconstructing the used public key
|
||||
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
|
||||
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
|
||||
// 0x1D = second key with even y, 0x1E = second key with odd y
|
||||
bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
bool fOk = false;
|
||||
ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
|
||||
if (sig==NULL)
|
||||
return false;
|
||||
vchSig.clear();
|
||||
vchSig.resize(65,0);
|
||||
int nBitsR = BN_num_bits(sig->r);
|
||||
int nBitsS = BN_num_bits(sig->s);
|
||||
if (nBitsR <= 256 && nBitsS <= 256)
|
||||
{
|
||||
int nRecId = -1;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
CKey keyRec;
|
||||
keyRec.fSet = true;
|
||||
if (fCompressedPubKey)
|
||||
keyRec.SetCompressedPubKey();
|
||||
if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
|
||||
if (keyRec.GetPubKey() == this->GetPubKey())
|
||||
{
|
||||
nRecId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nRecId == -1)
|
||||
throw key_error("CKey::SignCompact() : unable to construct recoverable key");
|
||||
|
||||
vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
|
||||
BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
|
||||
BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
|
||||
fOk = true;
|
||||
}
|
||||
ECDSA_SIG_free(sig);
|
||||
return fOk;
|
||||
}
|
||||
|
||||
// reconstruct public key from a compact signature
|
||||
// This is only slightly more CPU intensive than just verifying it.
|
||||
// If this function succeeds, the recovered public key is guaranteed to be valid
|
||||
// (the signature is a valid signature of the given data for that key)
|
||||
bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
if (vchSig.size() != 65)
|
||||
return false;
|
||||
int nV = vchSig[0];
|
||||
if (nV<27 || nV>=35)
|
||||
return false;
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
BN_bin2bn(&vchSig[1],32,sig->r);
|
||||
BN_bin2bn(&vchSig[33],32,sig->s);
|
||||
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (nV >= 31)
|
||||
{
|
||||
SetCompressedPubKey();
|
||||
nV -= 4;
|
||||
}
|
||||
if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
|
||||
{
|
||||
fSet = true;
|
||||
ECDSA_SIG_free(sig);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
CKey key;
|
||||
if (!key.SetCompactSignature(hash, vchSig))
|
||||
return false;
|
||||
if (GetPubKey() != key.GetPubKey())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::IsValid()
|
||||
{
|
||||
if (!fSet)
|
||||
return false;
|
||||
|
||||
bool fCompr;
|
||||
CSecret secret = GetSecret(fCompr);
|
||||
CKey key2;
|
||||
key2.SetSecret(secret, fCompr);
|
||||
return GetPubKey() == key2.GetPubKey();
|
||||
}
|
||||
162
samples/C++/key.h
Normal file
162
samples/C++/key.h
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_KEY_H
|
||||
#define BITCOIN_KEY_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include "allocators.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <openssl/ec.h> // for EC_KEY definition
|
||||
|
||||
// secp160k1
|
||||
// const unsigned int PRIVATE_KEY_SIZE = 192;
|
||||
// const unsigned int PUBLIC_KEY_SIZE = 41;
|
||||
// const unsigned int SIGNATURE_SIZE = 48;
|
||||
//
|
||||
// secp192k1
|
||||
// const unsigned int PRIVATE_KEY_SIZE = 222;
|
||||
// const unsigned int PUBLIC_KEY_SIZE = 49;
|
||||
// const unsigned int SIGNATURE_SIZE = 57;
|
||||
//
|
||||
// secp224k1
|
||||
// const unsigned int PRIVATE_KEY_SIZE = 250;
|
||||
// const unsigned int PUBLIC_KEY_SIZE = 57;
|
||||
// const unsigned int SIGNATURE_SIZE = 66;
|
||||
//
|
||||
// secp256k1:
|
||||
// const unsigned int PRIVATE_KEY_SIZE = 279;
|
||||
// const unsigned int PUBLIC_KEY_SIZE = 65;
|
||||
// const unsigned int SIGNATURE_SIZE = 72;
|
||||
//
|
||||
// see www.keylength.com
|
||||
// script supports up to 75 for single byte push
|
||||
|
||||
class key_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit key_error(const std::string& str) : std::runtime_error(str) {}
|
||||
};
|
||||
|
||||
/** A reference to a CKey: the Hash160 of its serialized public key */
|
||||
class CKeyID : public uint160
|
||||
{
|
||||
public:
|
||||
CKeyID() : uint160(0) { }
|
||||
CKeyID(const uint160 &in) : uint160(in) { }
|
||||
};
|
||||
|
||||
/** A reference to a CScript: the Hash160 of its serialization (see script.h) */
|
||||
class CScriptID : public uint160
|
||||
{
|
||||
public:
|
||||
CScriptID() : uint160(0) { }
|
||||
CScriptID(const uint160 &in) : uint160(in) { }
|
||||
};
|
||||
|
||||
/** An encapsulated public key. */
|
||||
class CPubKey {
|
||||
private:
|
||||
std::vector<unsigned char> vchPubKey;
|
||||
friend class CKey;
|
||||
|
||||
public:
|
||||
CPubKey() { }
|
||||
CPubKey(const std::vector<unsigned char> &vchPubKeyIn) : vchPubKey(vchPubKeyIn) { }
|
||||
friend bool operator==(const CPubKey &a, const CPubKey &b) { return a.vchPubKey == b.vchPubKey; }
|
||||
friend bool operator!=(const CPubKey &a, const CPubKey &b) { return a.vchPubKey != b.vchPubKey; }
|
||||
friend bool operator<(const CPubKey &a, const CPubKey &b) { return a.vchPubKey < b.vchPubKey; }
|
||||
|
||||
IMPLEMENT_SERIALIZE(
|
||||
READWRITE(vchPubKey);
|
||||
)
|
||||
|
||||
CKeyID GetID() const {
|
||||
return CKeyID(Hash160(vchPubKey));
|
||||
}
|
||||
|
||||
uint256 GetHash() const {
|
||||
return Hash(vchPubKey.begin(), vchPubKey.end());
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return vchPubKey.size() == 33 || vchPubKey.size() == 65;
|
||||
}
|
||||
|
||||
bool IsCompressed() const {
|
||||
return vchPubKey.size() == 33;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> Raw() const {
|
||||
return vchPubKey;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// secure_allocator is defined in serialize.h
|
||||
// CPrivKey is a serialized private key, with all parameters included (279 bytes)
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
|
||||
// CSecret is a serialization of just the secret parameter (32 bytes)
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
|
||||
|
||||
/** An encapsulated OpenSSL Elliptic Curve key (public and/or private) */
|
||||
class CKey
|
||||
{
|
||||
protected:
|
||||
EC_KEY* pkey;
|
||||
bool fSet;
|
||||
bool fCompressedPubKey;
|
||||
|
||||
void SetCompressedPubKey();
|
||||
|
||||
public:
|
||||
|
||||
void Reset();
|
||||
|
||||
CKey();
|
||||
CKey(const CKey& b);
|
||||
|
||||
CKey& operator=(const CKey& b);
|
||||
|
||||
~CKey();
|
||||
|
||||
bool IsNull() const;
|
||||
bool IsCompressed() const;
|
||||
|
||||
void MakeNewKey(bool fCompressed);
|
||||
bool SetPrivKey(const CPrivKey& vchPrivKey);
|
||||
bool SetSecret(const CSecret& vchSecret, bool fCompressed = false);
|
||||
CSecret GetSecret(bool &fCompressed) const;
|
||||
CPrivKey GetPrivKey() const;
|
||||
bool SetPubKey(const CPubKey& vchPubKey);
|
||||
CPubKey GetPubKey() const;
|
||||
|
||||
bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
|
||||
|
||||
// create a compact signature (65 bytes), which allows reconstructing the used public key
|
||||
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
|
||||
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
|
||||
// 0x1D = second key with even y, 0x1E = second key with odd y
|
||||
bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig);
|
||||
|
||||
// reconstruct public key from a compact signature
|
||||
// This is only slightly more CPU intensive than just verifying it.
|
||||
// If this function succeeds, the recovered public key is guaranteed to be valid
|
||||
// (the signature is a valid signature of the given data for that key)
|
||||
bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
// Verify a compact signature
|
||||
bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
bool IsValid();
|
||||
};
|
||||
|
||||
#endif
|
||||
74
samples/C++/main.cpp
Normal file
74
samples/C++/main.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
This file is part of the PhantomJS project from Ofi Labs.
|
||||
|
||||
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "consts.h"
|
||||
#include "utils.h"
|
||||
#include "env.h"
|
||||
#include "phantom.h"
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
#endif
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#if QT_VERSION != QT_VERSION_CHECK(4, 8, 0)
|
||||
#error Something is wrong with the setup. Please report to the mailing list!
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv, const char** envp)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
google_breakpad::ExceptionHandler eh("/tmp", NULL, Utils::exceptionHandler, NULL, true);
|
||||
#endif
|
||||
|
||||
// Registering an alternative Message Handler
|
||||
qInstallMsgHandler(Utils::messageHandler);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
#ifdef STATIC_BUILD
|
||||
Q_INIT_RESOURCE(WebKit);
|
||||
Q_INIT_RESOURCE(InspectorBackendStub);
|
||||
#endif
|
||||
|
||||
app.setWindowIcon(QIcon(":/phantomjs-icon.png"));
|
||||
app.setApplicationName("PhantomJS");
|
||||
app.setOrganizationName("Ofi Labs");
|
||||
app.setOrganizationDomain("www.ofilabs.com");
|
||||
app.setApplicationVersion(PHANTOMJS_VERSION_STRING);
|
||||
|
||||
Env::instance()->parse(envp);
|
||||
|
||||
Phantom phantom;
|
||||
if (phantom.execute()) {
|
||||
app.exec();
|
||||
}
|
||||
return phantom.returnValue();
|
||||
}
|
||||
415
samples/C++/qscicommand.h
Normal file
415
samples/C++/qscicommand.h
Normal file
@@ -0,0 +1,415 @@
|
||||
// This defines the interface to the QsciCommand class.
|
||||
//
|
||||
// Copyright (c) 2011 Riverbank Computing Limited <info@riverbankcomputing.com>
|
||||
//
|
||||
// This file is part of QScintilla.
|
||||
//
|
||||
// This file may be used under the terms of the GNU General Public
|
||||
// License versions 2.0 or 3.0 as published by the Free Software
|
||||
// Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
|
||||
// included in the packaging of this file. Alternatively you may (at
|
||||
// your option) use any later version of the GNU General Public
|
||||
// License if such license has been publicly approved by Riverbank
|
||||
// Computing Limited (or its successors, if any) and the KDE Free Qt
|
||||
// Foundation. In addition, as a special exception, Riverbank gives you
|
||||
// certain additional rights. These rights are described in the Riverbank
|
||||
// GPL Exception version 1.1, which can be found in the file
|
||||
// GPL_EXCEPTION.txt in this package.
|
||||
//
|
||||
// If you are unsure which license is appropriate for your use, please
|
||||
// contact the sales department at sales@riverbankcomputing.com.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
#ifndef QSCICOMMAND_H
|
||||
#define QSCICOMMAND_H
|
||||
|
||||
#ifdef __APPLE__
|
||||
extern "C++" {
|
||||
#endif
|
||||
|
||||
#include <qstring.h>
|
||||
|
||||
#include <Qsci/qsciglobal.h>
|
||||
#include <Qsci/qsciscintillabase.h>
|
||||
|
||||
|
||||
class QsciScintilla;
|
||||
|
||||
|
||||
//! \brief The QsciCommand class represents an internal editor command that may
|
||||
//! have one or two keys bound to it.
|
||||
//!
|
||||
//! Methods are provided to change the keys bound to the command and to remove
|
||||
//! a key binding. Each command has a user friendly description of the command
|
||||
//! for use in key mapping dialogs.
|
||||
class QSCINTILLA_EXPORT QsciCommand
|
||||
{
|
||||
public:
|
||||
//! This enum defines the different commands that can be assigned to a key.
|
||||
enum Command {
|
||||
//! Move down one line.
|
||||
LineDown = QsciScintillaBase::SCI_LINEDOWN,
|
||||
|
||||
//! Extend the selection down one line.
|
||||
LineDownExtend = QsciScintillaBase::SCI_LINEDOWNEXTEND,
|
||||
|
||||
//! Extend the rectangular selection down one line.
|
||||
LineDownRectExtend = QsciScintillaBase::SCI_LINEDOWNRECTEXTEND,
|
||||
|
||||
//! Scroll the view down one line.
|
||||
LineScrollDown = QsciScintillaBase::SCI_LINESCROLLDOWN,
|
||||
|
||||
//! Move up one line.
|
||||
LineUp = QsciScintillaBase::SCI_LINEUP,
|
||||
|
||||
//! Extend the selection up one line.
|
||||
LineUpExtend = QsciScintillaBase::SCI_LINEUPEXTEND,
|
||||
|
||||
//! Extend the rectangular selection up one line.
|
||||
LineUpRectExtend = QsciScintillaBase::SCI_LINEUPRECTEXTEND,
|
||||
|
||||
//! Scroll the view up one line.
|
||||
LineScrollUp = QsciScintillaBase::SCI_LINESCROLLUP,
|
||||
|
||||
//! Scroll to the start of the document.
|
||||
ScrollToStart = QsciScintillaBase::SCI_SCROLLTOSTART,
|
||||
|
||||
//! Scroll to the end of the document.
|
||||
ScrollToEnd = QsciScintillaBase::SCI_SCROLLTOEND,
|
||||
|
||||
//! Scroll vertically to centre the current line.
|
||||
VerticalCentreCaret = QsciScintillaBase::SCI_VERTICALCENTRECARET,
|
||||
|
||||
//! Move down one paragraph.
|
||||
ParaDown = QsciScintillaBase::SCI_PARADOWN,
|
||||
|
||||
//! Extend the selection down one paragraph.
|
||||
ParaDownExtend = QsciScintillaBase::SCI_PARADOWNEXTEND,
|
||||
|
||||
//! Move up one paragraph.
|
||||
ParaUp = QsciScintillaBase::SCI_PARAUP,
|
||||
|
||||
//! Extend the selection up one paragraph.
|
||||
ParaUpExtend = QsciScintillaBase::SCI_PARAUPEXTEND,
|
||||
|
||||
//! Move left one character.
|
||||
CharLeft = QsciScintillaBase::SCI_CHARLEFT,
|
||||
|
||||
//! Extend the selection left one character.
|
||||
CharLeftExtend = QsciScintillaBase::SCI_CHARLEFTEXTEND,
|
||||
|
||||
//! Extend the rectangular selection left one character.
|
||||
CharLeftRectExtend = QsciScintillaBase::SCI_CHARLEFTRECTEXTEND,
|
||||
|
||||
//! Move right one character.
|
||||
CharRight = QsciScintillaBase::SCI_CHARRIGHT,
|
||||
|
||||
//! Extend the selection right one character.
|
||||
CharRightExtend = QsciScintillaBase::SCI_CHARRIGHTEXTEND,
|
||||
|
||||
//! Extend the rectangular selection right one character.
|
||||
CharRightRectExtend = QsciScintillaBase::SCI_CHARRIGHTRECTEXTEND,
|
||||
|
||||
//! Move left one word.
|
||||
WordLeft = QsciScintillaBase::SCI_WORDLEFT,
|
||||
|
||||
//! Extend the selection left one word.
|
||||
WordLeftExtend = QsciScintillaBase::SCI_WORDLEFTEXTEND,
|
||||
|
||||
//! Move right one word.
|
||||
WordRight = QsciScintillaBase::SCI_WORDRIGHT,
|
||||
|
||||
//! Extend the selection right one word.
|
||||
WordRightExtend = QsciScintillaBase::SCI_WORDRIGHTEXTEND,
|
||||
|
||||
//! Move to the end of the previous word.
|
||||
WordLeftEnd = QsciScintillaBase::SCI_WORDLEFTEND,
|
||||
|
||||
//! Extend the selection to the end of the previous word.
|
||||
WordLeftEndExtend = QsciScintillaBase::SCI_WORDLEFTENDEXTEND,
|
||||
|
||||
//! Move to the end of the next word.
|
||||
WordRightEnd = QsciScintillaBase::SCI_WORDRIGHTEND,
|
||||
|
||||
//! Extend the selection to the end of the next word.
|
||||
WordRightEndExtend = QsciScintillaBase::SCI_WORDRIGHTENDEXTEND,
|
||||
|
||||
//! Move left one word part.
|
||||
WordPartLeft = QsciScintillaBase::SCI_WORDPARTLEFT,
|
||||
|
||||
//! Extend the selection left one word part.
|
||||
WordPartLeftExtend = QsciScintillaBase::SCI_WORDPARTLEFTEXTEND,
|
||||
|
||||
//! Move right one word part.
|
||||
WordPartRight = QsciScintillaBase::SCI_WORDPARTRIGHT,
|
||||
|
||||
//! Extend the selection right one word part.
|
||||
WordPartRightExtend = QsciScintillaBase::SCI_WORDPARTRIGHTEXTEND,
|
||||
|
||||
//! Move to the start of the document line.
|
||||
Home = QsciScintillaBase::SCI_HOME,
|
||||
|
||||
//! Extend the selection to the start of the document line.
|
||||
HomeExtend = QsciScintillaBase::SCI_HOMEEXTEND,
|
||||
|
||||
//! Extend the rectangular selection to the start of the document line.
|
||||
HomeRectExtend = QsciScintillaBase::SCI_HOMERECTEXTEND,
|
||||
|
||||
//! Move to the start of the displayed line.
|
||||
HomeDisplay = QsciScintillaBase::SCI_HOMEDISPLAY,
|
||||
|
||||
//! Extend the selection to the start of the displayed line.
|
||||
HomeDisplayExtend = QsciScintillaBase::SCI_HOMEDISPLAYEXTEND,
|
||||
|
||||
//! Move to the start of the displayed or document line.
|
||||
HomeWrap = QsciScintillaBase::SCI_HOMEWRAP,
|
||||
|
||||
//! Extend the selection to the start of the displayed or document
|
||||
//! line.
|
||||
HomeWrapExtend = QsciScintillaBase::SCI_HOMEWRAPEXTEND,
|
||||
|
||||
//! Move to the first visible character in the document line.
|
||||
VCHome = QsciScintillaBase::SCI_VCHOME,
|
||||
|
||||
//! Extend the selection to the first visible character in the document
|
||||
//! line.
|
||||
VCHomeExtend = QsciScintillaBase::SCI_VCHOMEEXTEND,
|
||||
|
||||
//! Extend the rectangular selection to the first visible character in
|
||||
//! the document line.
|
||||
VCHomeRectExtend = QsciScintillaBase::SCI_VCHOMERECTEXTEND,
|
||||
|
||||
//! Move to the first visible character of the displayed or document
|
||||
//! line.
|
||||
VCHomeWrap = QsciScintillaBase::SCI_VCHOMEWRAP,
|
||||
|
||||
//! Extend the selection to the first visible character of the
|
||||
//! displayed or document line.
|
||||
VCHomeWrapExtend = QsciScintillaBase::SCI_VCHOMEWRAPEXTEND,
|
||||
|
||||
//! Move to the end of the document line.
|
||||
LineEnd = QsciScintillaBase::SCI_LINEEND,
|
||||
|
||||
//! Extend the selection to the end of the document line.
|
||||
LineEndExtend = QsciScintillaBase::SCI_LINEENDEXTEND,
|
||||
|
||||
//! Extend the rectangular selection to the end of the document line.
|
||||
LineEndRectExtend = QsciScintillaBase::SCI_LINEENDRECTEXTEND,
|
||||
|
||||
//! Move to the end of the displayed line.
|
||||
LineEndDisplay = QsciScintillaBase::SCI_LINEENDDISPLAY,
|
||||
|
||||
//! Extend the selection to the end of the displayed line.
|
||||
LineEndDisplayExtend = QsciScintillaBase::SCI_LINEENDDISPLAYEXTEND,
|
||||
|
||||
//! Move to the end of the displayed or document line.
|
||||
LineEndWrap = QsciScintillaBase::SCI_LINEENDWRAP,
|
||||
|
||||
//! Extend the selection to the end of the displayed or document line.
|
||||
LineEndWrapExtend = QsciScintillaBase::SCI_LINEENDWRAPEXTEND,
|
||||
|
||||
//! Move to the start of the document.
|
||||
DocumentStart = QsciScintillaBase::SCI_DOCUMENTSTART,
|
||||
|
||||
//! Extend the selection to the start of the document.
|
||||
DocumentStartExtend = QsciScintillaBase::SCI_DOCUMENTSTARTEXTEND,
|
||||
|
||||
//! Move to the end of the document.
|
||||
DocumentEnd = QsciScintillaBase::SCI_DOCUMENTEND,
|
||||
|
||||
//! Extend the selection to the end of the document.
|
||||
DocumentEndExtend = QsciScintillaBase::SCI_DOCUMENTENDEXTEND,
|
||||
|
||||
//! Move up one page.
|
||||
PageUp = QsciScintillaBase::SCI_PAGEUP,
|
||||
|
||||
//! Extend the selection up one page.
|
||||
PageUpExtend = QsciScintillaBase::SCI_PAGEUPEXTEND,
|
||||
|
||||
//! Extend the rectangular selection up one page.
|
||||
PageUpRectExtend = QsciScintillaBase::SCI_PAGEUPRECTEXTEND,
|
||||
|
||||
//! Move down one page.
|
||||
PageDown = QsciScintillaBase::SCI_PAGEDOWN,
|
||||
|
||||
//! Extend the selection down one page.
|
||||
PageDownExtend = QsciScintillaBase::SCI_PAGEDOWNEXTEND,
|
||||
|
||||
//! Extend the rectangular selection down one page.
|
||||
PageDownRectExtend = QsciScintillaBase::SCI_PAGEDOWNRECTEXTEND,
|
||||
|
||||
//! Stuttered move up one page.
|
||||
StutteredPageUp = QsciScintillaBase::SCI_STUTTEREDPAGEUP,
|
||||
|
||||
//! Stuttered extend the selection up one page.
|
||||
StutteredPageUpExtend = QsciScintillaBase::SCI_STUTTEREDPAGEUPEXTEND,
|
||||
|
||||
//! Stuttered move down one page.
|
||||
StutteredPageDown = QsciScintillaBase::SCI_STUTTEREDPAGEDOWN,
|
||||
|
||||
//! Stuttered extend the selection down one page.
|
||||
StutteredPageDownExtend = QsciScintillaBase::SCI_STUTTEREDPAGEDOWNEXTEND,
|
||||
|
||||
//! Delete the current character.
|
||||
Delete = QsciScintillaBase::SCI_CLEAR,
|
||||
|
||||
//! Delete the previous character.
|
||||
DeleteBack = QsciScintillaBase::SCI_DELETEBACK,
|
||||
|
||||
//! Delete the previous character if not at start of line.
|
||||
DeleteBackNotLine = QsciScintillaBase::SCI_DELETEBACKNOTLINE,
|
||||
|
||||
//! Delete the word to the left.
|
||||
DeleteWordLeft = QsciScintillaBase::SCI_DELWORDLEFT,
|
||||
|
||||
//! Delete the word to the right.
|
||||
DeleteWordRight = QsciScintillaBase::SCI_DELWORDRIGHT,
|
||||
|
||||
//! Delete right to the end of the next word.
|
||||
DeleteWordRightEnd = QsciScintillaBase::SCI_DELWORDRIGHTEND,
|
||||
|
||||
//! Delete the line to the left.
|
||||
DeleteLineLeft = QsciScintillaBase::SCI_DELLINELEFT,
|
||||
|
||||
//! Delete the line to the right.
|
||||
DeleteLineRight = QsciScintillaBase::SCI_DELLINERIGHT,
|
||||
|
||||
//! Delete the current line.
|
||||
LineDelete = QsciScintillaBase::SCI_LINEDELETE,
|
||||
|
||||
//! Cut the current line to the clipboard.
|
||||
LineCut = QsciScintillaBase::SCI_LINECUT,
|
||||
|
||||
//! Copy the current line to the clipboard.
|
||||
LineCopy = QsciScintillaBase::SCI_LINECOPY,
|
||||
|
||||
//! Transpose the current and previous lines.
|
||||
LineTranspose = QsciScintillaBase::SCI_LINETRANSPOSE,
|
||||
|
||||
//! Duplicate the current line.
|
||||
LineDuplicate = QsciScintillaBase::SCI_LINEDUPLICATE,
|
||||
|
||||
//! Select the whole document.
|
||||
SelectAll = QsciScintillaBase::SCI_SELECTALL,
|
||||
|
||||
//! Move the selected lines up one line.
|
||||
MoveSelectedLinesUp = QsciScintillaBase::SCI_MOVESELECTEDLINESUP,
|
||||
|
||||
//! Move the selected lines down one line.
|
||||
MoveSelectedLinesDown = QsciScintillaBase::SCI_MOVESELECTEDLINESDOWN,
|
||||
|
||||
//! Duplicate the selection.
|
||||
SelectionDuplicate = QsciScintillaBase::SCI_SELECTIONDUPLICATE,
|
||||
|
||||
//! Convert the selection to lower case.
|
||||
SelectionLowerCase = QsciScintillaBase::SCI_LOWERCASE,
|
||||
|
||||
//! Convert the selection to upper case.
|
||||
SelectionUpperCase = QsciScintillaBase::SCI_UPPERCASE,
|
||||
|
||||
//! Cut the selection to the clipboard.
|
||||
SelectionCut = QsciScintillaBase::SCI_CUT,
|
||||
|
||||
//! Copy the selection to the clipboard.
|
||||
SelectionCopy = QsciScintillaBase::SCI_COPY,
|
||||
|
||||
//! Paste from the clipboard.
|
||||
Paste = QsciScintillaBase::SCI_PASTE,
|
||||
|
||||
//! Toggle insert/overtype.
|
||||
EditToggleOvertype = QsciScintillaBase::SCI_EDITTOGGLEOVERTYPE,
|
||||
|
||||
//! Insert a platform dependent newline.
|
||||
Newline = QsciScintillaBase::SCI_NEWLINE,
|
||||
|
||||
//! Insert a formfeed.
|
||||
Formfeed = QsciScintillaBase::SCI_FORMFEED,
|
||||
|
||||
//! Indent one level.
|
||||
Tab = QsciScintillaBase::SCI_TAB,
|
||||
|
||||
//! De-indent one level.
|
||||
Backtab = QsciScintillaBase::SCI_BACKTAB,
|
||||
|
||||
//! Cancel any current operation.
|
||||
Cancel = QsciScintillaBase::SCI_CANCEL,
|
||||
|
||||
//! Undo the last command.
|
||||
Undo = QsciScintillaBase::SCI_UNDO,
|
||||
|
||||
//! Redo the last command.
|
||||
Redo = QsciScintillaBase::SCI_REDO,
|
||||
|
||||
//! Zoom in.
|
||||
ZoomIn = QsciScintillaBase::SCI_ZOOMIN,
|
||||
|
||||
//! Zoom out.
|
||||
ZoomOut = QsciScintillaBase::SCI_ZOOMOUT,
|
||||
};
|
||||
|
||||
//! Return the command that will be executed by this instance.
|
||||
Command command() const {return scicmd;}
|
||||
|
||||
//! Execute the command.
|
||||
void execute();
|
||||
|
||||
//! Binds the key \a key to the command. If \a key is 0 then the key
|
||||
//! binding is removed. If \a key is invalid then the key binding is
|
||||
//! unchanged. Valid keys are any visible or control character or any
|
||||
//! of \c Key_Down, \c Key_Up, \c Key_Left, \c Key_Right, \c Key_Home,
|
||||
//! \c Key_End, \c Key_PageUp, \c Key_PageDown, \c Key_Delete,
|
||||
//! \c Key_Insert, \c Key_Escape, \c Key_Backspace, \c Key_Tab and
|
||||
//! \c Key_Return. Keys may be modified with any combination of \c SHIFT,
|
||||
//! \c CTRL, \c ALT and \c META.
|
||||
//!
|
||||
//! \sa key(), setAlternateKey(), validKey()
|
||||
void setKey(int key);
|
||||
|
||||
//! Binds the alternate key \a altkey to the command. If \a key is 0
|
||||
//! then the alternate key binding is removed.
|
||||
//!
|
||||
//! \sa alternateKey(), setKey(), validKey()
|
||||
void setAlternateKey(int altkey);
|
||||
|
||||
//! The key that is currently bound to the command is returned.
|
||||
//!
|
||||
//! \sa setKey(), alternateKey()
|
||||
int key() const {return qkey;}
|
||||
|
||||
//! The alternate key that is currently bound to the command is
|
||||
//! returned.
|
||||
//!
|
||||
//! \sa setAlternateKey(), key()
|
||||
int alternateKey() const {return qaltkey;}
|
||||
|
||||
//! If the key \a key is valid then true is returned.
|
||||
static bool validKey(int key);
|
||||
|
||||
//! The user friendly description of the command is returned.
|
||||
QString description() const;
|
||||
|
||||
private:
|
||||
friend class QsciCommandSet;
|
||||
|
||||
QsciCommand(QsciScintilla *qs, Command cmd, int key, int altkey,
|
||||
const char *desc);
|
||||
|
||||
void bindKey(int key,int &qk,int &scik);
|
||||
|
||||
QsciScintilla *qsCmd;
|
||||
Command scicmd;
|
||||
int qkey, scikey, qaltkey, scialtkey;
|
||||
const char *descCmd;
|
||||
|
||||
QsciCommand(const QsciCommand &);
|
||||
QsciCommand &operator=(const QsciCommand &);
|
||||
};
|
||||
|
||||
#ifdef __APPLE__
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
116
samples/C++/qsciprinter.h
Normal file
116
samples/C++/qsciprinter.h
Normal file
@@ -0,0 +1,116 @@
|
||||
// This module defines interface to the QsciPrinter class.
|
||||
//
|
||||
// Copyright (c) 2011 Riverbank Computing Limited <info@riverbankcomputing.com>
|
||||
//
|
||||
// This file is part of QScintilla.
|
||||
//
|
||||
// This file may be used under the terms of the GNU General Public
|
||||
// License versions 2.0 or 3.0 as published by the Free Software
|
||||
// Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
|
||||
// included in the packaging of this file. Alternatively you may (at
|
||||
// your option) use any later version of the GNU General Public
|
||||
// License if such license has been publicly approved by Riverbank
|
||||
// Computing Limited (or its successors, if any) and the KDE Free Qt
|
||||
// Foundation. In addition, as a special exception, Riverbank gives you
|
||||
// certain additional rights. These rights are described in the Riverbank
|
||||
// GPL Exception version 1.1, which can be found in the file
|
||||
// GPL_EXCEPTION.txt in this package.
|
||||
//
|
||||
// If you are unsure which license is appropriate for your use, please
|
||||
// contact the sales department at sales@riverbankcomputing.com.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
#ifndef QSCIPRINTER_H
|
||||
#define QSCIPRINTER_H
|
||||
|
||||
#ifdef __APPLE__
|
||||
extern "C++" {
|
||||
#endif
|
||||
|
||||
#include <qprinter.h>
|
||||
|
||||
#include <Qsci/qsciglobal.h>
|
||||
#include <Qsci/qsciscintilla.h>
|
||||
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QRect;
|
||||
class QPainter;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class QsciScintillaBase;
|
||||
|
||||
|
||||
//! \brief The QsciPrinter class is a sub-class of the Qt QPrinter class that
|
||||
//! is able to print the text of a Scintilla document.
|
||||
//!
|
||||
//! The class can be further sub-classed to alter to layout of the text, adding
|
||||
//! headers and footers for example.
|
||||
class QSCINTILLA_EXPORT QsciPrinter : public QPrinter
|
||||
{
|
||||
public:
|
||||
//! Constructs a printer paint device with mode \a mode.
|
||||
QsciPrinter(PrinterMode mode = ScreenResolution);
|
||||
|
||||
//! Destroys the QsciPrinter instance.
|
||||
virtual ~QsciPrinter();
|
||||
|
||||
//! Format a page, by adding headers and footers for example, before the
|
||||
//! document text is drawn on it. \a painter is the painter to be used to
|
||||
//! add customised text and graphics. \a drawing is true if the page is
|
||||
//! actually being drawn rather than being sized. \a painter drawing
|
||||
//! methods must only be called when \a drawing is true. \a area is the
|
||||
//! area of the page that will be used to draw the text. This should be
|
||||
//! modified if it is necessary to reserve space for any customised text or
|
||||
//! graphics. By default the area is relative to the printable area of the
|
||||
//! page. Use QPrinter::setFullPage() because calling printRange() if you
|
||||
//! want to try and print over the whole page. \a pagenr is the number of
|
||||
//! the page. The first page is numbered 1.
|
||||
virtual void formatPage(QPainter &painter, bool drawing, QRect &area,
|
||||
int pagenr);
|
||||
|
||||
//! Return the number of points to add to each font when printing.
|
||||
//!
|
||||
//! \sa setMagnification()
|
||||
int magnification() const {return mag;}
|
||||
|
||||
//! Sets the number of points to add to each font when printing to \a
|
||||
//! magnification.
|
||||
//!
|
||||
//! \sa magnification()
|
||||
virtual void setMagnification(int magnification);
|
||||
|
||||
//! Print a range of lines from the Scintilla instance \a qsb. \a from is
|
||||
//! the first line to print and a negative value signifies the first line
|
||||
//! of text. \a to is the last line to print and a negative value
|
||||
//! signifies the last line of text. true is returned if there was no
|
||||
//! error.
|
||||
virtual int printRange(QsciScintillaBase *qsb, int from = -1, int to = -1);
|
||||
|
||||
//! Return the line wrap mode used when printing. The default is
|
||||
//! QsciScintilla::WrapWord.
|
||||
//!
|
||||
//! \sa setWrapMode()
|
||||
QsciScintilla::WrapMode wrapMode() const {return wrap;}
|
||||
|
||||
//! Sets the line wrap mode used when printing to \a wmode.
|
||||
//!
|
||||
//! \sa wrapMode()
|
||||
virtual void setWrapMode(QsciScintilla::WrapMode wmode);
|
||||
|
||||
private:
|
||||
int mag;
|
||||
QsciScintilla::WrapMode wrap;
|
||||
|
||||
QsciPrinter(const QsciPrinter &);
|
||||
QsciPrinter &operator=(const QsciPrinter &);
|
||||
};
|
||||
|
||||
#ifdef __APPLE__
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1088
samples/C++/scanner.cc
Normal file
1088
samples/C++/scanner.cc
Normal file
File diff suppressed because it is too large
Load Diff
576
samples/C++/scanner.h
Normal file
576
samples/C++/scanner.h
Normal file
@@ -0,0 +1,576 @@
|
||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Features shared by parsing and pre-parsing scanners.
|
||||
|
||||
#ifndef V8_SCANNER_H_
|
||||
#define V8_SCANNER_H_
|
||||
|
||||
#include "allocation.h"
|
||||
#include "char-predicates.h"
|
||||
#include "checks.h"
|
||||
#include "globals.h"
|
||||
#include "token.h"
|
||||
#include "unicode-inl.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
|
||||
// General collection of (multi-)bit-flags that can be passed to scanners and
|
||||
// parsers to signify their (initial) mode of operation.
|
||||
enum ParsingFlags {
|
||||
kNoParsingFlags = 0,
|
||||
// Embed LanguageMode values in parsing flags, i.e., equivalent to:
|
||||
// CLASSIC_MODE = 0,
|
||||
// STRICT_MODE,
|
||||
// EXTENDED_MODE,
|
||||
kLanguageModeMask = 0x03,
|
||||
kAllowLazy = 0x04,
|
||||
kAllowNativesSyntax = 0x08,
|
||||
kAllowModules = 0x10
|
||||
};
|
||||
|
||||
STATIC_ASSERT((kLanguageModeMask & CLASSIC_MODE) == CLASSIC_MODE);
|
||||
STATIC_ASSERT((kLanguageModeMask & STRICT_MODE) == STRICT_MODE);
|
||||
STATIC_ASSERT((kLanguageModeMask & EXTENDED_MODE) == EXTENDED_MODE);
|
||||
|
||||
|
||||
// Returns the value (0 .. 15) of a hexadecimal character c.
|
||||
// If c is not a legal hexadecimal character, returns a value < 0.
|
||||
inline int HexValue(uc32 c) {
|
||||
c -= '0';
|
||||
if (static_cast<unsigned>(c) <= 9) return c;
|
||||
c = (c | 0x20) - ('a' - '0'); // detect 0x11..0x16 and 0x31..0x36.
|
||||
if (static_cast<unsigned>(c) <= 5) return c + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Buffered stream of UTF-16 code units, using an internal UTF-16 buffer.
|
||||
// A code unit is a 16 bit value representing either a 16 bit code point
|
||||
// or one part of a surrogate pair that make a single 21 bit code point.
|
||||
|
||||
class Utf16CharacterStream {
|
||||
public:
|
||||
Utf16CharacterStream() : pos_(0) { }
|
||||
virtual ~Utf16CharacterStream() { }
|
||||
|
||||
// Returns and advances past the next UTF-16 code unit in the input
|
||||
// stream. If there are no more code units, it returns a negative
|
||||
// value.
|
||||
inline uc32 Advance() {
|
||||
if (buffer_cursor_ < buffer_end_ || ReadBlock()) {
|
||||
pos_++;
|
||||
return static_cast<uc32>(*(buffer_cursor_++));
|
||||
}
|
||||
// Note: currently the following increment is necessary to avoid a
|
||||
// parser problem! The scanner treats the final kEndOfInput as
|
||||
// a code unit with a position, and does math relative to that
|
||||
// position.
|
||||
pos_++;
|
||||
|
||||
return kEndOfInput;
|
||||
}
|
||||
|
||||
// Return the current position in the code unit stream.
|
||||
// Starts at zero.
|
||||
inline unsigned pos() const { return pos_; }
|
||||
|
||||
// Skips forward past the next code_unit_count UTF-16 code units
|
||||
// in the input, or until the end of input if that comes sooner.
|
||||
// Returns the number of code units actually skipped. If less
|
||||
// than code_unit_count,
|
||||
inline unsigned SeekForward(unsigned code_unit_count) {
|
||||
unsigned buffered_chars =
|
||||
static_cast<unsigned>(buffer_end_ - buffer_cursor_);
|
||||
if (code_unit_count <= buffered_chars) {
|
||||
buffer_cursor_ += code_unit_count;
|
||||
pos_ += code_unit_count;
|
||||
return code_unit_count;
|
||||
}
|
||||
return SlowSeekForward(code_unit_count);
|
||||
}
|
||||
|
||||
// Pushes back the most recently read UTF-16 code unit (or negative
|
||||
// value if at end of input), i.e., the value returned by the most recent
|
||||
// call to Advance.
|
||||
// Must not be used right after calling SeekForward.
|
||||
virtual void PushBack(int32_t code_unit) = 0;
|
||||
|
||||
protected:
|
||||
static const uc32 kEndOfInput = -1;
|
||||
|
||||
// Ensures that the buffer_cursor_ points to the code_unit at
|
||||
// position pos_ of the input, if possible. If the position
|
||||
// is at or after the end of the input, return false. If there
|
||||
// are more code_units available, return true.
|
||||
virtual bool ReadBlock() = 0;
|
||||
virtual unsigned SlowSeekForward(unsigned code_unit_count) = 0;
|
||||
|
||||
const uc16* buffer_cursor_;
|
||||
const uc16* buffer_end_;
|
||||
unsigned pos_;
|
||||
};
|
||||
|
||||
|
||||
class UnicodeCache {
|
||||
// ---------------------------------------------------------------------
|
||||
// Caching predicates used by scanners.
|
||||
public:
|
||||
UnicodeCache() {}
|
||||
typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder;
|
||||
|
||||
StaticResource<Utf8Decoder>* utf8_decoder() {
|
||||
return &utf8_decoder_;
|
||||
}
|
||||
|
||||
bool IsIdentifierStart(unibrow::uchar c) { return kIsIdentifierStart.get(c); }
|
||||
bool IsIdentifierPart(unibrow::uchar c) { return kIsIdentifierPart.get(c); }
|
||||
bool IsLineTerminator(unibrow::uchar c) { return kIsLineTerminator.get(c); }
|
||||
bool IsWhiteSpace(unibrow::uchar c) { return kIsWhiteSpace.get(c); }
|
||||
|
||||
private:
|
||||
unibrow::Predicate<IdentifierStart, 128> kIsIdentifierStart;
|
||||
unibrow::Predicate<IdentifierPart, 128> kIsIdentifierPart;
|
||||
unibrow::Predicate<unibrow::LineTerminator, 128> kIsLineTerminator;
|
||||
unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;
|
||||
StaticResource<Utf8Decoder> utf8_decoder_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(UnicodeCache);
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// LiteralBuffer - Collector of chars of literals.
|
||||
|
||||
class LiteralBuffer {
|
||||
public:
|
||||
LiteralBuffer() : is_ascii_(true), position_(0), backing_store_() { }
|
||||
|
||||
~LiteralBuffer() {
|
||||
if (backing_store_.length() > 0) {
|
||||
backing_store_.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
INLINE(void AddChar(uint32_t code_unit)) {
|
||||
if (position_ >= backing_store_.length()) ExpandBuffer();
|
||||
if (is_ascii_) {
|
||||
if (code_unit < kMaxAsciiCharCodeU) {
|
||||
backing_store_[position_] = static_cast<byte>(code_unit);
|
||||
position_ += kASCIISize;
|
||||
return;
|
||||
}
|
||||
ConvertToUtf16();
|
||||
}
|
||||
ASSERT(code_unit < 0x10000u);
|
||||
*reinterpret_cast<uc16*>(&backing_store_[position_]) = code_unit;
|
||||
position_ += kUC16Size;
|
||||
}
|
||||
|
||||
bool is_ascii() { return is_ascii_; }
|
||||
|
||||
Vector<const uc16> utf16_literal() {
|
||||
ASSERT(!is_ascii_);
|
||||
ASSERT((position_ & 0x1) == 0);
|
||||
return Vector<const uc16>(
|
||||
reinterpret_cast<const uc16*>(backing_store_.start()),
|
||||
position_ >> 1);
|
||||
}
|
||||
|
||||
Vector<const char> ascii_literal() {
|
||||
ASSERT(is_ascii_);
|
||||
return Vector<const char>(
|
||||
reinterpret_cast<const char*>(backing_store_.start()),
|
||||
position_);
|
||||
}
|
||||
|
||||
int length() {
|
||||
return is_ascii_ ? position_ : (position_ >> 1);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
position_ = 0;
|
||||
is_ascii_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kInitialCapacity = 16;
|
||||
static const int kGrowthFactory = 4;
|
||||
static const int kMinConversionSlack = 256;
|
||||
static const int kMaxGrowth = 1 * MB;
|
||||
inline int NewCapacity(int min_capacity) {
|
||||
int capacity = Max(min_capacity, backing_store_.length());
|
||||
int new_capacity = Min(capacity * kGrowthFactory, capacity + kMaxGrowth);
|
||||
return new_capacity;
|
||||
}
|
||||
|
||||
void ExpandBuffer() {
|
||||
Vector<byte> new_store = Vector<byte>::New(NewCapacity(kInitialCapacity));
|
||||
memcpy(new_store.start(), backing_store_.start(), position_);
|
||||
backing_store_.Dispose();
|
||||
backing_store_ = new_store;
|
||||
}
|
||||
|
||||
void ConvertToUtf16() {
|
||||
ASSERT(is_ascii_);
|
||||
Vector<byte> new_store;
|
||||
int new_content_size = position_ * kUC16Size;
|
||||
if (new_content_size >= backing_store_.length()) {
|
||||
// Ensure room for all currently read code units as UC16 as well
|
||||
// as the code unit about to be stored.
|
||||
new_store = Vector<byte>::New(NewCapacity(new_content_size));
|
||||
} else {
|
||||
new_store = backing_store_;
|
||||
}
|
||||
char* src = reinterpret_cast<char*>(backing_store_.start());
|
||||
uc16* dst = reinterpret_cast<uc16*>(new_store.start());
|
||||
for (int i = position_ - 1; i >= 0; i--) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
if (new_store.start() != backing_store_.start()) {
|
||||
backing_store_.Dispose();
|
||||
backing_store_ = new_store;
|
||||
}
|
||||
position_ = new_content_size;
|
||||
is_ascii_ = false;
|
||||
}
|
||||
|
||||
bool is_ascii_;
|
||||
int position_;
|
||||
Vector<byte> backing_store_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LiteralBuffer);
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// JavaScript Scanner.
|
||||
|
||||
class Scanner {
|
||||
public:
|
||||
// Scoped helper for literal recording. Automatically drops the literal
|
||||
// if aborting the scanning before it's complete.
|
||||
class LiteralScope {
|
||||
public:
|
||||
explicit LiteralScope(Scanner* self)
|
||||
: scanner_(self), complete_(false) {
|
||||
scanner_->StartLiteral();
|
||||
}
|
||||
~LiteralScope() {
|
||||
if (!complete_) scanner_->DropLiteral();
|
||||
}
|
||||
void Complete() {
|
||||
scanner_->TerminateLiteral();
|
||||
complete_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
Scanner* scanner_;
|
||||
bool complete_;
|
||||
};
|
||||
|
||||
// Representation of an interval of source positions.
|
||||
struct Location {
|
||||
Location(int b, int e) : beg_pos(b), end_pos(e) { }
|
||||
Location() : beg_pos(0), end_pos(0) { }
|
||||
|
||||
bool IsValid() const {
|
||||
return beg_pos >= 0 && end_pos >= beg_pos;
|
||||
}
|
||||
|
||||
static Location invalid() { return Location(-1, -1); }
|
||||
|
||||
int beg_pos;
|
||||
int end_pos;
|
||||
};
|
||||
|
||||
// -1 is outside of the range of any real source code.
|
||||
static const int kNoOctalLocation = -1;
|
||||
|
||||
typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder;
|
||||
|
||||
explicit Scanner(UnicodeCache* scanner_contants);
|
||||
|
||||
void Initialize(Utf16CharacterStream* source);
|
||||
|
||||
// Returns the next token and advances input.
|
||||
Token::Value Next();
|
||||
// Returns the current token again.
|
||||
Token::Value current_token() { return current_.token; }
|
||||
// Returns the location information for the current token
|
||||
// (the token last returned by Next()).
|
||||
Location location() const { return current_.location; }
|
||||
// Returns the literal string, if any, for the current token (the
|
||||
// token last returned by Next()). The string is 0-terminated.
|
||||
// Literal strings are collected for identifiers, strings, and
|
||||
// numbers.
|
||||
// These functions only give the correct result if the literal
|
||||
// was scanned between calls to StartLiteral() and TerminateLiteral().
|
||||
Vector<const char> literal_ascii_string() {
|
||||
ASSERT_NOT_NULL(current_.literal_chars);
|
||||
return current_.literal_chars->ascii_literal();
|
||||
}
|
||||
Vector<const uc16> literal_utf16_string() {
|
||||
ASSERT_NOT_NULL(current_.literal_chars);
|
||||
return current_.literal_chars->utf16_literal();
|
||||
}
|
||||
bool is_literal_ascii() {
|
||||
ASSERT_NOT_NULL(current_.literal_chars);
|
||||
return current_.literal_chars->is_ascii();
|
||||
}
|
||||
int literal_length() const {
|
||||
ASSERT_NOT_NULL(current_.literal_chars);
|
||||
return current_.literal_chars->length();
|
||||
}
|
||||
|
||||
bool literal_contains_escapes() const {
|
||||
Location location = current_.location;
|
||||
int source_length = (location.end_pos - location.beg_pos);
|
||||
if (current_.token == Token::STRING) {
|
||||
// Subtract delimiters.
|
||||
source_length -= 2;
|
||||
}
|
||||
return current_.literal_chars->length() != source_length;
|
||||
}
|
||||
|
||||
// Similar functions for the upcoming token.
|
||||
|
||||
// One token look-ahead (past the token returned by Next()).
|
||||
Token::Value peek() const { return next_.token; }
|
||||
|
||||
Location peek_location() const { return next_.location; }
|
||||
|
||||
// Returns the literal string for the next token (the token that
|
||||
// would be returned if Next() were called).
|
||||
Vector<const char> next_literal_ascii_string() {
|
||||
ASSERT_NOT_NULL(next_.literal_chars);
|
||||
return next_.literal_chars->ascii_literal();
|
||||
}
|
||||
Vector<const uc16> next_literal_utf16_string() {
|
||||
ASSERT_NOT_NULL(next_.literal_chars);
|
||||
return next_.literal_chars->utf16_literal();
|
||||
}
|
||||
bool is_next_literal_ascii() {
|
||||
ASSERT_NOT_NULL(next_.literal_chars);
|
||||
return next_.literal_chars->is_ascii();
|
||||
}
|
||||
int next_literal_length() const {
|
||||
ASSERT_NOT_NULL(next_.literal_chars);
|
||||
return next_.literal_chars->length();
|
||||
}
|
||||
|
||||
UnicodeCache* unicode_cache() { return unicode_cache_; }
|
||||
|
||||
static const int kCharacterLookaheadBufferSize = 1;
|
||||
|
||||
// Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
|
||||
uc32 ScanOctalEscape(uc32 c, int length);
|
||||
|
||||
// Returns the location of the last seen octal literal.
|
||||
Location octal_position() const { return octal_pos_; }
|
||||
void clear_octal_position() { octal_pos_ = Location::invalid(); }
|
||||
|
||||
// Seek forward to the given position. This operation does not
|
||||
// work in general, for instance when there are pushed back
|
||||
// characters, but works for seeking forward until simple delimiter
|
||||
// tokens, which is what it is used for.
|
||||
void SeekForward(int pos);
|
||||
|
||||
bool HarmonyScoping() const {
|
||||
return harmony_scoping_;
|
||||
}
|
||||
void SetHarmonyScoping(bool scoping) {
|
||||
harmony_scoping_ = scoping;
|
||||
}
|
||||
bool HarmonyModules() const {
|
||||
return harmony_modules_;
|
||||
}
|
||||
void SetHarmonyModules(bool modules) {
|
||||
harmony_modules_ = modules;
|
||||
}
|
||||
|
||||
|
||||
// Returns true if there was a line terminator before the peek'ed token,
|
||||
// possibly inside a multi-line comment.
|
||||
bool HasAnyLineTerminatorBeforeNext() const {
|
||||
return has_line_terminator_before_next_ ||
|
||||
has_multiline_comment_before_next_;
|
||||
}
|
||||
|
||||
// Scans the input as a regular expression pattern, previous
|
||||
// character(s) must be /(=). Returns true if a pattern is scanned.
|
||||
bool ScanRegExpPattern(bool seen_equal);
|
||||
// Returns true if regexp flags are scanned (always since flags can
|
||||
// be empty).
|
||||
bool ScanRegExpFlags();
|
||||
|
||||
// Tells whether the buffer contains an identifier (no escapes).
|
||||
// Used for checking if a property name is an identifier.
|
||||
static bool IsIdentifier(unibrow::CharacterStream* buffer);
|
||||
|
||||
private:
|
||||
// The current and look-ahead token.
|
||||
struct TokenDesc {
|
||||
Token::Value token;
|
||||
Location location;
|
||||
LiteralBuffer* literal_chars;
|
||||
};
|
||||
|
||||
// Call this after setting source_ to the input.
|
||||
void Init() {
|
||||
// Set c0_ (one character ahead)
|
||||
STATIC_ASSERT(kCharacterLookaheadBufferSize == 1);
|
||||
Advance();
|
||||
// Initialize current_ to not refer to a literal.
|
||||
current_.literal_chars = NULL;
|
||||
}
|
||||
|
||||
// Literal buffer support
|
||||
inline void StartLiteral() {
|
||||
LiteralBuffer* free_buffer = (current_.literal_chars == &literal_buffer1_) ?
|
||||
&literal_buffer2_ : &literal_buffer1_;
|
||||
free_buffer->Reset();
|
||||
next_.literal_chars = free_buffer;
|
||||
}
|
||||
|
||||
INLINE(void AddLiteralChar(uc32 c)) {
|
||||
ASSERT_NOT_NULL(next_.literal_chars);
|
||||
next_.literal_chars->AddChar(c);
|
||||
}
|
||||
|
||||
// Complete scanning of a literal.
|
||||
inline void TerminateLiteral() {
|
||||
// Does nothing in the current implementation.
|
||||
}
|
||||
|
||||
// Stops scanning of a literal and drop the collected characters,
|
||||
// e.g., due to an encountered error.
|
||||
inline void DropLiteral() {
|
||||
next_.literal_chars = NULL;
|
||||
}
|
||||
|
||||
inline void AddLiteralCharAdvance() {
|
||||
AddLiteralChar(c0_);
|
||||
Advance();
|
||||
}
|
||||
|
||||
// Low-level scanning support.
|
||||
void Advance() { c0_ = source_->Advance(); }
|
||||
void PushBack(uc32 ch) {
|
||||
source_->PushBack(c0_);
|
||||
c0_ = ch;
|
||||
}
|
||||
|
||||
inline Token::Value Select(Token::Value tok) {
|
||||
Advance();
|
||||
return tok;
|
||||
}
|
||||
|
||||
inline Token::Value Select(uc32 next, Token::Value then, Token::Value else_) {
|
||||
Advance();
|
||||
if (c0_ == next) {
|
||||
Advance();
|
||||
return then;
|
||||
} else {
|
||||
return else_;
|
||||
}
|
||||
}
|
||||
|
||||
uc32 ScanHexNumber(int expected_length);
|
||||
|
||||
// Scans a single JavaScript token.
|
||||
void Scan();
|
||||
|
||||
bool SkipWhiteSpace();
|
||||
Token::Value SkipSingleLineComment();
|
||||
Token::Value SkipMultiLineComment();
|
||||
// Scans a possible HTML comment -- begins with '<!'.
|
||||
Token::Value ScanHtmlComment();
|
||||
|
||||
void ScanDecimalDigits();
|
||||
Token::Value ScanNumber(bool seen_period);
|
||||
Token::Value ScanIdentifierOrKeyword();
|
||||
Token::Value ScanIdentifierSuffix(LiteralScope* literal);
|
||||
|
||||
Token::Value ScanString();
|
||||
|
||||
// Scans an escape-sequence which is part of a string and adds the
|
||||
// decoded character to the current literal. Returns true if a pattern
|
||||
// is scanned.
|
||||
bool ScanEscape();
|
||||
// Decodes a Unicode escape-sequence which is part of an identifier.
|
||||
// If the escape sequence cannot be decoded the result is kBadChar.
|
||||
uc32 ScanIdentifierUnicodeEscape();
|
||||
// Scans a Unicode escape-sequence and adds its characters,
|
||||
// uninterpreted, to the current literal. Used for parsing RegExp
|
||||
// flags.
|
||||
bool ScanLiteralUnicodeEscape();
|
||||
|
||||
// Return the current source position.
|
||||
int source_pos() {
|
||||
return source_->pos() - kCharacterLookaheadBufferSize;
|
||||
}
|
||||
|
||||
UnicodeCache* unicode_cache_;
|
||||
|
||||
// Buffers collecting literal strings, numbers, etc.
|
||||
LiteralBuffer literal_buffer1_;
|
||||
LiteralBuffer literal_buffer2_;
|
||||
|
||||
TokenDesc current_; // desc for current token (as returned by Next())
|
||||
TokenDesc next_; // desc for next token (one token look-ahead)
|
||||
|
||||
// Input stream. Must be initialized to an Utf16CharacterStream.
|
||||
Utf16CharacterStream* source_;
|
||||
|
||||
|
||||
// Start position of the octal literal last scanned.
|
||||
Location octal_pos_;
|
||||
|
||||
// One Unicode character look-ahead; c0_ < 0 at the end of the input.
|
||||
uc32 c0_;
|
||||
|
||||
// Whether there is a line terminator whitespace character after
|
||||
// the current token, and before the next. Does not count newlines
|
||||
// inside multiline comments.
|
||||
bool has_line_terminator_before_next_;
|
||||
// Whether there is a multi-line comment that contains a
|
||||
// line-terminator after the current token, and before the next.
|
||||
bool has_multiline_comment_before_next_;
|
||||
// Whether we scan 'let' as a keyword for harmony block-scoped let bindings.
|
||||
bool harmony_scoping_;
|
||||
// Whether we scan 'module', 'import', 'export' as keywords.
|
||||
bool harmony_modules_;
|
||||
};
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_SCANNER_H_
|
||||
71
samples/C++/utils.h
Normal file
71
samples/C++/utils.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
This file is part of the PhantomJS project from Ofi Labs.
|
||||
|
||||
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||
Copyright (C) 2011 Ivan De Marino <ivan.de.marino@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QWebFrame>
|
||||
#include <QFile>
|
||||
|
||||
#include "csconverter.h"
|
||||
#include "encoding.h"
|
||||
|
||||
class QTemporaryFile;
|
||||
/**
|
||||
* Aggregate common utility functions.
|
||||
* Functions are static methods.
|
||||
* It's important to notice that, at the moment, this class can't be instantiated by design.
|
||||
*/
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
static void showUsage();
|
||||
static void messageHandler(QtMsgType type, const char *msg);
|
||||
static bool exceptionHandler(const char* dump_path, const char* minidump_id, void* context, bool succeeded);
|
||||
static QVariant coffee2js(const QString &script);
|
||||
static bool injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame, const bool startingScript = false);
|
||||
static bool injectJsInFrame(const QString &jsFilePath, const Encoding &jsFileEnc, const QString &libraryPath, QWebFrame *targetFrame, const bool startingScript = false);
|
||||
static QString readResourceFileUtf8(const QString &resourceFilePath);
|
||||
|
||||
static bool loadJSForDebug(const QString &jsFilePath, const Encoding &jsFileEnc, const QString &libraryPath, QWebFrame *targetFrame, const bool autorun = false);
|
||||
static bool loadJSForDebug(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame, const bool autorun = false);
|
||||
static void cleanupFromDebug();
|
||||
|
||||
private:
|
||||
static QString findScript(const QString &jsFilePath, const QString& libraryPath);
|
||||
static QString jsFromScriptFile(const QString& scriptPath, const Encoding& enc);
|
||||
Utils(); //< This class shouldn't be instantiated
|
||||
|
||||
static QTemporaryFile* m_tempHarness; //< We want to make sure to clean up after ourselves
|
||||
static QTemporaryFile* m_tempWrapper;
|
||||
};
|
||||
|
||||
#endif // UTILS_H
|
||||
288
samples/C++/v8.cc
Normal file
288
samples/C++/v8.cc
Normal file
@@ -0,0 +1,288 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "assembler.h"
|
||||
#include "isolate.h"
|
||||
#include "elements.h"
|
||||
#include "bootstrapper.h"
|
||||
#include "debug.h"
|
||||
#include "deoptimizer.h"
|
||||
#include "frames.h"
|
||||
#include "heap-profiler.h"
|
||||
#include "hydrogen.h"
|
||||
#include "lithium-allocator.h"
|
||||
#include "log.h"
|
||||
#include "once.h"
|
||||
#include "platform.h"
|
||||
#include "runtime-profiler.h"
|
||||
#include "serialize.h"
|
||||
#include "store-buffer.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
V8_DECLARE_ONCE(init_once);
|
||||
|
||||
bool V8::is_running_ = false;
|
||||
bool V8::has_been_set_up_ = false;
|
||||
bool V8::has_been_disposed_ = false;
|
||||
bool V8::has_fatal_error_ = false;
|
||||
bool V8::use_crankshaft_ = true;
|
||||
List<CallCompletedCallback>* V8::call_completed_callbacks_ = NULL;
|
||||
|
||||
static LazyMutex entropy_mutex = LAZY_MUTEX_INITIALIZER;
|
||||
|
||||
static EntropySource entropy_source;
|
||||
|
||||
|
||||
bool V8::Initialize(Deserializer* des) {
|
||||
FlagList::EnforceFlagImplications();
|
||||
|
||||
InitializeOncePerProcess();
|
||||
|
||||
// The current thread may not yet had entered an isolate to run.
|
||||
// Note the Isolate::Current() may be non-null because for various
|
||||
// initialization purposes an initializing thread may be assigned an isolate
|
||||
// but not actually enter it.
|
||||
if (i::Isolate::CurrentPerIsolateThreadData() == NULL) {
|
||||
i::Isolate::EnterDefaultIsolate();
|
||||
}
|
||||
|
||||
ASSERT(i::Isolate::CurrentPerIsolateThreadData() != NULL);
|
||||
ASSERT(i::Isolate::CurrentPerIsolateThreadData()->thread_id().Equals(
|
||||
i::ThreadId::Current()));
|
||||
ASSERT(i::Isolate::CurrentPerIsolateThreadData()->isolate() ==
|
||||
i::Isolate::Current());
|
||||
|
||||
if (IsDead()) return false;
|
||||
|
||||
Isolate* isolate = Isolate::Current();
|
||||
if (isolate->IsInitialized()) return true;
|
||||
|
||||
is_running_ = true;
|
||||
has_been_set_up_ = true;
|
||||
has_fatal_error_ = false;
|
||||
has_been_disposed_ = false;
|
||||
|
||||
return isolate->Init(des);
|
||||
}
|
||||
|
||||
|
||||
void V8::SetFatalError() {
|
||||
is_running_ = false;
|
||||
has_fatal_error_ = true;
|
||||
}
|
||||
|
||||
|
||||
void V8::TearDown() {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
ASSERT(isolate->IsDefaultIsolate());
|
||||
|
||||
if (!has_been_set_up_ || has_been_disposed_) return;
|
||||
|
||||
ElementsAccessor::TearDown();
|
||||
LOperand::TearDownCaches();
|
||||
RegisteredExtension::UnregisterAll();
|
||||
|
||||
isolate->TearDown();
|
||||
delete isolate;
|
||||
|
||||
is_running_ = false;
|
||||
has_been_disposed_ = true;
|
||||
|
||||
delete call_completed_callbacks_;
|
||||
call_completed_callbacks_ = NULL;
|
||||
|
||||
OS::TearDown();
|
||||
}
|
||||
|
||||
|
||||
static void seed_random(uint32_t* state) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (FLAG_random_seed != 0) {
|
||||
state[i] = FLAG_random_seed;
|
||||
} else if (entropy_source != NULL) {
|
||||
uint32_t val;
|
||||
ScopedLock lock(entropy_mutex.Pointer());
|
||||
entropy_source(reinterpret_cast<unsigned char*>(&val), sizeof(uint32_t));
|
||||
state[i] = val;
|
||||
} else {
|
||||
state[i] = random();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Random number generator using George Marsaglia's MWC algorithm.
|
||||
static uint32_t random_base(uint32_t* state) {
|
||||
// Initialize seed using the system random().
|
||||
// No non-zero seed will ever become zero again.
|
||||
if (state[0] == 0) seed_random(state);
|
||||
|
||||
// Mix the bits. Never replaces state[i] with 0 if it is nonzero.
|
||||
state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16);
|
||||
state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16);
|
||||
|
||||
return (state[0] << 14) + (state[1] & 0x3FFFF);
|
||||
}
|
||||
|
||||
|
||||
void V8::SetEntropySource(EntropySource source) {
|
||||
entropy_source = source;
|
||||
}
|
||||
|
||||
|
||||
void V8::SetReturnAddressLocationResolver(
|
||||
ReturnAddressLocationResolver resolver) {
|
||||
StackFrame::SetReturnAddressLocationResolver(resolver);
|
||||
}
|
||||
|
||||
|
||||
// Used by JavaScript APIs
|
||||
uint32_t V8::Random(Context* context) {
|
||||
ASSERT(context->IsGlobalContext());
|
||||
ByteArray* seed = context->random_seed();
|
||||
return random_base(reinterpret_cast<uint32_t*>(seed->GetDataStartAddress()));
|
||||
}
|
||||
|
||||
|
||||
// Used internally by the JIT and memory allocator for security
|
||||
// purposes. So, we keep a different state to prevent informations
|
||||
// leaks that could be used in an exploit.
|
||||
uint32_t V8::RandomPrivate(Isolate* isolate) {
|
||||
ASSERT(isolate == Isolate::Current());
|
||||
return random_base(isolate->private_random_seed());
|
||||
}
|
||||
|
||||
|
||||
bool V8::IdleNotification(int hint) {
|
||||
// Returning true tells the caller that there is no need to call
|
||||
// IdleNotification again.
|
||||
if (!FLAG_use_idle_notification) return true;
|
||||
|
||||
// Tell the heap that it may want to adjust.
|
||||
return HEAP->IdleNotification(hint);
|
||||
}
|
||||
|
||||
|
||||
void V8::AddCallCompletedCallback(CallCompletedCallback callback) {
|
||||
if (call_completed_callbacks_ == NULL) { // Lazy init.
|
||||
call_completed_callbacks_ = new List<CallCompletedCallback>();
|
||||
}
|
||||
for (int i = 0; i < call_completed_callbacks_->length(); i++) {
|
||||
if (callback == call_completed_callbacks_->at(i)) return;
|
||||
}
|
||||
call_completed_callbacks_->Add(callback);
|
||||
}
|
||||
|
||||
|
||||
void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) {
|
||||
if (call_completed_callbacks_ == NULL) return;
|
||||
for (int i = 0; i < call_completed_callbacks_->length(); i++) {
|
||||
if (callback == call_completed_callbacks_->at(i)) {
|
||||
call_completed_callbacks_->Remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void V8::FireCallCompletedCallback(Isolate* isolate) {
|
||||
if (call_completed_callbacks_ == NULL) return;
|
||||
HandleScopeImplementer* handle_scope_implementer =
|
||||
isolate->handle_scope_implementer();
|
||||
if (!handle_scope_implementer->CallDepthIsZero()) return;
|
||||
// Fire callbacks. Increase call depth to prevent recursive callbacks.
|
||||
handle_scope_implementer->IncrementCallDepth();
|
||||
for (int i = 0; i < call_completed_callbacks_->length(); i++) {
|
||||
call_completed_callbacks_->at(i)();
|
||||
}
|
||||
handle_scope_implementer->DecrementCallDepth();
|
||||
}
|
||||
|
||||
|
||||
// Use a union type to avoid type-aliasing optimizations in GCC.
|
||||
typedef union {
|
||||
double double_value;
|
||||
uint64_t uint64_t_value;
|
||||
} double_int_union;
|
||||
|
||||
|
||||
Object* V8::FillHeapNumberWithRandom(Object* heap_number,
|
||||
Context* context) {
|
||||
double_int_union r;
|
||||
uint64_t random_bits = Random(context);
|
||||
// Convert 32 random bits to 0.(32 random bits) in a double
|
||||
// by computing:
|
||||
// ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
|
||||
static const double binary_million = 1048576.0;
|
||||
r.double_value = binary_million;
|
||||
r.uint64_t_value |= random_bits;
|
||||
r.double_value -= binary_million;
|
||||
|
||||
HeapNumber::cast(heap_number)->set_value(r.double_value);
|
||||
return heap_number;
|
||||
}
|
||||
|
||||
void V8::InitializeOncePerProcessImpl() {
|
||||
OS::SetUp();
|
||||
|
||||
use_crankshaft_ = FLAG_crankshaft;
|
||||
|
||||
if (Serializer::enabled()) {
|
||||
use_crankshaft_ = false;
|
||||
}
|
||||
|
||||
CPU::SetUp();
|
||||
if (!CPU::SupportsCrankshaft()) {
|
||||
use_crankshaft_ = false;
|
||||
}
|
||||
|
||||
OS::PostSetUp();
|
||||
|
||||
RuntimeProfiler::GlobalSetUp();
|
||||
|
||||
ElementsAccessor::InitializeOncePerProcess();
|
||||
|
||||
if (FLAG_stress_compaction) {
|
||||
FLAG_force_marking_deque_overflows = true;
|
||||
FLAG_gc_global = true;
|
||||
FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
|
||||
}
|
||||
|
||||
LOperand::SetUpCaches();
|
||||
SetUpJSCallerSavedCodeData();
|
||||
SamplerRegistry::SetUp();
|
||||
ExternalReference::SetUp();
|
||||
}
|
||||
|
||||
void V8::InitializeOncePerProcess() {
|
||||
CallOnce(&init_once, &InitializeOncePerProcessImpl);
|
||||
}
|
||||
|
||||
} } // namespace v8::internal
|
||||
152
samples/C++/v8.h
Normal file
152
samples/C++/v8.h
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Top include for all V8 .cc files.
|
||||
//
|
||||
|
||||
#ifndef V8_V8_H_
|
||||
#define V8_V8_H_
|
||||
|
||||
#if defined(GOOGLE3)
|
||||
// Google3 special flag handling.
|
||||
#if defined(DEBUG) && defined(NDEBUG)
|
||||
// V8 only uses DEBUG and whenever it is set we are building a debug
|
||||
// version of V8. We do not use NDEBUG and simply undef it here for
|
||||
// consistency.
|
||||
#undef NDEBUG
|
||||
#endif
|
||||
#endif // defined(GOOGLE3)
|
||||
|
||||
// V8 only uses DEBUG, but included external files
|
||||
// may use NDEBUG - make sure they are consistent.
|
||||
#if defined(DEBUG) && defined(NDEBUG)
|
||||
#error both DEBUG and NDEBUG are set
|
||||
#endif
|
||||
|
||||
// Basic includes
|
||||
#include "../include/v8.h"
|
||||
#include "v8globals.h"
|
||||
#include "v8checks.h"
|
||||
#include "allocation.h"
|
||||
#include "v8utils.h"
|
||||
#include "flags.h"
|
||||
|
||||
// Objects & heap
|
||||
#include "objects-inl.h"
|
||||
#include "spaces-inl.h"
|
||||
#include "heap-inl.h"
|
||||
#include "incremental-marking-inl.h"
|
||||
#include "mark-compact-inl.h"
|
||||
#include "log-inl.h"
|
||||
#include "cpu-profiler-inl.h"
|
||||
#include "handles-inl.h"
|
||||
#include "zone-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class Deserializer;
|
||||
|
||||
class V8 : public AllStatic {
|
||||
public:
|
||||
// Global actions.
|
||||
|
||||
// If Initialize is called with des == NULL, the initial state is
|
||||
// created from scratch. If a non-null Deserializer is given, the
|
||||
// initial state is created by reading the deserialized data into an
|
||||
// empty heap.
|
||||
static bool Initialize(Deserializer* des);
|
||||
static void TearDown();
|
||||
static bool IsRunning() { return is_running_; }
|
||||
static bool UseCrankshaft() { return use_crankshaft_; }
|
||||
// To be dead you have to have lived
|
||||
// TODO(isolates): move IsDead to Isolate.
|
||||
static bool IsDead() { return has_fatal_error_ || has_been_disposed_; }
|
||||
static void SetFatalError();
|
||||
|
||||
// Report process out of memory. Implementation found in api.cc.
|
||||
static void FatalProcessOutOfMemory(const char* location,
|
||||
bool take_snapshot = false);
|
||||
|
||||
// Allows an entropy source to be provided for use in random number
|
||||
// generation.
|
||||
static void SetEntropySource(EntropySource source);
|
||||
// Support for return-address rewriting profilers.
|
||||
static void SetReturnAddressLocationResolver(
|
||||
ReturnAddressLocationResolver resolver);
|
||||
// Random number generation support. Not cryptographically safe.
|
||||
static uint32_t Random(Context* context);
|
||||
// We use random numbers internally in memory allocation and in the
|
||||
// compilers for security. In order to prevent information leaks we
|
||||
// use a separate random state for internal random number
|
||||
// generation.
|
||||
static uint32_t RandomPrivate(Isolate* isolate);
|
||||
static Object* FillHeapNumberWithRandom(Object* heap_number,
|
||||
Context* context);
|
||||
|
||||
// Idle notification directly from the API.
|
||||
static bool IdleNotification(int hint);
|
||||
|
||||
static void AddCallCompletedCallback(CallCompletedCallback callback);
|
||||
static void RemoveCallCompletedCallback(CallCompletedCallback callback);
|
||||
static void FireCallCompletedCallback(Isolate* isolate);
|
||||
|
||||
private:
|
||||
static void InitializeOncePerProcessImpl();
|
||||
static void InitializeOncePerProcess();
|
||||
|
||||
// True if engine is currently running
|
||||
static bool is_running_;
|
||||
// True if V8 has ever been run
|
||||
static bool has_been_set_up_;
|
||||
// True if error has been signaled for current engine
|
||||
// (reset to false if engine is restarted)
|
||||
static bool has_fatal_error_;
|
||||
// True if engine has been shut down
|
||||
// (reset if engine is restarted)
|
||||
static bool has_been_disposed_;
|
||||
// True if we are using the crankshaft optimizing compiler.
|
||||
static bool use_crankshaft_;
|
||||
// List of callbacks when a Call completes.
|
||||
static List<CallCompletedCallback>* call_completed_callbacks_;
|
||||
};
|
||||
|
||||
|
||||
// JavaScript defines two kinds of 'nil'.
|
||||
enum NilValue { kNullValue, kUndefinedValue };
|
||||
|
||||
|
||||
// JavaScript defines two kinds of equality.
|
||||
enum EqualityKind { kStrictEquality, kNonStrictEquality };
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
namespace i = v8::internal;
|
||||
|
||||
#endif // V8_V8_H_
|
||||
4674
samples/C++/wrapper_inner.cpp
Normal file
4674
samples/C++/wrapper_inner.cpp
Normal file
File diff suppressed because it is too large
Load Diff
25
samples/C/blob.c
Normal file
25
samples/C/blob.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "cache.h"
|
||||
#include "blob.h"
|
||||
|
||||
const char *blob_type = "blob";
|
||||
|
||||
struct blob *lookup_blob(const unsigned char *sha1)
|
||||
{
|
||||
struct object *obj = lookup_object(sha1);
|
||||
if (!obj)
|
||||
return create_object(sha1, OBJ_BLOB, alloc_blob_node());
|
||||
if (!obj->type)
|
||||
obj->type = OBJ_BLOB;
|
||||
if (obj->type != OBJ_BLOB) {
|
||||
error("Object %s is a %s, not a blob",
|
||||
sha1_to_hex(sha1), typename(obj->type));
|
||||
return NULL;
|
||||
}
|
||||
return (struct blob *) obj;
|
||||
}
|
||||
|
||||
int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size)
|
||||
{
|
||||
item->object.parsed = 1;
|
||||
return 0;
|
||||
}
|
||||
25
samples/C/blob.h
Normal file
25
samples/C/blob.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef BLOB_H
|
||||
#define BLOB_H
|
||||
|
||||
#include "object.h"
|
||||
|
||||
extern const char *blob_type;
|
||||
|
||||
struct blob {
|
||||
struct object object;
|
||||
};
|
||||
|
||||
struct blob *lookup_blob(const unsigned char *sha1);
|
||||
|
||||
int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size);
|
||||
|
||||
/**
|
||||
* Blobs do not contain references to other objects and do not have
|
||||
* structured data that needs parsing. However, code may use the
|
||||
* "parsed" bit in the struct object for a blob to determine whether
|
||||
* its content has been found to actually be available, so
|
||||
* parse_blob_buffer() is used (by object.c) to flag that the object
|
||||
* has been read successfully from the database.
|
||||
**/
|
||||
|
||||
#endif /* BLOB_H */
|
||||
99
samples/C/cache.c
Normal file
99
samples/C/cache.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2012 the libgit2 contributors
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "repository.h"
|
||||
#include "commit.h"
|
||||
#include "thread-utils.h"
|
||||
#include "util.h"
|
||||
#include "cache.h"
|
||||
|
||||
int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr)
|
||||
{
|
||||
if (size < 8)
|
||||
size = 8;
|
||||
size = git__size_t_powerof2(size);
|
||||
|
||||
cache->size_mask = size - 1;
|
||||
cache->lru_count = 0;
|
||||
cache->free_obj = free_ptr;
|
||||
|
||||
git_mutex_init(&cache->lock);
|
||||
|
||||
cache->nodes = git__malloc(size * sizeof(git_cached_obj *));
|
||||
GITERR_CHECK_ALLOC(cache->nodes);
|
||||
|
||||
memset(cache->nodes, 0x0, size * sizeof(git_cached_obj *));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_cache_free(git_cache *cache)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < (cache->size_mask + 1); ++i) {
|
||||
if (cache->nodes[i] != NULL)
|
||||
git_cached_obj_decref(cache->nodes[i], cache->free_obj);
|
||||
}
|
||||
|
||||
git__free(cache->nodes);
|
||||
}
|
||||
|
||||
void *git_cache_get(git_cache *cache, const git_oid *oid)
|
||||
{
|
||||
uint32_t hash;
|
||||
git_cached_obj *node = NULL, *result = NULL;
|
||||
|
||||
memcpy(&hash, oid->id, sizeof(hash));
|
||||
|
||||
git_mutex_lock(&cache->lock);
|
||||
{
|
||||
node = cache->nodes[hash & cache->size_mask];
|
||||
|
||||
if (node != NULL && git_oid_cmp(&node->oid, oid) == 0) {
|
||||
git_cached_obj_incref(node);
|
||||
result = node;
|
||||
}
|
||||
}
|
||||
git_mutex_unlock(&cache->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void *git_cache_try_store(git_cache *cache, void *_entry)
|
||||
{
|
||||
git_cached_obj *entry = _entry;
|
||||
uint32_t hash;
|
||||
|
||||
memcpy(&hash, &entry->oid, sizeof(uint32_t));
|
||||
|
||||
/* increase the refcount on this object, because
|
||||
* the cache now owns it */
|
||||
git_cached_obj_incref(entry);
|
||||
|
||||
git_mutex_lock(&cache->lock);
|
||||
{
|
||||
git_cached_obj *node = cache->nodes[hash & cache->size_mask];
|
||||
|
||||
if (node == NULL) {
|
||||
cache->nodes[hash & cache->size_mask] = entry;
|
||||
} else if (git_oid_cmp(&node->oid, &entry->oid) == 0) {
|
||||
git_cached_obj_decref(entry, cache->free_obj);
|
||||
entry = node;
|
||||
} else {
|
||||
git_cached_obj_decref(node, cache->free_obj);
|
||||
cache->nodes[hash & cache->size_mask] = entry;
|
||||
}
|
||||
}
|
||||
git_mutex_unlock(&cache->lock);
|
||||
|
||||
/* increase the refcount again, because we are
|
||||
* returning it to the user */
|
||||
git_cached_obj_incref(entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
1228
samples/C/commit.c
Normal file
1228
samples/C/commit.c
Normal file
File diff suppressed because it is too large
Load Diff
226
samples/C/commit.h
Normal file
226
samples/C/commit.h
Normal file
@@ -0,0 +1,226 @@
|
||||
#ifndef COMMIT_H
|
||||
#define COMMIT_H
|
||||
|
||||
#include "object.h"
|
||||
#include "tree.h"
|
||||
#include "strbuf.h"
|
||||
#include "decorate.h"
|
||||
|
||||
struct commit_list {
|
||||
struct commit *item;
|
||||
struct commit_list *next;
|
||||
};
|
||||
|
||||
struct commit {
|
||||
struct object object;
|
||||
void *util;
|
||||
unsigned int indegree;
|
||||
unsigned long date;
|
||||
struct commit_list *parents;
|
||||
struct tree *tree;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
extern int save_commit_buffer;
|
||||
extern const char *commit_type;
|
||||
|
||||
/* While we can decorate any object with a name, it's only used for commits.. */
|
||||
extern struct decoration name_decoration;
|
||||
struct name_decoration {
|
||||
struct name_decoration *next;
|
||||
int type;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
struct commit *lookup_commit(const unsigned char *sha1);
|
||||
struct commit *lookup_commit_reference(const unsigned char *sha1);
|
||||
struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
|
||||
int quiet);
|
||||
struct commit *lookup_commit_reference_by_name(const char *name);
|
||||
|
||||
/*
|
||||
* Look up object named by "sha1", dereference tag as necessary,
|
||||
* get a commit and return it. If "sha1" does not dereference to
|
||||
* a commit, use ref_name to report an error and die.
|
||||
*/
|
||||
struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name);
|
||||
|
||||
int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
|
||||
int parse_commit(struct commit *item);
|
||||
|
||||
/* Find beginning and length of commit subject. */
|
||||
int find_commit_subject(const char *commit_buffer, const char **subject);
|
||||
|
||||
struct commit_list *commit_list_insert(struct commit *item,
|
||||
struct commit_list **list);
|
||||
struct commit_list **commit_list_append(struct commit *commit,
|
||||
struct commit_list **next);
|
||||
unsigned commit_list_count(const struct commit_list *l);
|
||||
struct commit_list *commit_list_insert_by_date(struct commit *item,
|
||||
struct commit_list **list);
|
||||
void commit_list_sort_by_date(struct commit_list **list);
|
||||
|
||||
void free_commit_list(struct commit_list *list);
|
||||
|
||||
/* Commit formats */
|
||||
enum cmit_fmt {
|
||||
CMIT_FMT_RAW,
|
||||
CMIT_FMT_MEDIUM,
|
||||
CMIT_FMT_DEFAULT = CMIT_FMT_MEDIUM,
|
||||
CMIT_FMT_SHORT,
|
||||
CMIT_FMT_FULL,
|
||||
CMIT_FMT_FULLER,
|
||||
CMIT_FMT_ONELINE,
|
||||
CMIT_FMT_EMAIL,
|
||||
CMIT_FMT_USERFORMAT,
|
||||
|
||||
CMIT_FMT_UNSPECIFIED
|
||||
};
|
||||
|
||||
struct pretty_print_context {
|
||||
enum cmit_fmt fmt;
|
||||
int abbrev;
|
||||
const char *subject;
|
||||
const char *after_subject;
|
||||
int preserve_subject;
|
||||
enum date_mode date_mode;
|
||||
unsigned date_mode_explicit:1;
|
||||
int need_8bit_cte;
|
||||
int show_notes;
|
||||
struct reflog_walk_info *reflog_info;
|
||||
const char *output_encoding;
|
||||
};
|
||||
|
||||
struct userformat_want {
|
||||
unsigned notes:1;
|
||||
};
|
||||
|
||||
extern int has_non_ascii(const char *text);
|
||||
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
|
||||
extern char *logmsg_reencode(const struct commit *commit,
|
||||
const char *output_encoding);
|
||||
extern char *reencode_commit_message(const struct commit *commit,
|
||||
const char **encoding_p);
|
||||
extern void get_commit_format(const char *arg, struct rev_info *);
|
||||
extern const char *format_subject(struct strbuf *sb, const char *msg,
|
||||
const char *line_separator);
|
||||
extern void userformat_find_requirements(const char *fmt, struct userformat_want *w);
|
||||
extern void format_commit_message(const struct commit *commit,
|
||||
const char *format, struct strbuf *sb,
|
||||
const struct pretty_print_context *context);
|
||||
extern void pretty_print_commit(const struct pretty_print_context *pp,
|
||||
const struct commit *commit,
|
||||
struct strbuf *sb);
|
||||
extern void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
|
||||
struct strbuf *sb);
|
||||
void pp_user_info(const struct pretty_print_context *pp,
|
||||
const char *what, struct strbuf *sb,
|
||||
const char *line, const char *encoding);
|
||||
void pp_title_line(const struct pretty_print_context *pp,
|
||||
const char **msg_p,
|
||||
struct strbuf *sb,
|
||||
const char *encoding,
|
||||
int need_8bit_cte);
|
||||
void pp_remainder(const struct pretty_print_context *pp,
|
||||
const char **msg_p,
|
||||
struct strbuf *sb,
|
||||
int indent);
|
||||
|
||||
|
||||
/** Removes the first commit from a list sorted by date, and adds all
|
||||
* of its parents.
|
||||
**/
|
||||
struct commit *pop_most_recent_commit(struct commit_list **list,
|
||||
unsigned int mark);
|
||||
|
||||
struct commit *pop_commit(struct commit_list **stack);
|
||||
|
||||
void clear_commit_marks(struct commit *commit, unsigned int mark);
|
||||
void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark);
|
||||
|
||||
/*
|
||||
* Performs an in-place topological sort of list supplied.
|
||||
*
|
||||
* invariant of resulting list is:
|
||||
* a reachable from b => ord(b) < ord(a)
|
||||
* in addition, when lifo == 0, commits on parallel tracks are
|
||||
* sorted in the dates order.
|
||||
*/
|
||||
void sort_in_topological_order(struct commit_list ** list, int lifo);
|
||||
|
||||
struct commit_graft {
|
||||
unsigned char sha1[20];
|
||||
int nr_parent; /* < 0 if shallow commit */
|
||||
unsigned char parent[FLEX_ARRAY][20]; /* more */
|
||||
};
|
||||
typedef int (*each_commit_graft_fn)(const struct commit_graft *, void *);
|
||||
|
||||
struct commit_graft *read_graft_line(char *buf, int len);
|
||||
int register_commit_graft(struct commit_graft *, int);
|
||||
struct commit_graft *lookup_commit_graft(const unsigned char *sha1);
|
||||
|
||||
extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);
|
||||
extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup);
|
||||
extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
|
||||
|
||||
extern int register_shallow(const unsigned char *sha1);
|
||||
extern int unregister_shallow(const unsigned char *sha1);
|
||||
extern int for_each_commit_graft(each_commit_graft_fn, void *);
|
||||
extern int is_repository_shallow(void);
|
||||
extern struct commit_list *get_shallow_commits(struct object_array *heads,
|
||||
int depth, int shallow_flag, int not_shallow_flag);
|
||||
|
||||
int is_descendant_of(struct commit *, struct commit_list *);
|
||||
int in_merge_bases(struct commit *, struct commit **, int);
|
||||
|
||||
extern int interactive_add(int argc, const char **argv, const char *prefix, int patch);
|
||||
extern int run_add_interactive(const char *revision, const char *patch_mode,
|
||||
const char **pathspec);
|
||||
|
||||
static inline int single_parent(struct commit *commit)
|
||||
{
|
||||
return commit->parents && !commit->parents->next;
|
||||
}
|
||||
|
||||
struct commit_list *reduce_heads(struct commit_list *heads);
|
||||
|
||||
struct commit_extra_header {
|
||||
struct commit_extra_header *next;
|
||||
char *key;
|
||||
char *value;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
extern void append_merge_tag_headers(struct commit_list *parents,
|
||||
struct commit_extra_header ***tail);
|
||||
|
||||
extern int commit_tree(const struct strbuf *msg, unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit);
|
||||
|
||||
extern int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit,
|
||||
struct commit_extra_header *);
|
||||
|
||||
extern struct commit_extra_header *read_commit_extra_headers(struct commit *, const char **);
|
||||
extern struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
|
||||
|
||||
extern void free_commit_extra_headers(struct commit_extra_header *extra);
|
||||
|
||||
struct merge_remote_desc {
|
||||
struct object *obj; /* the named object, could be a tag */
|
||||
const char *name;
|
||||
};
|
||||
#define merge_remote_util(commit) ((struct merge_remote_desc *)((commit)->util))
|
||||
|
||||
/*
|
||||
* Given "name" from the command line to merge, find the commit object
|
||||
* and return it, while storing merge_remote_desc in its ->util field,
|
||||
* to allow callers to tell if we are told to merge a tag.
|
||||
*/
|
||||
struct commit *get_merge_parent(const char *name);
|
||||
|
||||
extern int parse_signed_commit(const unsigned char *sha1,
|
||||
struct strbuf *message, struct strbuf *signature);
|
||||
#endif /* COMMIT_H */
|
||||
725
samples/C/cpu.c
Normal file
725
samples/C/cpu.c
Normal file
@@ -0,0 +1,725 @@
|
||||
/* CPU control.
|
||||
* (C) 2001, 2002, 2003, 2004 Rusty Russell
|
||||
*
|
||||
* This code is licenced under the GPL.
|
||||
*/
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/oom.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/stop_machine.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include "smpboot.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Serializes the updates to cpu_online_mask, cpu_present_mask */
|
||||
static DEFINE_MUTEX(cpu_add_remove_lock);
|
||||
|
||||
/*
|
||||
* The following two API's must be used when attempting
|
||||
* to serialize the updates to cpu_online_mask, cpu_present_mask.
|
||||
*/
|
||||
void cpu_maps_update_begin(void)
|
||||
{
|
||||
mutex_lock(&cpu_add_remove_lock);
|
||||
}
|
||||
|
||||
void cpu_maps_update_done(void)
|
||||
{
|
||||
mutex_unlock(&cpu_add_remove_lock);
|
||||
}
|
||||
|
||||
static RAW_NOTIFIER_HEAD(cpu_chain);
|
||||
|
||||
/* If set, cpu_up and cpu_down will return -EBUSY and do nothing.
|
||||
* Should always be manipulated under cpu_add_remove_lock
|
||||
*/
|
||||
static int cpu_hotplug_disabled;
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
|
||||
static struct {
|
||||
struct task_struct *active_writer;
|
||||
struct mutex lock; /* Synchronizes accesses to refcount, */
|
||||
/*
|
||||
* Also blocks the new readers during
|
||||
* an ongoing cpu hotplug operation.
|
||||
*/
|
||||
int refcount;
|
||||
} cpu_hotplug = {
|
||||
.active_writer = NULL,
|
||||
.lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
|
||||
.refcount = 0,
|
||||
};
|
||||
|
||||
void get_online_cpus(void)
|
||||
{
|
||||
might_sleep();
|
||||
if (cpu_hotplug.active_writer == current)
|
||||
return;
|
||||
mutex_lock(&cpu_hotplug.lock);
|
||||
cpu_hotplug.refcount++;
|
||||
mutex_unlock(&cpu_hotplug.lock);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_online_cpus);
|
||||
|
||||
void put_online_cpus(void)
|
||||
{
|
||||
if (cpu_hotplug.active_writer == current)
|
||||
return;
|
||||
mutex_lock(&cpu_hotplug.lock);
|
||||
if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer))
|
||||
wake_up_process(cpu_hotplug.active_writer);
|
||||
mutex_unlock(&cpu_hotplug.lock);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(put_online_cpus);
|
||||
|
||||
/*
|
||||
* This ensures that the hotplug operation can begin only when the
|
||||
* refcount goes to zero.
|
||||
*
|
||||
* Note that during a cpu-hotplug operation, the new readers, if any,
|
||||
* will be blocked by the cpu_hotplug.lock
|
||||
*
|
||||
* Since cpu_hotplug_begin() is always called after invoking
|
||||
* cpu_maps_update_begin(), we can be sure that only one writer is active.
|
||||
*
|
||||
* Note that theoretically, there is a possibility of a livelock:
|
||||
* - Refcount goes to zero, last reader wakes up the sleeping
|
||||
* writer.
|
||||
* - Last reader unlocks the cpu_hotplug.lock.
|
||||
* - A new reader arrives at this moment, bumps up the refcount.
|
||||
* - The writer acquires the cpu_hotplug.lock finds the refcount
|
||||
* non zero and goes to sleep again.
|
||||
*
|
||||
* However, this is very difficult to achieve in practice since
|
||||
* get_online_cpus() not an api which is called all that often.
|
||||
*
|
||||
*/
|
||||
static void cpu_hotplug_begin(void)
|
||||
{
|
||||
cpu_hotplug.active_writer = current;
|
||||
|
||||
for (;;) {
|
||||
mutex_lock(&cpu_hotplug.lock);
|
||||
if (likely(!cpu_hotplug.refcount))
|
||||
break;
|
||||
__set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
mutex_unlock(&cpu_hotplug.lock);
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_hotplug_done(void)
|
||||
{
|
||||
cpu_hotplug.active_writer = NULL;
|
||||
mutex_unlock(&cpu_hotplug.lock);
|
||||
}
|
||||
|
||||
#else /* #if CONFIG_HOTPLUG_CPU */
|
||||
static void cpu_hotplug_begin(void) {}
|
||||
static void cpu_hotplug_done(void) {}
|
||||
#endif /* #else #if CONFIG_HOTPLUG_CPU */
|
||||
|
||||
/* Need to know about CPUs going up/down? */
|
||||
int __ref register_cpu_notifier(struct notifier_block *nb)
|
||||
{
|
||||
int ret;
|
||||
cpu_maps_update_begin();
|
||||
ret = raw_notifier_chain_register(&cpu_chain, nb);
|
||||
cpu_maps_update_done();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __cpu_notify(unsigned long val, void *v, int nr_to_call,
|
||||
int *nr_calls)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = __raw_notifier_call_chain(&cpu_chain, val, v, nr_to_call,
|
||||
nr_calls);
|
||||
|
||||
return notifier_to_errno(ret);
|
||||
}
|
||||
|
||||
static int cpu_notify(unsigned long val, void *v)
|
||||
{
|
||||
return __cpu_notify(val, v, -1, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
|
||||
static void cpu_notify_nofail(unsigned long val, void *v)
|
||||
{
|
||||
BUG_ON(cpu_notify(val, v));
|
||||
}
|
||||
EXPORT_SYMBOL(register_cpu_notifier);
|
||||
|
||||
void __ref unregister_cpu_notifier(struct notifier_block *nb)
|
||||
{
|
||||
cpu_maps_update_begin();
|
||||
raw_notifier_chain_unregister(&cpu_chain, nb);
|
||||
cpu_maps_update_done();
|
||||
}
|
||||
EXPORT_SYMBOL(unregister_cpu_notifier);
|
||||
|
||||
/**
|
||||
* clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
|
||||
* @cpu: a CPU id
|
||||
*
|
||||
* This function walks all processes, finds a valid mm struct for each one and
|
||||
* then clears a corresponding bit in mm's cpumask. While this all sounds
|
||||
* trivial, there are various non-obvious corner cases, which this function
|
||||
* tries to solve in a safe manner.
|
||||
*
|
||||
* Also note that the function uses a somewhat relaxed locking scheme, so it may
|
||||
* be called only for an already offlined CPU.
|
||||
*/
|
||||
void clear_tasks_mm_cpumask(int cpu)
|
||||
{
|
||||
struct task_struct *p;
|
||||
|
||||
/*
|
||||
* This function is called after the cpu is taken down and marked
|
||||
* offline, so its not like new tasks will ever get this cpu set in
|
||||
* their mm mask. -- Peter Zijlstra
|
||||
* Thus, we may use rcu_read_lock() here, instead of grabbing
|
||||
* full-fledged tasklist_lock.
|
||||
*/
|
||||
WARN_ON(cpu_online(cpu));
|
||||
rcu_read_lock();
|
||||
for_each_process(p) {
|
||||
struct task_struct *t;
|
||||
|
||||
/*
|
||||
* Main thread might exit, but other threads may still have
|
||||
* a valid mm. Find one.
|
||||
*/
|
||||
t = find_lock_task_mm(p);
|
||||
if (!t)
|
||||
continue;
|
||||
cpumask_clear_cpu(cpu, mm_cpumask(t->mm));
|
||||
task_unlock(t);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static inline void check_for_tasks(int cpu)
|
||||
{
|
||||
struct task_struct *p;
|
||||
|
||||
write_lock_irq(&tasklist_lock);
|
||||
for_each_process(p) {
|
||||
if (task_cpu(p) == cpu && p->state == TASK_RUNNING &&
|
||||
(p->utime || p->stime))
|
||||
printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d "
|
||||
"(state = %ld, flags = %x)\n",
|
||||
p->comm, task_pid_nr(p), cpu,
|
||||
p->state, p->flags);
|
||||
}
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
}
|
||||
|
||||
struct take_cpu_down_param {
|
||||
unsigned long mod;
|
||||
void *hcpu;
|
||||
};
|
||||
|
||||
/* Take this CPU down. */
|
||||
static int __ref take_cpu_down(void *_param)
|
||||
{
|
||||
struct take_cpu_down_param *param = _param;
|
||||
int err;
|
||||
|
||||
/* Ensure this CPU doesn't handle any more interrupts. */
|
||||
err = __cpu_disable();
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
cpu_notify(CPU_DYING | param->mod, param->hcpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Requires cpu_add_remove_lock to be held */
|
||||
static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
|
||||
{
|
||||
int err, nr_calls = 0;
|
||||
void *hcpu = (void *)(long)cpu;
|
||||
unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
|
||||
struct take_cpu_down_param tcd_param = {
|
||||
.mod = mod,
|
||||
.hcpu = hcpu,
|
||||
};
|
||||
|
||||
if (num_online_cpus() == 1)
|
||||
return -EBUSY;
|
||||
|
||||
if (!cpu_online(cpu))
|
||||
return -EINVAL;
|
||||
|
||||
cpu_hotplug_begin();
|
||||
|
||||
err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls);
|
||||
if (err) {
|
||||
nr_calls--;
|
||||
__cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL);
|
||||
printk("%s: attempt to take down CPU %u failed\n",
|
||||
__func__, cpu);
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
|
||||
if (err) {
|
||||
/* CPU didn't die: tell everyone. Can't complain. */
|
||||
cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu);
|
||||
|
||||
goto out_release;
|
||||
}
|
||||
BUG_ON(cpu_online(cpu));
|
||||
|
||||
/*
|
||||
* The migration_call() CPU_DYING callback will have removed all
|
||||
* runnable tasks from the cpu, there's only the idle task left now
|
||||
* that the migration thread is done doing the stop_machine thing.
|
||||
*
|
||||
* Wait for the stop thread to go away.
|
||||
*/
|
||||
while (!idle_cpu(cpu))
|
||||
cpu_relax();
|
||||
|
||||
/* This actually kills the CPU. */
|
||||
__cpu_die(cpu);
|
||||
|
||||
/* CPU is completely dead: tell everyone. Too late to complain. */
|
||||
cpu_notify_nofail(CPU_DEAD | mod, hcpu);
|
||||
|
||||
check_for_tasks(cpu);
|
||||
|
||||
out_release:
|
||||
cpu_hotplug_done();
|
||||
if (!err)
|
||||
cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu);
|
||||
return err;
|
||||
}
|
||||
|
||||
int __ref cpu_down(unsigned int cpu)
|
||||
{
|
||||
int err;
|
||||
|
||||
cpu_maps_update_begin();
|
||||
|
||||
if (cpu_hotplug_disabled) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = _cpu_down(cpu, 0);
|
||||
|
||||
out:
|
||||
cpu_maps_update_done();
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(cpu_down);
|
||||
#endif /*CONFIG_HOTPLUG_CPU*/
|
||||
|
||||
/* Requires cpu_add_remove_lock to be held */
|
||||
static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
|
||||
{
|
||||
int ret, nr_calls = 0;
|
||||
void *hcpu = (void *)(long)cpu;
|
||||
unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
|
||||
struct task_struct *idle;
|
||||
|
||||
if (cpu_online(cpu) || !cpu_present(cpu))
|
||||
return -EINVAL;
|
||||
|
||||
cpu_hotplug_begin();
|
||||
|
||||
idle = idle_thread_get(cpu);
|
||||
if (IS_ERR(idle)) {
|
||||
ret = PTR_ERR(idle);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls);
|
||||
if (ret) {
|
||||
nr_calls--;
|
||||
printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n",
|
||||
__func__, cpu);
|
||||
goto out_notify;
|
||||
}
|
||||
|
||||
/* Arch-specific enabling code. */
|
||||
ret = __cpu_up(cpu, idle);
|
||||
if (ret != 0)
|
||||
goto out_notify;
|
||||
BUG_ON(!cpu_online(cpu));
|
||||
|
||||
/* Now call notifier in preparation. */
|
||||
cpu_notify(CPU_ONLINE | mod, hcpu);
|
||||
|
||||
out_notify:
|
||||
if (ret != 0)
|
||||
__cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);
|
||||
out:
|
||||
cpu_hotplug_done();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __cpuinit cpu_up(unsigned int cpu)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
int nid;
|
||||
pg_data_t *pgdat;
|
||||
#endif
|
||||
|
||||
if (!cpu_possible(cpu)) {
|
||||
printk(KERN_ERR "can't online cpu %d because it is not "
|
||||
"configured as may-hotadd at boot time\n", cpu);
|
||||
#if defined(CONFIG_IA64)
|
||||
printk(KERN_ERR "please check additional_cpus= boot "
|
||||
"parameter\n");
|
||||
#endif
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
nid = cpu_to_node(cpu);
|
||||
if (!node_online(nid)) {
|
||||
err = mem_online_node(nid);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
pgdat = NODE_DATA(nid);
|
||||
if (!pgdat) {
|
||||
printk(KERN_ERR
|
||||
"Can't online cpu %d due to NULL pgdat\n", cpu);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (pgdat->node_zonelists->_zonerefs->zone == NULL) {
|
||||
mutex_lock(&zonelists_mutex);
|
||||
build_all_zonelists(NULL);
|
||||
mutex_unlock(&zonelists_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
cpu_maps_update_begin();
|
||||
|
||||
if (cpu_hotplug_disabled) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = _cpu_up(cpu, 0);
|
||||
|
||||
out:
|
||||
cpu_maps_update_done();
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpu_up);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP_SMP
|
||||
static cpumask_var_t frozen_cpus;
|
||||
|
||||
void __weak arch_disable_nonboot_cpus_begin(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __weak arch_disable_nonboot_cpus_end(void)
|
||||
{
|
||||
}
|
||||
|
||||
int disable_nonboot_cpus(void)
|
||||
{
|
||||
int cpu, first_cpu, error = 0;
|
||||
|
||||
cpu_maps_update_begin();
|
||||
first_cpu = cpumask_first(cpu_online_mask);
|
||||
/*
|
||||
* We take down all of the non-boot CPUs in one shot to avoid races
|
||||
* with the userspace trying to use the CPU hotplug at the same time
|
||||
*/
|
||||
cpumask_clear(frozen_cpus);
|
||||
arch_disable_nonboot_cpus_begin();
|
||||
|
||||
printk("Disabling non-boot CPUs ...\n");
|
||||
for_each_online_cpu(cpu) {
|
||||
if (cpu == first_cpu)
|
||||
continue;
|
||||
error = _cpu_down(cpu, 1);
|
||||
if (!error)
|
||||
cpumask_set_cpu(cpu, frozen_cpus);
|
||||
else {
|
||||
printk(KERN_ERR "Error taking CPU%d down: %d\n",
|
||||
cpu, error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
arch_disable_nonboot_cpus_end();
|
||||
|
||||
if (!error) {
|
||||
BUG_ON(num_online_cpus() > 1);
|
||||
/* Make sure the CPUs won't be enabled by someone else */
|
||||
cpu_hotplug_disabled = 1;
|
||||
} else {
|
||||
printk(KERN_ERR "Non-boot CPUs are not disabled\n");
|
||||
}
|
||||
cpu_maps_update_done();
|
||||
return error;
|
||||
}
|
||||
|
||||
void __weak arch_enable_nonboot_cpus_begin(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __weak arch_enable_nonboot_cpus_end(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __ref enable_nonboot_cpus(void)
|
||||
{
|
||||
int cpu, error;
|
||||
|
||||
/* Allow everyone to use the CPU hotplug again */
|
||||
cpu_maps_update_begin();
|
||||
cpu_hotplug_disabled = 0;
|
||||
if (cpumask_empty(frozen_cpus))
|
||||
goto out;
|
||||
|
||||
printk(KERN_INFO "Enabling non-boot CPUs ...\n");
|
||||
|
||||
arch_enable_nonboot_cpus_begin();
|
||||
|
||||
for_each_cpu(cpu, frozen_cpus) {
|
||||
error = _cpu_up(cpu, 1);
|
||||
if (!error) {
|
||||
printk(KERN_INFO "CPU%d is up\n", cpu);
|
||||
continue;
|
||||
}
|
||||
printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error);
|
||||
}
|
||||
|
||||
arch_enable_nonboot_cpus_end();
|
||||
|
||||
cpumask_clear(frozen_cpus);
|
||||
out:
|
||||
cpu_maps_update_done();
|
||||
}
|
||||
|
||||
static int __init alloc_frozen_cpus(void)
|
||||
{
|
||||
if (!alloc_cpumask_var(&frozen_cpus, GFP_KERNEL|__GFP_ZERO))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
core_initcall(alloc_frozen_cpus);
|
||||
|
||||
/*
|
||||
* Prevent regular CPU hotplug from racing with the freezer, by disabling CPU
|
||||
* hotplug when tasks are about to be frozen. Also, don't allow the freezer
|
||||
* to continue until any currently running CPU hotplug operation gets
|
||||
* completed.
|
||||
* To modify the 'cpu_hotplug_disabled' flag, we need to acquire the
|
||||
* 'cpu_add_remove_lock'. And this same lock is also taken by the regular
|
||||
* CPU hotplug path and released only after it is complete. Thus, we
|
||||
* (and hence the freezer) will block here until any currently running CPU
|
||||
* hotplug operation gets completed.
|
||||
*/
|
||||
void cpu_hotplug_disable_before_freeze(void)
|
||||
{
|
||||
cpu_maps_update_begin();
|
||||
cpu_hotplug_disabled = 1;
|
||||
cpu_maps_update_done();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When tasks have been thawed, re-enable regular CPU hotplug (which had been
|
||||
* disabled while beginning to freeze tasks).
|
||||
*/
|
||||
void cpu_hotplug_enable_after_thaw(void)
|
||||
{
|
||||
cpu_maps_update_begin();
|
||||
cpu_hotplug_disabled = 0;
|
||||
cpu_maps_update_done();
|
||||
}
|
||||
|
||||
/*
|
||||
* When callbacks for CPU hotplug notifications are being executed, we must
|
||||
* ensure that the state of the system with respect to the tasks being frozen
|
||||
* or not, as reported by the notification, remains unchanged *throughout the
|
||||
* duration* of the execution of the callbacks.
|
||||
* Hence we need to prevent the freezer from racing with regular CPU hotplug.
|
||||
*
|
||||
* This synchronization is implemented by mutually excluding regular CPU
|
||||
* hotplug and Suspend/Hibernate call paths by hooking onto the Suspend/
|
||||
* Hibernate notifications.
|
||||
*/
|
||||
static int
|
||||
cpu_hotplug_pm_callback(struct notifier_block *nb,
|
||||
unsigned long action, void *ptr)
|
||||
{
|
||||
switch (action) {
|
||||
|
||||
case PM_SUSPEND_PREPARE:
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
cpu_hotplug_disable_before_freeze();
|
||||
break;
|
||||
|
||||
case PM_POST_SUSPEND:
|
||||
case PM_POST_HIBERNATION:
|
||||
cpu_hotplug_enable_after_thaw();
|
||||
break;
|
||||
|
||||
default:
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
|
||||
static int __init cpu_hotplug_pm_sync_init(void)
|
||||
{
|
||||
pm_notifier(cpu_hotplug_pm_callback, 0);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(cpu_hotplug_pm_sync_init);
|
||||
|
||||
#endif /* CONFIG_PM_SLEEP_SMP */
|
||||
|
||||
/**
|
||||
* notify_cpu_starting(cpu) - call the CPU_STARTING notifiers
|
||||
* @cpu: cpu that just started
|
||||
*
|
||||
* This function calls the cpu_chain notifiers with CPU_STARTING.
|
||||
* It must be called by the arch code on the new cpu, before the new cpu
|
||||
* enables interrupts and before the "boot" cpu returns from __cpu_up().
|
||||
*/
|
||||
void __cpuinit notify_cpu_starting(unsigned int cpu)
|
||||
{
|
||||
unsigned long val = CPU_STARTING;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP_SMP
|
||||
if (frozen_cpus != NULL && cpumask_test_cpu(cpu, frozen_cpus))
|
||||
val = CPU_STARTING_FROZEN;
|
||||
#endif /* CONFIG_PM_SLEEP_SMP */
|
||||
cpu_notify(val, (void *)(long)cpu);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/*
|
||||
* cpu_bit_bitmap[] is a special, "compressed" data structure that
|
||||
* represents all NR_CPUS bits binary values of 1<<nr.
|
||||
*
|
||||
* It is used by cpumask_of() to get a constant address to a CPU
|
||||
* mask value that has a single bit set only.
|
||||
*/
|
||||
|
||||
/* cpu_bit_bitmap[0] is empty - so we can back into it */
|
||||
#define MASK_DECLARE_1(x) [x+1][0] = (1UL << (x))
|
||||
#define MASK_DECLARE_2(x) MASK_DECLARE_1(x), MASK_DECLARE_1(x+1)
|
||||
#define MASK_DECLARE_4(x) MASK_DECLARE_2(x), MASK_DECLARE_2(x+2)
|
||||
#define MASK_DECLARE_8(x) MASK_DECLARE_4(x), MASK_DECLARE_4(x+4)
|
||||
|
||||
const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {
|
||||
|
||||
MASK_DECLARE_8(0), MASK_DECLARE_8(8),
|
||||
MASK_DECLARE_8(16), MASK_DECLARE_8(24),
|
||||
#if BITS_PER_LONG > 32
|
||||
MASK_DECLARE_8(32), MASK_DECLARE_8(40),
|
||||
MASK_DECLARE_8(48), MASK_DECLARE_8(56),
|
||||
#endif
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cpu_bit_bitmap);
|
||||
|
||||
const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL;
|
||||
EXPORT_SYMBOL(cpu_all_bits);
|
||||
|
||||
#ifdef CONFIG_INIT_ALL_POSSIBLE
|
||||
static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly
|
||||
= CPU_BITS_ALL;
|
||||
#else
|
||||
static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly;
|
||||
#endif
|
||||
const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
|
||||
EXPORT_SYMBOL(cpu_possible_mask);
|
||||
|
||||
static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly;
|
||||
const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);
|
||||
EXPORT_SYMBOL(cpu_online_mask);
|
||||
|
||||
static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly;
|
||||
const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits);
|
||||
EXPORT_SYMBOL(cpu_present_mask);
|
||||
|
||||
static DECLARE_BITMAP(cpu_active_bits, CONFIG_NR_CPUS) __read_mostly;
|
||||
const struct cpumask *const cpu_active_mask = to_cpumask(cpu_active_bits);
|
||||
EXPORT_SYMBOL(cpu_active_mask);
|
||||
|
||||
void set_cpu_possible(unsigned int cpu, bool possible)
|
||||
{
|
||||
if (possible)
|
||||
cpumask_set_cpu(cpu, to_cpumask(cpu_possible_bits));
|
||||
else
|
||||
cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits));
|
||||
}
|
||||
|
||||
void set_cpu_present(unsigned int cpu, bool present)
|
||||
{
|
||||
if (present)
|
||||
cpumask_set_cpu(cpu, to_cpumask(cpu_present_bits));
|
||||
else
|
||||
cpumask_clear_cpu(cpu, to_cpumask(cpu_present_bits));
|
||||
}
|
||||
|
||||
void set_cpu_online(unsigned int cpu, bool online)
|
||||
{
|
||||
if (online)
|
||||
cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
|
||||
else
|
||||
cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
|
||||
}
|
||||
|
||||
void set_cpu_active(unsigned int cpu, bool active)
|
||||
{
|
||||
if (active)
|
||||
cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits));
|
||||
else
|
||||
cpumask_clear_cpu(cpu, to_cpumask(cpu_active_bits));
|
||||
}
|
||||
|
||||
void init_cpu_present(const struct cpumask *src)
|
||||
{
|
||||
cpumask_copy(to_cpumask(cpu_present_bits), src);
|
||||
}
|
||||
|
||||
void init_cpu_possible(const struct cpumask *src)
|
||||
{
|
||||
cpumask_copy(to_cpumask(cpu_possible_bits), src);
|
||||
}
|
||||
|
||||
void init_cpu_online(const struct cpumask *src)
|
||||
{
|
||||
cpumask_copy(to_cpumask(cpu_online_bits), src);
|
||||
}
|
||||
784
samples/C/diff.c
Normal file
784
samples/C/diff.c
Normal file
@@ -0,0 +1,784 @@
|
||||
/*
|
||||
* Copyright (C) 2012 the libgit2 contributors
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "git2/diff.h"
|
||||
#include "diff.h"
|
||||
#include "fileops.h"
|
||||
#include "config.h"
|
||||
#include "attr_file.h"
|
||||
|
||||
static char *diff_prefix_from_pathspec(const git_strarray *pathspec)
|
||||
{
|
||||
git_buf prefix = GIT_BUF_INIT;
|
||||
const char *scan;
|
||||
|
||||
if (git_buf_common_prefix(&prefix, pathspec) < 0)
|
||||
return NULL;
|
||||
|
||||
/* diff prefix will only be leading non-wildcards */
|
||||
for (scan = prefix.ptr; *scan && !git__iswildcard(*scan); ++scan);
|
||||
git_buf_truncate(&prefix, scan - prefix.ptr);
|
||||
|
||||
if (prefix.size > 0)
|
||||
return git_buf_detach(&prefix);
|
||||
|
||||
git_buf_free(&prefix);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool diff_pathspec_is_interesting(const git_strarray *pathspec)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
if (pathspec == NULL || pathspec->count == 0)
|
||||
return false;
|
||||
if (pathspec->count > 1)
|
||||
return true;
|
||||
|
||||
str = pathspec->strings[0];
|
||||
if (!str || !str[0] || (!str[1] && (str[0] == '*' || str[0] == '.')))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool diff_path_matches_pathspec(git_diff_list *diff, const char *path)
|
||||
{
|
||||
unsigned int i;
|
||||
git_attr_fnmatch *match;
|
||||
|
||||
if (!diff->pathspec.length)
|
||||
return true;
|
||||
|
||||
git_vector_foreach(&diff->pathspec, i, match) {
|
||||
int result = p_fnmatch(match->pattern, path, 0);
|
||||
|
||||
/* if we didn't match, look for exact dirname prefix match */
|
||||
if (result == FNM_NOMATCH &&
|
||||
(match->flags & GIT_ATTR_FNMATCH_HASWILD) == 0 &&
|
||||
strncmp(path, match->pattern, match->length) == 0 &&
|
||||
path[match->length] == '/')
|
||||
result = 0;
|
||||
|
||||
if (result == 0)
|
||||
return (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) ? false : true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static git_diff_delta *diff_delta__alloc(
|
||||
git_diff_list *diff,
|
||||
git_delta_t status,
|
||||
const char *path)
|
||||
{
|
||||
git_diff_delta *delta = git__calloc(1, sizeof(git_diff_delta));
|
||||
if (!delta)
|
||||
return NULL;
|
||||
|
||||
delta->old_file.path = git_pool_strdup(&diff->pool, path);
|
||||
if (delta->old_file.path == NULL) {
|
||||
git__free(delta);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
delta->new_file.path = delta->old_file.path;
|
||||
|
||||
if (diff->opts.flags & GIT_DIFF_REVERSE) {
|
||||
switch (status) {
|
||||
case GIT_DELTA_ADDED: status = GIT_DELTA_DELETED; break;
|
||||
case GIT_DELTA_DELETED: status = GIT_DELTA_ADDED; break;
|
||||
default: break; /* leave other status values alone */
|
||||
}
|
||||
}
|
||||
delta->status = status;
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
static git_diff_delta *diff_delta__dup(
|
||||
const git_diff_delta *d, git_pool *pool)
|
||||
{
|
||||
git_diff_delta *delta = git__malloc(sizeof(git_diff_delta));
|
||||
if (!delta)
|
||||
return NULL;
|
||||
|
||||
memcpy(delta, d, sizeof(git_diff_delta));
|
||||
|
||||
delta->old_file.path = git_pool_strdup(pool, d->old_file.path);
|
||||
if (delta->old_file.path == NULL)
|
||||
goto fail;
|
||||
|
||||
if (d->new_file.path != d->old_file.path) {
|
||||
delta->new_file.path = git_pool_strdup(pool, d->new_file.path);
|
||||
if (delta->new_file.path == NULL)
|
||||
goto fail;
|
||||
} else {
|
||||
delta->new_file.path = delta->old_file.path;
|
||||
}
|
||||
|
||||
return delta;
|
||||
|
||||
fail:
|
||||
git__free(delta);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static git_diff_delta *diff_delta__merge_like_cgit(
|
||||
const git_diff_delta *a, const git_diff_delta *b, git_pool *pool)
|
||||
{
|
||||
git_diff_delta *dup = diff_delta__dup(a, pool);
|
||||
if (!dup)
|
||||
return NULL;
|
||||
|
||||
if (git_oid_cmp(&dup->new_file.oid, &b->new_file.oid) == 0)
|
||||
return dup;
|
||||
|
||||
git_oid_cpy(&dup->new_file.oid, &b->new_file.oid);
|
||||
|
||||
dup->new_file.mode = b->new_file.mode;
|
||||
dup->new_file.size = b->new_file.size;
|
||||
dup->new_file.flags = b->new_file.flags;
|
||||
|
||||
/* Emulate C git for merging two diffs (a la 'git diff <sha>').
|
||||
*
|
||||
* When C git does a diff between the work dir and a tree, it actually
|
||||
* diffs with the index but uses the workdir contents. This emulates
|
||||
* those choices so we can emulate the type of diff.
|
||||
*/
|
||||
if (git_oid_cmp(&dup->old_file.oid, &dup->new_file.oid) == 0) {
|
||||
if (dup->status == GIT_DELTA_DELETED)
|
||||
/* preserve pending delete info */;
|
||||
else if (b->status == GIT_DELTA_UNTRACKED ||
|
||||
b->status == GIT_DELTA_IGNORED)
|
||||
dup->status = b->status;
|
||||
else
|
||||
dup->status = GIT_DELTA_UNMODIFIED;
|
||||
}
|
||||
else if (dup->status == GIT_DELTA_UNMODIFIED ||
|
||||
b->status == GIT_DELTA_DELETED)
|
||||
dup->status = b->status;
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
static int diff_delta__from_one(
|
||||
git_diff_list *diff,
|
||||
git_delta_t status,
|
||||
const git_index_entry *entry)
|
||||
{
|
||||
git_diff_delta *delta;
|
||||
|
||||
if (status == GIT_DELTA_IGNORED &&
|
||||
(diff->opts.flags & GIT_DIFF_INCLUDE_IGNORED) == 0)
|
||||
return 0;
|
||||
|
||||
if (status == GIT_DELTA_UNTRACKED &&
|
||||
(diff->opts.flags & GIT_DIFF_INCLUDE_UNTRACKED) == 0)
|
||||
return 0;
|
||||
|
||||
if (!diff_path_matches_pathspec(diff, entry->path))
|
||||
return 0;
|
||||
|
||||
delta = diff_delta__alloc(diff, status, entry->path);
|
||||
GITERR_CHECK_ALLOC(delta);
|
||||
|
||||
/* This fn is just for single-sided diffs */
|
||||
assert(status != GIT_DELTA_MODIFIED);
|
||||
|
||||
if (delta->status == GIT_DELTA_DELETED) {
|
||||
delta->old_file.mode = entry->mode;
|
||||
delta->old_file.size = entry->file_size;
|
||||
git_oid_cpy(&delta->old_file.oid, &entry->oid);
|
||||
} else /* ADDED, IGNORED, UNTRACKED */ {
|
||||
delta->new_file.mode = entry->mode;
|
||||
delta->new_file.size = entry->file_size;
|
||||
git_oid_cpy(&delta->new_file.oid, &entry->oid);
|
||||
}
|
||||
|
||||
delta->old_file.flags |= GIT_DIFF_FILE_VALID_OID;
|
||||
delta->new_file.flags |= GIT_DIFF_FILE_VALID_OID;
|
||||
|
||||
if (git_vector_insert(&diff->deltas, delta) < 0) {
|
||||
git__free(delta);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int diff_delta__from_two(
|
||||
git_diff_list *diff,
|
||||
git_delta_t status,
|
||||
const git_index_entry *old_entry,
|
||||
const git_index_entry *new_entry,
|
||||
git_oid *new_oid)
|
||||
{
|
||||
git_diff_delta *delta;
|
||||
|
||||
if (status == GIT_DELTA_UNMODIFIED &&
|
||||
(diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0)
|
||||
return 0;
|
||||
|
||||
if ((diff->opts.flags & GIT_DIFF_REVERSE) != 0) {
|
||||
const git_index_entry *temp = old_entry;
|
||||
old_entry = new_entry;
|
||||
new_entry = temp;
|
||||
}
|
||||
|
||||
delta = diff_delta__alloc(diff, status, old_entry->path);
|
||||
GITERR_CHECK_ALLOC(delta);
|
||||
|
||||
delta->old_file.mode = old_entry->mode;
|
||||
git_oid_cpy(&delta->old_file.oid, &old_entry->oid);
|
||||
delta->old_file.flags |= GIT_DIFF_FILE_VALID_OID;
|
||||
|
||||
delta->new_file.mode = new_entry->mode;
|
||||
git_oid_cpy(&delta->new_file.oid, new_oid ? new_oid : &new_entry->oid);
|
||||
if (new_oid || !git_oid_iszero(&new_entry->oid))
|
||||
delta->new_file.flags |= GIT_DIFF_FILE_VALID_OID;
|
||||
|
||||
if (git_vector_insert(&diff->deltas, delta) < 0) {
|
||||
git__free(delta);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *diff_strdup_prefix(git_pool *pool, const char *prefix)
|
||||
{
|
||||
size_t len = strlen(prefix);
|
||||
|
||||
/* append '/' at end if needed */
|
||||
if (len > 0 && prefix[len - 1] != '/')
|
||||
return git_pool_strcat(pool, prefix, "/");
|
||||
else
|
||||
return git_pool_strndup(pool, prefix, len + 1);
|
||||
}
|
||||
|
||||
static int diff_delta__cmp(const void *a, const void *b)
|
||||
{
|
||||
const git_diff_delta *da = a, *db = b;
|
||||
int val = strcmp(da->old_file.path, db->old_file.path);
|
||||
return val ? val : ((int)da->status - (int)db->status);
|
||||
}
|
||||
|
||||
static int config_bool(git_config *cfg, const char *name, int defvalue)
|
||||
{
|
||||
int val = defvalue;
|
||||
|
||||
if (git_config_get_bool(&val, cfg, name) < 0)
|
||||
giterr_clear();
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static git_diff_list *git_diff_list_alloc(
|
||||
git_repository *repo, const git_diff_options *opts)
|
||||
{
|
||||
git_config *cfg;
|
||||
size_t i;
|
||||
git_diff_list *diff = git__calloc(1, sizeof(git_diff_list));
|
||||
if (diff == NULL)
|
||||
return NULL;
|
||||
|
||||
diff->repo = repo;
|
||||
|
||||
if (git_vector_init(&diff->deltas, 0, diff_delta__cmp) < 0 ||
|
||||
git_pool_init(&diff->pool, 1, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
/* load config values that affect diff behavior */
|
||||
if (git_repository_config__weakptr(&cfg, repo) < 0)
|
||||
goto fail;
|
||||
if (config_bool(cfg, "core.symlinks", 1))
|
||||
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_HAS_SYMLINKS;
|
||||
if (config_bool(cfg, "core.ignorestat", 0))
|
||||
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_ASSUME_UNCHANGED;
|
||||
if (config_bool(cfg, "core.filemode", 1))
|
||||
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_EXEC_BIT;
|
||||
if (config_bool(cfg, "core.trustctime", 1))
|
||||
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_CTIME;
|
||||
/* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */
|
||||
|
||||
if (opts == NULL)
|
||||
return diff;
|
||||
|
||||
memcpy(&diff->opts, opts, sizeof(git_diff_options));
|
||||
memset(&diff->opts.pathspec, 0, sizeof(diff->opts.pathspec));
|
||||
|
||||
diff->opts.old_prefix = diff_strdup_prefix(&diff->pool,
|
||||
opts->old_prefix ? opts->old_prefix : DIFF_OLD_PREFIX_DEFAULT);
|
||||
diff->opts.new_prefix = diff_strdup_prefix(&diff->pool,
|
||||
opts->new_prefix ? opts->new_prefix : DIFF_NEW_PREFIX_DEFAULT);
|
||||
|
||||
if (!diff->opts.old_prefix || !diff->opts.new_prefix)
|
||||
goto fail;
|
||||
|
||||
if (diff->opts.flags & GIT_DIFF_REVERSE) {
|
||||
char *swap = diff->opts.old_prefix;
|
||||
diff->opts.old_prefix = diff->opts.new_prefix;
|
||||
diff->opts.new_prefix = swap;
|
||||
}
|
||||
|
||||
/* only copy pathspec if it is "interesting" so we can test
|
||||
* diff->pathspec.length > 0 to know if it is worth calling
|
||||
* fnmatch as we iterate.
|
||||
*/
|
||||
if (!diff_pathspec_is_interesting(&opts->pathspec))
|
||||
return diff;
|
||||
|
||||
if (git_vector_init(
|
||||
&diff->pathspec, (unsigned int)opts->pathspec.count, NULL) < 0)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < opts->pathspec.count; ++i) {
|
||||
int ret;
|
||||
const char *pattern = opts->pathspec.strings[i];
|
||||
git_attr_fnmatch *match = git__calloc(1, sizeof(git_attr_fnmatch));
|
||||
if (!match)
|
||||
goto fail;
|
||||
match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE;
|
||||
ret = git_attr_fnmatch__parse(match, &diff->pool, NULL, &pattern);
|
||||
if (ret == GIT_ENOTFOUND) {
|
||||
git__free(match);
|
||||
continue;
|
||||
} else if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
if (git_vector_insert(&diff->pathspec, match) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return diff;
|
||||
|
||||
fail:
|
||||
git_diff_list_free(diff);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void git_diff_list_free(git_diff_list *diff)
|
||||
{
|
||||
git_diff_delta *delta;
|
||||
git_attr_fnmatch *match;
|
||||
unsigned int i;
|
||||
|
||||
if (!diff)
|
||||
return;
|
||||
|
||||
git_vector_foreach(&diff->deltas, i, delta) {
|
||||
git__free(delta);
|
||||
diff->deltas.contents[i] = NULL;
|
||||
}
|
||||
git_vector_free(&diff->deltas);
|
||||
|
||||
git_vector_foreach(&diff->pathspec, i, match) {
|
||||
git__free(match);
|
||||
diff->pathspec.contents[i] = NULL;
|
||||
}
|
||||
git_vector_free(&diff->pathspec);
|
||||
|
||||
git_pool_clear(&diff->pool);
|
||||
git__free(diff);
|
||||
}
|
||||
|
||||
static int oid_for_workdir_item(
|
||||
git_repository *repo,
|
||||
const git_index_entry *item,
|
||||
git_oid *oid)
|
||||
{
|
||||
int result;
|
||||
git_buf full_path = GIT_BUF_INIT;
|
||||
|
||||
if (git_buf_joinpath(&full_path, git_repository_workdir(repo), item->path) < 0)
|
||||
return -1;
|
||||
|
||||
/* calculate OID for file if possible*/
|
||||
if (S_ISLNK(item->mode))
|
||||
result = git_odb__hashlink(oid, full_path.ptr);
|
||||
else if (!git__is_sizet(item->file_size)) {
|
||||
giterr_set(GITERR_OS, "File size overflow for 32-bit systems");
|
||||
result = -1;
|
||||
} else {
|
||||
int fd = git_futils_open_ro(full_path.ptr);
|
||||
if (fd < 0)
|
||||
result = fd;
|
||||
else {
|
||||
result = git_odb__hashfd(
|
||||
oid, fd, (size_t)item->file_size, GIT_OBJ_BLOB);
|
||||
p_close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
git_buf_free(&full_path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define EXEC_BIT_MASK 0000111
|
||||
|
||||
static int maybe_modified(
|
||||
git_iterator *old_iter,
|
||||
const git_index_entry *oitem,
|
||||
git_iterator *new_iter,
|
||||
const git_index_entry *nitem,
|
||||
git_diff_list *diff)
|
||||
{
|
||||
git_oid noid, *use_noid = NULL;
|
||||
git_delta_t status = GIT_DELTA_MODIFIED;
|
||||
unsigned int omode = oitem->mode;
|
||||
unsigned int nmode = nitem->mode;
|
||||
|
||||
GIT_UNUSED(old_iter);
|
||||
|
||||
if (!diff_path_matches_pathspec(diff, oitem->path))
|
||||
return 0;
|
||||
|
||||
/* on platforms with no symlinks, promote plain files to symlinks */
|
||||
if (S_ISLNK(omode) && S_ISREG(nmode) &&
|
||||
!(diff->diffcaps & GIT_DIFFCAPS_HAS_SYMLINKS))
|
||||
nmode = GIT_MODE_TYPE(omode) | (nmode & GIT_MODE_PERMS_MASK);
|
||||
|
||||
/* on platforms with no execmode, clear exec bit from comparisons */
|
||||
if (!(diff->diffcaps & GIT_DIFFCAPS_TRUST_EXEC_BIT)) {
|
||||
omode = omode & ~EXEC_BIT_MASK;
|
||||
nmode = nmode & ~EXEC_BIT_MASK;
|
||||
}
|
||||
|
||||
/* support "assume unchanged" (badly, b/c we still stat everything) */
|
||||
if ((diff->diffcaps & GIT_DIFFCAPS_ASSUME_UNCHANGED) != 0)
|
||||
status = (oitem->flags_extended & GIT_IDXENTRY_INTENT_TO_ADD) ?
|
||||
GIT_DELTA_MODIFIED : GIT_DELTA_UNMODIFIED;
|
||||
|
||||
/* support "skip worktree" index bit */
|
||||
else if ((oitem->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE) != 0)
|
||||
status = GIT_DELTA_UNMODIFIED;
|
||||
|
||||
/* if basic type of file changed, then split into delete and add */
|
||||
else if (GIT_MODE_TYPE(omode) != GIT_MODE_TYPE(nmode)) {
|
||||
if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 ||
|
||||
diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if oids and modes match, then file is unmodified */
|
||||
else if (git_oid_cmp(&oitem->oid, &nitem->oid) == 0 &&
|
||||
omode == nmode)
|
||||
status = GIT_DELTA_UNMODIFIED;
|
||||
|
||||
/* if we have a workdir item with an unknown oid, check deeper */
|
||||
else if (git_oid_iszero(&nitem->oid) && new_iter->type == GIT_ITERATOR_WORKDIR) {
|
||||
/* TODO: add check against index file st_mtime to avoid racy-git */
|
||||
|
||||
/* if they files look exactly alike, then we'll assume the same */
|
||||
if (oitem->file_size == nitem->file_size &&
|
||||
(!(diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) ||
|
||||
(oitem->ctime.seconds == nitem->ctime.seconds)) &&
|
||||
oitem->mtime.seconds == nitem->mtime.seconds &&
|
||||
(!(diff->diffcaps & GIT_DIFFCAPS_USE_DEV) ||
|
||||
(oitem->dev == nitem->dev)) &&
|
||||
oitem->ino == nitem->ino &&
|
||||
oitem->uid == nitem->uid &&
|
||||
oitem->gid == nitem->gid)
|
||||
status = GIT_DELTA_UNMODIFIED;
|
||||
|
||||
else if (S_ISGITLINK(nmode)) {
|
||||
git_submodule *sub;
|
||||
|
||||
if ((diff->opts.flags & GIT_DIFF_IGNORE_SUBMODULES) != 0)
|
||||
status = GIT_DELTA_UNMODIFIED;
|
||||
else if (git_submodule_lookup(&sub, diff->repo, nitem->path) < 0)
|
||||
return -1;
|
||||
else if (sub->ignore == GIT_SUBMODULE_IGNORE_ALL)
|
||||
status = GIT_DELTA_UNMODIFIED;
|
||||
else {
|
||||
/* TODO: support other GIT_SUBMODULE_IGNORE values */
|
||||
status = GIT_DELTA_UNMODIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: check git attributes so we will not have to read the file
|
||||
* in if it is marked binary.
|
||||
*/
|
||||
|
||||
else if (oid_for_workdir_item(diff->repo, nitem, &noid) < 0)
|
||||
return -1;
|
||||
|
||||
else if (git_oid_cmp(&oitem->oid, &noid) == 0 &&
|
||||
omode == nmode)
|
||||
status = GIT_DELTA_UNMODIFIED;
|
||||
|
||||
/* store calculated oid so we don't have to recalc later */
|
||||
use_noid = &noid;
|
||||
}
|
||||
|
||||
return diff_delta__from_two(diff, status, oitem, nitem, use_noid);
|
||||
}
|
||||
|
||||
static int diff_from_iterators(
|
||||
git_repository *repo,
|
||||
const git_diff_options *opts, /**< can be NULL for defaults */
|
||||
git_iterator *old_iter,
|
||||
git_iterator *new_iter,
|
||||
git_diff_list **diff_ptr)
|
||||
{
|
||||
const git_index_entry *oitem, *nitem;
|
||||
git_buf ignore_prefix = GIT_BUF_INIT;
|
||||
git_diff_list *diff = git_diff_list_alloc(repo, opts);
|
||||
if (!diff)
|
||||
goto fail;
|
||||
|
||||
diff->old_src = old_iter->type;
|
||||
diff->new_src = new_iter->type;
|
||||
|
||||
if (git_iterator_current(old_iter, &oitem) < 0 ||
|
||||
git_iterator_current(new_iter, &nitem) < 0)
|
||||
goto fail;
|
||||
|
||||
/* run iterators building diffs */
|
||||
while (oitem || nitem) {
|
||||
|
||||
/* create DELETED records for old items not matched in new */
|
||||
if (oitem && (!nitem || strcmp(oitem->path, nitem->path) < 0)) {
|
||||
if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 ||
|
||||
git_iterator_advance(old_iter, &oitem) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* create ADDED, TRACKED, or IGNORED records for new items not
|
||||
* matched in old (and/or descend into directories as needed)
|
||||
*/
|
||||
else if (nitem && (!oitem || strcmp(oitem->path, nitem->path) > 0)) {
|
||||
git_delta_t delta_type = GIT_DELTA_UNTRACKED;
|
||||
|
||||
/* check if contained in ignored parent directory */
|
||||
if (git_buf_len(&ignore_prefix) &&
|
||||
git__prefixcmp(nitem->path, git_buf_cstr(&ignore_prefix)) == 0)
|
||||
delta_type = GIT_DELTA_IGNORED;
|
||||
|
||||
if (S_ISDIR(nitem->mode)) {
|
||||
/* recurse into directory only if there are tracked items in
|
||||
* it or if the user requested the contents of untracked
|
||||
* directories and it is not under an ignored directory.
|
||||
*/
|
||||
if ((oitem && git__prefixcmp(oitem->path, nitem->path) == 0) ||
|
||||
(delta_type == GIT_DELTA_UNTRACKED &&
|
||||
(diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS) != 0))
|
||||
{
|
||||
/* if this directory is ignored, remember it as the
|
||||
* "ignore_prefix" for processing contained items
|
||||
*/
|
||||
if (delta_type == GIT_DELTA_UNTRACKED &&
|
||||
git_iterator_current_is_ignored(new_iter))
|
||||
git_buf_sets(&ignore_prefix, nitem->path);
|
||||
|
||||
if (git_iterator_advance_into_directory(new_iter, &nitem) < 0)
|
||||
goto fail;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* In core git, the next two "else if" clauses are effectively
|
||||
* reversed -- i.e. when an untracked file contained in an
|
||||
* ignored directory is individually ignored, it shows up as an
|
||||
* ignored file in the diff list, even though other untracked
|
||||
* files in the same directory are skipped completely.
|
||||
*
|
||||
* To me, this is odd. If the directory is ignored and the file
|
||||
* is untracked, we should skip it consistently, regardless of
|
||||
* whether it happens to match a pattern in the ignore file.
|
||||
*
|
||||
* To match the core git behavior, just reverse the following
|
||||
* two "else if" cases so that individual file ignores are
|
||||
* checked before container directory exclusions are used to
|
||||
* skip the file.
|
||||
*/
|
||||
else if (delta_type == GIT_DELTA_IGNORED) {
|
||||
if (git_iterator_advance(new_iter, &nitem) < 0)
|
||||
goto fail;
|
||||
continue; /* ignored parent directory, so skip completely */
|
||||
}
|
||||
|
||||
else if (git_iterator_current_is_ignored(new_iter))
|
||||
delta_type = GIT_DELTA_IGNORED;
|
||||
|
||||
else if (new_iter->type != GIT_ITERATOR_WORKDIR)
|
||||
delta_type = GIT_DELTA_ADDED;
|
||||
|
||||
if (diff_delta__from_one(diff, delta_type, nitem) < 0 ||
|
||||
git_iterator_advance(new_iter, &nitem) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* otherwise item paths match, so create MODIFIED record
|
||||
* (or ADDED and DELETED pair if type changed)
|
||||
*/
|
||||
else {
|
||||
assert(oitem && nitem && strcmp(oitem->path, nitem->path) == 0);
|
||||
|
||||
if (maybe_modified(old_iter, oitem, new_iter, nitem, diff) < 0 ||
|
||||
git_iterator_advance(old_iter, &oitem) < 0 ||
|
||||
git_iterator_advance(new_iter, &nitem) < 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
git_iterator_free(old_iter);
|
||||
git_iterator_free(new_iter);
|
||||
git_buf_free(&ignore_prefix);
|
||||
|
||||
*diff_ptr = diff;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
git_iterator_free(old_iter);
|
||||
git_iterator_free(new_iter);
|
||||
git_buf_free(&ignore_prefix);
|
||||
|
||||
git_diff_list_free(diff);
|
||||
*diff_ptr = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int git_diff_tree_to_tree(
|
||||
git_repository *repo,
|
||||
const git_diff_options *opts, /**< can be NULL for defaults */
|
||||
git_tree *old_tree,
|
||||
git_tree *new_tree,
|
||||
git_diff_list **diff)
|
||||
{
|
||||
git_iterator *a = NULL, *b = NULL;
|
||||
char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL;
|
||||
|
||||
assert(repo && old_tree && new_tree && diff);
|
||||
|
||||
if (git_iterator_for_tree_range(&a, repo, old_tree, prefix, prefix) < 0 ||
|
||||
git_iterator_for_tree_range(&b, repo, new_tree, prefix, prefix) < 0)
|
||||
return -1;
|
||||
|
||||
git__free(prefix);
|
||||
|
||||
return diff_from_iterators(repo, opts, a, b, diff);
|
||||
}
|
||||
|
||||
int git_diff_index_to_tree(
|
||||
git_repository *repo,
|
||||
const git_diff_options *opts,
|
||||
git_tree *old_tree,
|
||||
git_diff_list **diff)
|
||||
{
|
||||
git_iterator *a = NULL, *b = NULL;
|
||||
char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL;
|
||||
|
||||
assert(repo && diff);
|
||||
|
||||
if (git_iterator_for_tree_range(&a, repo, old_tree, prefix, prefix) < 0 ||
|
||||
git_iterator_for_index_range(&b, repo, prefix, prefix) < 0)
|
||||
return -1;
|
||||
|
||||
git__free(prefix);
|
||||
|
||||
return diff_from_iterators(repo, opts, a, b, diff);
|
||||
}
|
||||
|
||||
int git_diff_workdir_to_index(
|
||||
git_repository *repo,
|
||||
const git_diff_options *opts,
|
||||
git_diff_list **diff)
|
||||
{
|
||||
git_iterator *a = NULL, *b = NULL;
|
||||
char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL;
|
||||
|
||||
assert(repo && diff);
|
||||
|
||||
if (git_iterator_for_index_range(&a, repo, prefix, prefix) < 0 ||
|
||||
git_iterator_for_workdir_range(&b, repo, prefix, prefix) < 0)
|
||||
return -1;
|
||||
|
||||
git__free(prefix);
|
||||
|
||||
return diff_from_iterators(repo, opts, a, b, diff);
|
||||
}
|
||||
|
||||
|
||||
int git_diff_workdir_to_tree(
|
||||
git_repository *repo,
|
||||
const git_diff_options *opts,
|
||||
git_tree *old_tree,
|
||||
git_diff_list **diff)
|
||||
{
|
||||
git_iterator *a = NULL, *b = NULL;
|
||||
char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL;
|
||||
|
||||
assert(repo && old_tree && diff);
|
||||
|
||||
if (git_iterator_for_tree_range(&a, repo, old_tree, prefix, prefix) < 0 ||
|
||||
git_iterator_for_workdir_range(&b, repo, prefix, prefix) < 0)
|
||||
return -1;
|
||||
|
||||
git__free(prefix);
|
||||
|
||||
return diff_from_iterators(repo, opts, a, b, diff);
|
||||
}
|
||||
|
||||
int git_diff_merge(
|
||||
git_diff_list *onto,
|
||||
const git_diff_list *from)
|
||||
{
|
||||
int error = 0;
|
||||
git_pool onto_pool;
|
||||
git_vector onto_new;
|
||||
git_diff_delta *delta;
|
||||
unsigned int i, j;
|
||||
|
||||
assert(onto && from);
|
||||
|
||||
if (!from->deltas.length)
|
||||
return 0;
|
||||
|
||||
if (git_vector_init(&onto_new, onto->deltas.length, diff_delta__cmp) < 0 ||
|
||||
git_pool_init(&onto_pool, 1, 0) < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) {
|
||||
git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i);
|
||||
const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j);
|
||||
int cmp = !f ? -1 : !o ? 1 : strcmp(o->old_file.path, f->old_file.path);
|
||||
|
||||
if (cmp < 0) {
|
||||
delta = diff_delta__dup(o, &onto_pool);
|
||||
i++;
|
||||
} else if (cmp > 0) {
|
||||
delta = diff_delta__dup(f, &onto_pool);
|
||||
j++;
|
||||
} else {
|
||||
delta = diff_delta__merge_like_cgit(o, f, &onto_pool);
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
if ((error = !delta ? -1 : git_vector_insert(&onto_new, delta)) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
git_vector_swap(&onto->deltas, &onto_new);
|
||||
git_pool_swap(&onto->pool, &onto_pool);
|
||||
onto->new_src = from->new_src;
|
||||
}
|
||||
|
||||
git_vector_foreach(&onto_new, i, delta)
|
||||
git__free(delta);
|
||||
git_vector_free(&onto_new);
|
||||
git_pool_clear(&onto_pool);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
609
samples/C/git.c
Normal file
609
samples/C/git.c
Normal file
@@ -0,0 +1,609 @@
|
||||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
#include "exec_cmd.h"
|
||||
#include "help.h"
|
||||
#include "quote.h"
|
||||
#include "run-command.h"
|
||||
|
||||
const char git_usage_string[] =
|
||||
"git [--version] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
|
||||
" [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]\n"
|
||||
" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
|
||||
" [-c name=value] [--help]\n"
|
||||
" <command> [<args>]";
|
||||
|
||||
const char git_more_info_string[] =
|
||||
N_("See 'git help <command>' for more information on a specific command.");
|
||||
|
||||
static struct startup_info git_startup_info;
|
||||
static int use_pager = -1;
|
||||
struct pager_config {
|
||||
const char *cmd;
|
||||
int want;
|
||||
char *value;
|
||||
};
|
||||
|
||||
static int pager_command_config(const char *var, const char *value, void *data)
|
||||
{
|
||||
struct pager_config *c = data;
|
||||
if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd)) {
|
||||
int b = git_config_maybe_bool(var, value);
|
||||
if (b >= 0)
|
||||
c->want = b;
|
||||
else {
|
||||
c->want = 1;
|
||||
c->value = xstrdup(value);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
|
||||
int check_pager_config(const char *cmd)
|
||||
{
|
||||
struct pager_config c;
|
||||
c.cmd = cmd;
|
||||
c.want = -1;
|
||||
c.value = NULL;
|
||||
git_config(pager_command_config, &c);
|
||||
if (c.value)
|
||||
pager_program = c.value;
|
||||
return c.want;
|
||||
}
|
||||
|
||||
static void commit_pager_choice(void) {
|
||||
switch (use_pager) {
|
||||
case 0:
|
||||
setenv("GIT_PAGER", "cat", 1);
|
||||
break;
|
||||
case 1:
|
||||
setup_pager();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_options(const char ***argv, int *argc, int *envchanged)
|
||||
{
|
||||
const char **orig_argv = *argv;
|
||||
|
||||
while (*argc > 0) {
|
||||
const char *cmd = (*argv)[0];
|
||||
if (cmd[0] != '-')
|
||||
break;
|
||||
|
||||
/*
|
||||
* For legacy reasons, the "version" and "help"
|
||||
* commands can be written with "--" prepended
|
||||
* to make them look like flags.
|
||||
*/
|
||||
if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version"))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Check remaining flags.
|
||||
*/
|
||||
if (!prefixcmp(cmd, "--exec-path")) {
|
||||
cmd += 11;
|
||||
if (*cmd == '=')
|
||||
git_set_argv_exec_path(cmd + 1);
|
||||
else {
|
||||
puts(git_exec_path());
|
||||
exit(0);
|
||||
}
|
||||
} else if (!strcmp(cmd, "--html-path")) {
|
||||
puts(system_path(GIT_HTML_PATH));
|
||||
exit(0);
|
||||
} else if (!strcmp(cmd, "--man-path")) {
|
||||
puts(system_path(GIT_MAN_PATH));
|
||||
exit(0);
|
||||
} else if (!strcmp(cmd, "--info-path")) {
|
||||
puts(system_path(GIT_INFO_PATH));
|
||||
exit(0);
|
||||
} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
|
||||
use_pager = 1;
|
||||
} else if (!strcmp(cmd, "--no-pager")) {
|
||||
use_pager = 0;
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--no-replace-objects")) {
|
||||
read_replace_refs = 0;
|
||||
setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--git-dir")) {
|
||||
if (*argc < 2) {
|
||||
fprintf(stderr, "No directory given for --git-dir.\n" );
|
||||
usage(git_usage_string);
|
||||
}
|
||||
setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
(*argv)++;
|
||||
(*argc)--;
|
||||
} else if (!prefixcmp(cmd, "--git-dir=")) {
|
||||
setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--namespace")) {
|
||||
if (*argc < 2) {
|
||||
fprintf(stderr, "No namespace given for --namespace.\n" );
|
||||
usage(git_usage_string);
|
||||
}
|
||||
setenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
(*argv)++;
|
||||
(*argc)--;
|
||||
} else if (!prefixcmp(cmd, "--namespace=")) {
|
||||
setenv(GIT_NAMESPACE_ENVIRONMENT, cmd + 12, 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--work-tree")) {
|
||||
if (*argc < 2) {
|
||||
fprintf(stderr, "No directory given for --work-tree.\n" );
|
||||
usage(git_usage_string);
|
||||
}
|
||||
setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
(*argv)++;
|
||||
(*argc)--;
|
||||
} else if (!prefixcmp(cmd, "--work-tree=")) {
|
||||
setenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--bare")) {
|
||||
static char git_dir[PATH_MAX+1];
|
||||
is_bare_repository_cfg = 1;
|
||||
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "-c")) {
|
||||
if (*argc < 2) {
|
||||
fprintf(stderr, "-c expects a configuration string\n" );
|
||||
usage(git_usage_string);
|
||||
}
|
||||
git_config_push_parameter((*argv)[1]);
|
||||
(*argv)++;
|
||||
(*argc)--;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown option: %s\n", cmd);
|
||||
usage(git_usage_string);
|
||||
}
|
||||
|
||||
(*argv)++;
|
||||
(*argc)--;
|
||||
}
|
||||
return (*argv) - orig_argv;
|
||||
}
|
||||
|
||||
static int handle_alias(int *argcp, const char ***argv)
|
||||
{
|
||||
int envchanged = 0, ret = 0, saved_errno = errno;
|
||||
const char *subdir;
|
||||
int count, option_count;
|
||||
const char **new_argv;
|
||||
const char *alias_command;
|
||||
char *alias_string;
|
||||
int unused_nongit;
|
||||
|
||||
subdir = setup_git_directory_gently(&unused_nongit);
|
||||
|
||||
alias_command = (*argv)[0];
|
||||
alias_string = alias_lookup(alias_command);
|
||||
if (alias_string) {
|
||||
if (alias_string[0] == '!') {
|
||||
const char **alias_argv;
|
||||
int argc = *argcp, i;
|
||||
|
||||
commit_pager_choice();
|
||||
|
||||
/* build alias_argv */
|
||||
alias_argv = xmalloc(sizeof(*alias_argv) * (argc + 1));
|
||||
alias_argv[0] = alias_string + 1;
|
||||
for (i = 1; i < argc; ++i)
|
||||
alias_argv[i] = (*argv)[i];
|
||||
alias_argv[argc] = NULL;
|
||||
|
||||
ret = run_command_v_opt(alias_argv, RUN_USING_SHELL);
|
||||
if (ret >= 0) /* normal exit */
|
||||
exit(ret);
|
||||
|
||||
die_errno("While expanding alias '%s': '%s'",
|
||||
alias_command, alias_string + 1);
|
||||
}
|
||||
count = split_cmdline(alias_string, &new_argv);
|
||||
if (count < 0)
|
||||
die("Bad alias.%s string: %s", alias_command,
|
||||
split_cmdline_strerror(count));
|
||||
option_count = handle_options(&new_argv, &count, &envchanged);
|
||||
if (envchanged)
|
||||
die("alias '%s' changes environment variables\n"
|
||||
"You can use '!git' in the alias to do this.",
|
||||
alias_command);
|
||||
memmove(new_argv - option_count, new_argv,
|
||||
count * sizeof(char *));
|
||||
new_argv -= option_count;
|
||||
|
||||
if (count < 1)
|
||||
die("empty alias for %s", alias_command);
|
||||
|
||||
if (!strcmp(alias_command, new_argv[0]))
|
||||
die("recursive alias: %s", alias_command);
|
||||
|
||||
trace_argv_printf(new_argv,
|
||||
"trace: alias expansion: %s =>",
|
||||
alias_command);
|
||||
|
||||
new_argv = xrealloc(new_argv, sizeof(char *) *
|
||||
(count + *argcp));
|
||||
/* insert after command name */
|
||||
memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
|
||||
|
||||
*argv = new_argv;
|
||||
*argcp += count - 1;
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (subdir && chdir(subdir))
|
||||
die_errno("Cannot change to '%s'", subdir);
|
||||
|
||||
errno = saved_errno;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char git_version_string[] = GIT_VERSION;
|
||||
|
||||
#define RUN_SETUP (1<<0)
|
||||
#define RUN_SETUP_GENTLY (1<<1)
|
||||
#define USE_PAGER (1<<2)
|
||||
/*
|
||||
* require working tree to be present -- anything uses this needs
|
||||
* RUN_SETUP for reading from the configuration file.
|
||||
*/
|
||||
#define NEED_WORK_TREE (1<<3)
|
||||
|
||||
struct cmd_struct {
|
||||
const char *cmd;
|
||||
int (*fn)(int, const char **, const char *);
|
||||
int option;
|
||||
};
|
||||
|
||||
static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
|
||||
{
|
||||
int status, help;
|
||||
struct stat st;
|
||||
const char *prefix;
|
||||
|
||||
prefix = NULL;
|
||||
help = argc == 2 && !strcmp(argv[1], "-h");
|
||||
if (!help) {
|
||||
if (p->option & RUN_SETUP)
|
||||
prefix = setup_git_directory();
|
||||
if (p->option & RUN_SETUP_GENTLY) {
|
||||
int nongit_ok;
|
||||
prefix = setup_git_directory_gently(&nongit_ok);
|
||||
}
|
||||
|
||||
if (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY))
|
||||
use_pager = check_pager_config(p->cmd);
|
||||
if (use_pager == -1 && p->option & USE_PAGER)
|
||||
use_pager = 1;
|
||||
|
||||
if ((p->option & (RUN_SETUP | RUN_SETUP_GENTLY)) &&
|
||||
startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */
|
||||
trace_repo_setup(prefix);
|
||||
}
|
||||
commit_pager_choice();
|
||||
|
||||
if (!help && p->option & NEED_WORK_TREE)
|
||||
setup_work_tree();
|
||||
|
||||
trace_argv_printf(argv, "trace: built-in: git");
|
||||
|
||||
status = p->fn(argc, argv, prefix);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Somebody closed stdout? */
|
||||
if (fstat(fileno(stdout), &st))
|
||||
return 0;
|
||||
/* Ignore write errors for pipes and sockets.. */
|
||||
if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
|
||||
return 0;
|
||||
|
||||
/* Check for ENOSPC and EIO errors.. */
|
||||
if (fflush(stdout))
|
||||
die_errno("write failure on standard output");
|
||||
if (ferror(stdout))
|
||||
die("unknown write failure on standard output");
|
||||
if (fclose(stdout))
|
||||
die_errno("close failed on standard output");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_internal_command(int argc, const char **argv)
|
||||
{
|
||||
const char *cmd = argv[0];
|
||||
static struct cmd_struct commands[] = {
|
||||
{ "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "annotate", cmd_annotate, RUN_SETUP },
|
||||
{ "apply", cmd_apply, RUN_SETUP_GENTLY },
|
||||
{ "archive", cmd_archive },
|
||||
{ "bisect--helper", cmd_bisect__helper, RUN_SETUP },
|
||||
{ "blame", cmd_blame, RUN_SETUP },
|
||||
{ "branch", cmd_branch, RUN_SETUP },
|
||||
{ "bundle", cmd_bundle, RUN_SETUP_GENTLY },
|
||||
{ "cat-file", cmd_cat_file, RUN_SETUP },
|
||||
{ "check-attr", cmd_check_attr, RUN_SETUP },
|
||||
{ "check-ref-format", cmd_check_ref_format },
|
||||
{ "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "checkout-index", cmd_checkout_index,
|
||||
RUN_SETUP | NEED_WORK_TREE},
|
||||
{ "cherry", cmd_cherry, RUN_SETUP },
|
||||
{ "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "clone", cmd_clone },
|
||||
{ "column", cmd_column, RUN_SETUP_GENTLY },
|
||||
{ "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "commit-tree", cmd_commit_tree, RUN_SETUP },
|
||||
{ "config", cmd_config, RUN_SETUP_GENTLY },
|
||||
{ "count-objects", cmd_count_objects, RUN_SETUP },
|
||||
{ "describe", cmd_describe, RUN_SETUP },
|
||||
{ "diff", cmd_diff },
|
||||
{ "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "diff-index", cmd_diff_index, RUN_SETUP },
|
||||
{ "diff-tree", cmd_diff_tree, RUN_SETUP },
|
||||
{ "fast-export", cmd_fast_export, RUN_SETUP },
|
||||
{ "fetch", cmd_fetch, RUN_SETUP },
|
||||
{ "fetch-pack", cmd_fetch_pack, RUN_SETUP },
|
||||
{ "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
|
||||
{ "for-each-ref", cmd_for_each_ref, RUN_SETUP },
|
||||
{ "format-patch", cmd_format_patch, RUN_SETUP },
|
||||
{ "fsck", cmd_fsck, RUN_SETUP },
|
||||
{ "fsck-objects", cmd_fsck, RUN_SETUP },
|
||||
{ "gc", cmd_gc, RUN_SETUP },
|
||||
{ "get-tar-commit-id", cmd_get_tar_commit_id },
|
||||
{ "grep", cmd_grep, RUN_SETUP_GENTLY },
|
||||
{ "hash-object", cmd_hash_object },
|
||||
{ "help", cmd_help },
|
||||
{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
|
||||
{ "init", cmd_init_db },
|
||||
{ "init-db", cmd_init_db },
|
||||
{ "log", cmd_log, RUN_SETUP },
|
||||
{ "ls-files", cmd_ls_files, RUN_SETUP },
|
||||
{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
|
||||
{ "ls-tree", cmd_ls_tree, RUN_SETUP },
|
||||
{ "mailinfo", cmd_mailinfo },
|
||||
{ "mailsplit", cmd_mailsplit },
|
||||
{ "merge", cmd_merge, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "merge-base", cmd_merge_base, RUN_SETUP },
|
||||
{ "merge-file", cmd_merge_file, RUN_SETUP_GENTLY },
|
||||
{ "merge-index", cmd_merge_index, RUN_SETUP },
|
||||
{ "merge-ours", cmd_merge_ours, RUN_SETUP },
|
||||
{ "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "merge-tree", cmd_merge_tree, RUN_SETUP },
|
||||
{ "mktag", cmd_mktag, RUN_SETUP },
|
||||
{ "mktree", cmd_mktree, RUN_SETUP },
|
||||
{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "name-rev", cmd_name_rev, RUN_SETUP },
|
||||
{ "notes", cmd_notes, RUN_SETUP },
|
||||
{ "pack-objects", cmd_pack_objects, RUN_SETUP },
|
||||
{ "pack-redundant", cmd_pack_redundant, RUN_SETUP },
|
||||
{ "pack-refs", cmd_pack_refs, RUN_SETUP },
|
||||
{ "patch-id", cmd_patch_id },
|
||||
{ "peek-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
|
||||
{ "pickaxe", cmd_blame, RUN_SETUP },
|
||||
{ "prune", cmd_prune, RUN_SETUP },
|
||||
{ "prune-packed", cmd_prune_packed, RUN_SETUP },
|
||||
{ "push", cmd_push, RUN_SETUP },
|
||||
{ "read-tree", cmd_read_tree, RUN_SETUP },
|
||||
{ "receive-pack", cmd_receive_pack },
|
||||
{ "reflog", cmd_reflog, RUN_SETUP },
|
||||
{ "remote", cmd_remote, RUN_SETUP },
|
||||
{ "remote-ext", cmd_remote_ext },
|
||||
{ "remote-fd", cmd_remote_fd },
|
||||
{ "replace", cmd_replace, RUN_SETUP },
|
||||
{ "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
|
||||
{ "rerere", cmd_rerere, RUN_SETUP },
|
||||
{ "reset", cmd_reset, RUN_SETUP },
|
||||
{ "rev-list", cmd_rev_list, RUN_SETUP },
|
||||
{ "rev-parse", cmd_rev_parse },
|
||||
{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "rm", cmd_rm, RUN_SETUP },
|
||||
{ "send-pack", cmd_send_pack, RUN_SETUP },
|
||||
{ "shortlog", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },
|
||||
{ "show", cmd_show, RUN_SETUP },
|
||||
{ "show-branch", cmd_show_branch, RUN_SETUP },
|
||||
{ "show-ref", cmd_show_ref, RUN_SETUP },
|
||||
{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "stripspace", cmd_stripspace },
|
||||
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
|
||||
{ "tag", cmd_tag, RUN_SETUP },
|
||||
{ "tar-tree", cmd_tar_tree },
|
||||
{ "unpack-file", cmd_unpack_file, RUN_SETUP },
|
||||
{ "unpack-objects", cmd_unpack_objects, RUN_SETUP },
|
||||
{ "update-index", cmd_update_index, RUN_SETUP },
|
||||
{ "update-ref", cmd_update_ref, RUN_SETUP },
|
||||
{ "update-server-info", cmd_update_server_info, RUN_SETUP },
|
||||
{ "upload-archive", cmd_upload_archive },
|
||||
{ "upload-archive--writer", cmd_upload_archive_writer },
|
||||
{ "var", cmd_var, RUN_SETUP_GENTLY },
|
||||
{ "verify-pack", cmd_verify_pack },
|
||||
{ "verify-tag", cmd_verify_tag, RUN_SETUP },
|
||||
{ "version", cmd_version },
|
||||
{ "whatchanged", cmd_whatchanged, RUN_SETUP },
|
||||
{ "write-tree", cmd_write_tree, RUN_SETUP },
|
||||
};
|
||||
int i;
|
||||
static const char ext[] = STRIP_EXTENSION;
|
||||
|
||||
if (sizeof(ext) > 1) {
|
||||
i = strlen(argv[0]) - strlen(ext);
|
||||
if (i > 0 && !strcmp(argv[0] + i, ext)) {
|
||||
char *argv0 = xstrdup(argv[0]);
|
||||
argv[0] = cmd = argv0;
|
||||
argv0[i] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn "git cmd --help" into "git help cmd" */
|
||||
if (argc > 1 && !strcmp(argv[1], "--help")) {
|
||||
argv[1] = argv[0];
|
||||
argv[0] = cmd = "help";
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(commands); i++) {
|
||||
struct cmd_struct *p = commands+i;
|
||||
if (strcmp(p->cmd, cmd))
|
||||
continue;
|
||||
exit(run_builtin(p, argc, argv));
|
||||
}
|
||||
}
|
||||
|
||||
static void execv_dashed_external(const char **argv)
|
||||
{
|
||||
struct strbuf cmd = STRBUF_INIT;
|
||||
const char *tmp;
|
||||
int status;
|
||||
|
||||
if (use_pager == -1)
|
||||
use_pager = check_pager_config(argv[0]);
|
||||
commit_pager_choice();
|
||||
|
||||
strbuf_addf(&cmd, "git-%s", argv[0]);
|
||||
|
||||
/*
|
||||
* argv[0] must be the git command, but the argv array
|
||||
* belongs to the caller, and may be reused in
|
||||
* subsequent loop iterations. Save argv[0] and
|
||||
* restore it on error.
|
||||
*/
|
||||
tmp = argv[0];
|
||||
argv[0] = cmd.buf;
|
||||
|
||||
trace_argv_printf(argv, "trace: exec:");
|
||||
|
||||
/*
|
||||
* if we fail because the command is not found, it is
|
||||
* OK to return. Otherwise, we just pass along the status code.
|
||||
*/
|
||||
status = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE | RUN_CLEAN_ON_EXIT);
|
||||
if (status >= 0 || errno != ENOENT)
|
||||
exit(status);
|
||||
|
||||
argv[0] = tmp;
|
||||
|
||||
strbuf_release(&cmd);
|
||||
}
|
||||
|
||||
static int run_argv(int *argcp, const char ***argv)
|
||||
{
|
||||
int done_alias = 0;
|
||||
|
||||
while (1) {
|
||||
/* See if it's an internal command */
|
||||
handle_internal_command(*argcp, *argv);
|
||||
|
||||
/* .. then try the external ones */
|
||||
execv_dashed_external(*argv);
|
||||
|
||||
/* It could be an alias -- this works around the insanity
|
||||
* of overriding "git log" with "git show" by having
|
||||
* alias.log = show
|
||||
*/
|
||||
if (done_alias || !handle_alias(argcp, argv))
|
||||
break;
|
||||
done_alias = 1;
|
||||
}
|
||||
|
||||
return done_alias;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
const char *cmd;
|
||||
|
||||
startup_info = &git_startup_info;
|
||||
|
||||
cmd = git_extract_argv0_path(argv[0]);
|
||||
if (!cmd)
|
||||
cmd = "git-help";
|
||||
|
||||
git_setup_gettext();
|
||||
|
||||
/*
|
||||
* "git-xxxx" is the same as "git xxxx", but we obviously:
|
||||
*
|
||||
* - cannot take flags in between the "git" and the "xxxx".
|
||||
* - cannot execute it externally (since it would just do
|
||||
* the same thing over again)
|
||||
*
|
||||
* So we just directly call the internal command handler, and
|
||||
* die if that one cannot handle it.
|
||||
*/
|
||||
if (!prefixcmp(cmd, "git-")) {
|
||||
cmd += 4;
|
||||
argv[0] = cmd;
|
||||
handle_internal_command(argc, argv);
|
||||
die("cannot handle %s internally", cmd);
|
||||
}
|
||||
|
||||
/* Look for flags.. */
|
||||
argv++;
|
||||
argc--;
|
||||
handle_options(&argv, &argc, NULL);
|
||||
if (argc > 0) {
|
||||
if (!prefixcmp(argv[0], "--"))
|
||||
argv[0] += 2;
|
||||
} else {
|
||||
/* The user didn't specify a command; give them help */
|
||||
commit_pager_choice();
|
||||
printf("usage: %s\n\n", git_usage_string);
|
||||
list_common_cmds_help();
|
||||
printf("\n%s\n", git_more_info_string);
|
||||
exit(1);
|
||||
}
|
||||
cmd = argv[0];
|
||||
|
||||
/*
|
||||
* We use PATH to find git commands, but we prepend some higher
|
||||
* precedence paths: the "--exec-path" option, the GIT_EXEC_PATH
|
||||
* environment, and the $(gitexecdir) from the Makefile at build
|
||||
* time.
|
||||
*/
|
||||
setup_path();
|
||||
|
||||
while (1) {
|
||||
static int done_help = 0;
|
||||
static int was_alias = 0;
|
||||
was_alias = run_argv(&argc, &argv);
|
||||
if (errno != ENOENT)
|
||||
break;
|
||||
if (was_alias) {
|
||||
fprintf(stderr, "Expansion of alias '%s' failed; "
|
||||
"'%s' is not a git command\n",
|
||||
cmd, argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (!done_help) {
|
||||
cmd = argv[0] = help_unknown_cmd(cmd);
|
||||
done_help = 1;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Failed to run command '%s': %s\n",
|
||||
cmd, strerror(errno));
|
||||
|
||||
return 1;
|
||||
}
|
||||
74
samples/C/hash.c
Normal file
74
samples/C/hash.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2012 the libgit2 contributors
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "hash.h"
|
||||
|
||||
#if defined(PPC_SHA1)
|
||||
# include "ppc/sha1.h"
|
||||
#else
|
||||
# include "sha1.h"
|
||||
#endif
|
||||
|
||||
struct git_hash_ctx {
|
||||
SHA_CTX c;
|
||||
};
|
||||
|
||||
git_hash_ctx *git_hash_new_ctx(void)
|
||||
{
|
||||
git_hash_ctx *ctx = git__malloc(sizeof(*ctx));
|
||||
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
SHA1_Init(&ctx->c);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void git_hash_free_ctx(git_hash_ctx *ctx)
|
||||
{
|
||||
git__free(ctx);
|
||||
}
|
||||
|
||||
void git_hash_init(git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
SHA1_Init(&ctx->c);
|
||||
}
|
||||
|
||||
void git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
|
||||
{
|
||||
assert(ctx);
|
||||
SHA1_Update(&ctx->c, data, len);
|
||||
}
|
||||
|
||||
void git_hash_final(git_oid *out, git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
SHA1_Final(out->id, &ctx->c);
|
||||
}
|
||||
|
||||
void git_hash_buf(git_oid *out, const void *data, size_t len)
|
||||
{
|
||||
SHA_CTX c;
|
||||
|
||||
SHA1_Init(&c);
|
||||
SHA1_Update(&c, data, len);
|
||||
SHA1_Final(out->id, &c);
|
||||
}
|
||||
|
||||
void git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n)
|
||||
{
|
||||
SHA_CTX c;
|
||||
size_t i;
|
||||
|
||||
SHA1_Init(&c);
|
||||
for (i = 0; i < n; i++)
|
||||
SHA1_Update(&c, vec[i].data, vec[i].len);
|
||||
SHA1_Final(out->id, &c);
|
||||
}
|
||||
7
samples/C/hello.c
Normal file
7
samples/C/hello.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("Hello World\n");
|
||||
return 0;
|
||||
}
|
||||
6
samples/C/hello.h
Normal file
6
samples/C/hello.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef HELLO_H
|
||||
#define HELLO_H
|
||||
|
||||
void hello();
|
||||
|
||||
#endif
|
||||
2059
samples/C/http_parser.c
Normal file
2059
samples/C/http_parser.c
Normal file
File diff suppressed because it is too large
Load Diff
318
samples/C/http_parser.h
Normal file
318
samples/C/http_parser.h
Normal file
@@ -0,0 +1,318 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef http_parser_h
|
||||
#define http_parser_h
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define HTTP_PARSER_VERSION_MAJOR 1
|
||||
#define HTTP_PARSER_VERSION_MINOR 0
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
typedef unsigned int size_t;
|
||||
typedef int ssize_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
|
||||
* faster
|
||||
*/
|
||||
#ifndef HTTP_PARSER_STRICT
|
||||
# define HTTP_PARSER_STRICT 1
|
||||
#endif
|
||||
|
||||
/* Compile with -DHTTP_PARSER_DEBUG=1 to add extra debugging information to
|
||||
* the error reporting facility.
|
||||
*/
|
||||
#ifndef HTTP_PARSER_DEBUG
|
||||
# define HTTP_PARSER_DEBUG 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Maximium header size allowed */
|
||||
#define HTTP_MAX_HEADER_SIZE (80*1024)
|
||||
|
||||
|
||||
typedef struct http_parser http_parser;
|
||||
typedef struct http_parser_settings http_parser_settings;
|
||||
|
||||
|
||||
/* Callbacks should return non-zero to indicate an error. The parser will
|
||||
* then halt execution.
|
||||
*
|
||||
* The one exception is on_headers_complete. In a HTTP_RESPONSE parser
|
||||
* returning '1' from on_headers_complete will tell the parser that it
|
||||
* should not expect a body. This is used when receiving a response to a
|
||||
* HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
|
||||
* chunked' headers that indicate the presence of a body.
|
||||
*
|
||||
* http_data_cb does not return data chunks. It will be call arbitrarally
|
||||
* many times for each string. E.G. you might get 10 callbacks for "on_path"
|
||||
* each providing just a few characters more data.
|
||||
*/
|
||||
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
|
||||
typedef int (*http_cb) (http_parser*);
|
||||
|
||||
|
||||
/* Request Methods */
|
||||
#define HTTP_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
/* pathological */ \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
/* webdav */ \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
/* subversion */ \
|
||||
XX(16, REPORT, REPORT) \
|
||||
XX(17, MKACTIVITY, MKACTIVITY) \
|
||||
XX(18, CHECKOUT, CHECKOUT) \
|
||||
XX(19, MERGE, MERGE) \
|
||||
/* upnp */ \
|
||||
XX(20, MSEARCH, M-SEARCH) \
|
||||
XX(21, NOTIFY, NOTIFY) \
|
||||
XX(22, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
/* RFC-5789 */ \
|
||||
XX(24, PATCH, PATCH) \
|
||||
XX(25, PURGE, PURGE) \
|
||||
|
||||
enum http_method
|
||||
{
|
||||
#define XX(num, name, string) HTTP_##name = num,
|
||||
HTTP_METHOD_MAP(XX)
|
||||
#undef XX
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
|
||||
|
||||
|
||||
/* Flag values for http_parser.flags field */
|
||||
enum flags
|
||||
{ F_CHUNKED = 1 << 0
|
||||
, F_CONNECTION_KEEP_ALIVE = 1 << 1
|
||||
, F_CONNECTION_CLOSE = 1 << 2
|
||||
, F_TRAILING = 1 << 3
|
||||
, F_UPGRADE = 1 << 4
|
||||
, F_SKIPBODY = 1 << 5
|
||||
};
|
||||
|
||||
|
||||
/* Map for errno-related constants
|
||||
*
|
||||
* The provided argument should be a macro that takes 2 arguments.
|
||||
*/
|
||||
#define HTTP_ERRNO_MAP(XX) \
|
||||
/* No error */ \
|
||||
XX(OK, "success") \
|
||||
\
|
||||
/* Callback-related errors */ \
|
||||
XX(CB_message_begin, "the on_message_begin callback failed") \
|
||||
XX(CB_url, "the on_url callback failed") \
|
||||
XX(CB_header_field, "the on_header_field callback failed") \
|
||||
XX(CB_header_value, "the on_header_value callback failed") \
|
||||
XX(CB_headers_complete, "the on_headers_complete callback failed") \
|
||||
XX(CB_body, "the on_body callback failed") \
|
||||
XX(CB_message_complete, "the on_message_complete callback failed") \
|
||||
\
|
||||
/* Parsing-related errors */ \
|
||||
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
||||
XX(HEADER_OVERFLOW, \
|
||||
"too many header bytes seen; overflow detected") \
|
||||
XX(CLOSED_CONNECTION, \
|
||||
"data received after completed connection: close message") \
|
||||
XX(INVALID_VERSION, "invalid HTTP version") \
|
||||
XX(INVALID_STATUS, "invalid HTTP status code") \
|
||||
XX(INVALID_METHOD, "invalid HTTP method") \
|
||||
XX(INVALID_URL, "invalid URL") \
|
||||
XX(INVALID_HOST, "invalid host") \
|
||||
XX(INVALID_PORT, "invalid port") \
|
||||
XX(INVALID_PATH, "invalid path") \
|
||||
XX(INVALID_QUERY_STRING, "invalid query string") \
|
||||
XX(INVALID_FRAGMENT, "invalid fragment") \
|
||||
XX(LF_EXPECTED, "LF character expected") \
|
||||
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
||||
XX(INVALID_CONTENT_LENGTH, \
|
||||
"invalid character in content-length header") \
|
||||
XX(INVALID_CHUNK_SIZE, \
|
||||
"invalid character in chunk size header") \
|
||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
|
||||
XX(STRICT, "strict mode assertion failed") \
|
||||
XX(PAUSED, "parser is paused") \
|
||||
XX(UNKNOWN, "an unknown error occurred")
|
||||
|
||||
|
||||
/* Define HPE_* values for each errno value above */
|
||||
#define HTTP_ERRNO_GEN(n, s) HPE_##n,
|
||||
enum http_errno {
|
||||
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
|
||||
};
|
||||
#undef HTTP_ERRNO_GEN
|
||||
|
||||
|
||||
/* Get an http_errno value from an http_parser */
|
||||
#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
|
||||
|
||||
/* Get the line number that generated the current error */
|
||||
#if HTTP_PARSER_DEBUG
|
||||
#define HTTP_PARSER_ERRNO_LINE(p) ((p)->error_lineno)
|
||||
#else
|
||||
#define HTTP_PARSER_ERRNO_LINE(p) 0
|
||||
#endif
|
||||
|
||||
|
||||
struct http_parser {
|
||||
/** PRIVATE **/
|
||||
unsigned char type : 2; /* enum http_parser_type */
|
||||
unsigned char flags : 6; /* F_* values from 'flags' enum; semi-public */
|
||||
unsigned char state; /* enum state from http_parser.c */
|
||||
unsigned char header_state; /* enum header_state from http_parser.c */
|
||||
unsigned char index; /* index into current matcher */
|
||||
|
||||
uint32_t nread; /* # bytes read in various scenarios */
|
||||
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
|
||||
|
||||
/** READ-ONLY **/
|
||||
unsigned short http_major;
|
||||
unsigned short http_minor;
|
||||
unsigned short status_code; /* responses only */
|
||||
unsigned char method; /* requests only */
|
||||
unsigned char http_errno : 7;
|
||||
|
||||
/* 1 = Upgrade header was present and the parser has exited because of that.
|
||||
* 0 = No upgrade header present.
|
||||
* Should be checked when http_parser_execute() returns in addition to
|
||||
* error checking.
|
||||
*/
|
||||
unsigned char upgrade : 1;
|
||||
|
||||
#if HTTP_PARSER_DEBUG
|
||||
uint32_t error_lineno;
|
||||
#endif
|
||||
|
||||
/** PUBLIC **/
|
||||
void *data; /* A pointer to get hook to the "connection" or "socket" object */
|
||||
};
|
||||
|
||||
|
||||
struct http_parser_settings {
|
||||
http_cb on_message_begin;
|
||||
http_data_cb on_url;
|
||||
http_data_cb on_header_field;
|
||||
http_data_cb on_header_value;
|
||||
http_cb on_headers_complete;
|
||||
http_data_cb on_body;
|
||||
http_cb on_message_complete;
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_url_fields
|
||||
{ UF_SCHEMA = 0
|
||||
, UF_HOST = 1
|
||||
, UF_PORT = 2
|
||||
, UF_PATH = 3
|
||||
, UF_QUERY = 4
|
||||
, UF_FRAGMENT = 5
|
||||
, UF_MAX = 6
|
||||
};
|
||||
|
||||
|
||||
/* Result structure for http_parser_parse_url().
|
||||
*
|
||||
* Callers should index into field_data[] with UF_* values iff field_set
|
||||
* has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
|
||||
* because we probably have padding left over), we convert any port to
|
||||
* a uint16_t.
|
||||
*/
|
||||
struct http_parser_url {
|
||||
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
|
||||
uint16_t port; /* Converted UF_PORT string */
|
||||
|
||||
struct {
|
||||
uint16_t off; /* Offset into buffer in which field starts */
|
||||
uint16_t len; /* Length of run in buffer */
|
||||
} field_data[UF_MAX];
|
||||
};
|
||||
|
||||
|
||||
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
||||
|
||||
|
||||
size_t http_parser_execute(http_parser *parser,
|
||||
const http_parser_settings *settings,
|
||||
const char *data,
|
||||
size_t len);
|
||||
|
||||
|
||||
/* If http_should_keep_alive() in the on_headers_complete or
|
||||
* on_message_complete callback returns true, then this will be should be
|
||||
* the last message on the connection.
|
||||
* If you are the server, respond with the "Connection: close" header.
|
||||
* If you are the client, close the connection.
|
||||
*/
|
||||
int http_should_keep_alive(http_parser *parser);
|
||||
|
||||
/* Returns a string version of the HTTP method. */
|
||||
const char *http_method_str(enum http_method m);
|
||||
|
||||
/* Return a string name of the given error */
|
||||
const char *http_errno_name(enum http_errno err);
|
||||
|
||||
/* Return a string description of the given error */
|
||||
const char *http_errno_description(enum http_errno err);
|
||||
|
||||
/* Parse a URL; return nonzero on failure */
|
||||
int http_parser_parse_url(const char *buf, size_t buflen,
|
||||
int is_connect,
|
||||
struct http_parser_url *u);
|
||||
|
||||
/* Pause or un-pause the parser; a nonzero value pauses */
|
||||
void http_parser_pause(http_parser *parser, int paused);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
2551
samples/C/markdown.c
Normal file
2551
samples/C/markdown.c
Normal file
File diff suppressed because it is too large
Load Diff
462
samples/C/process.c
Normal file
462
samples/C/process.c
Normal file
@@ -0,0 +1,462 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && !TARGET_OS_IPHONE
|
||||
# include <crt_externs.h>
|
||||
# define environ (*_NSGetEnviron())
|
||||
#else
|
||||
extern char **environ;
|
||||
#endif
|
||||
|
||||
|
||||
static void uv__chld(EV_P_ ev_child* watcher, int revents) {
|
||||
int status = watcher->rstatus;
|
||||
int exit_status = 0;
|
||||
int term_signal = 0;
|
||||
uv_process_t *process = watcher->data;
|
||||
|
||||
assert(&process->child_watcher == watcher);
|
||||
assert(revents & EV_CHILD);
|
||||
|
||||
ev_child_stop(EV_A_ &process->child_watcher);
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
exit_status = WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
term_signal = WTERMSIG(status);
|
||||
}
|
||||
|
||||
if (process->exit_cb) {
|
||||
process->exit_cb(process, exit_status, term_signal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uv__make_socketpair(int fds[2], int flags) {
|
||||
#ifdef SOCK_NONBLOCK
|
||||
int fl;
|
||||
|
||||
fl = SOCK_CLOEXEC;
|
||||
|
||||
if (flags & UV__F_NONBLOCK)
|
||||
fl |= SOCK_NONBLOCK;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM|fl, 0, fds) == 0)
|
||||
return 0;
|
||||
|
||||
if (errno != EINVAL)
|
||||
return -1;
|
||||
|
||||
/* errno == EINVAL so maybe the kernel headers lied about
|
||||
* the availability of SOCK_NONBLOCK. This can happen if people
|
||||
* build libuv against newer kernel headers than the kernel
|
||||
* they actually run the software on.
|
||||
*/
|
||||
#endif
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
|
||||
return -1;
|
||||
|
||||
uv__cloexec(fds[0], 1);
|
||||
uv__cloexec(fds[1], 1);
|
||||
|
||||
if (flags & UV__F_NONBLOCK) {
|
||||
uv__nonblock(fds[0], 1);
|
||||
uv__nonblock(fds[1], 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv__make_pipe(int fds[2], int flags) {
|
||||
#if __linux__
|
||||
int fl;
|
||||
|
||||
fl = UV__O_CLOEXEC;
|
||||
|
||||
if (flags & UV__F_NONBLOCK)
|
||||
fl |= UV__O_NONBLOCK;
|
||||
|
||||
if (uv__pipe2(fds, fl) == 0)
|
||||
return 0;
|
||||
|
||||
if (errno != ENOSYS)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if (pipe(fds))
|
||||
return -1;
|
||||
|
||||
uv__cloexec(fds[0], 1);
|
||||
uv__cloexec(fds[1], 1);
|
||||
|
||||
if (flags & UV__F_NONBLOCK) {
|
||||
uv__nonblock(fds[0], 1);
|
||||
uv__nonblock(fds[1], 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Used for initializing stdio streams like options.stdin_stream. Returns
|
||||
* zero on success.
|
||||
*/
|
||||
static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2],
|
||||
int writable) {
|
||||
int fd = -1;
|
||||
switch (container->flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
|
||||
UV_INHERIT_STREAM)) {
|
||||
case UV_IGNORE:
|
||||
return 0;
|
||||
case UV_CREATE_PIPE:
|
||||
assert(container->data.stream != NULL);
|
||||
|
||||
if (container->data.stream->type != UV_NAMED_PIPE) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return uv__make_socketpair(fds, 0);
|
||||
case UV_INHERIT_FD:
|
||||
case UV_INHERIT_STREAM:
|
||||
if (container->flags & UV_INHERIT_FD) {
|
||||
fd = container->data.fd;
|
||||
} else {
|
||||
fd = container->data.stream->fd;
|
||||
}
|
||||
|
||||
if (fd == -1) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fds[writable ? 1 : 0] = fd;
|
||||
|
||||
return 0;
|
||||
default:
|
||||
assert(0 && "Unexpected flags");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int uv__process_stdio_flags(uv_stdio_container_t* container,
|
||||
int writable) {
|
||||
if (container->data.stream->type == UV_NAMED_PIPE &&
|
||||
((uv_pipe_t*)container->data.stream)->ipc) {
|
||||
return UV_STREAM_READABLE | UV_STREAM_WRITABLE;
|
||||
} else if (writable) {
|
||||
return UV_STREAM_WRITABLE;
|
||||
} else {
|
||||
return UV_STREAM_READABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int uv__process_open_stream(uv_stdio_container_t* container, int fds[2],
|
||||
int writable) {
|
||||
int fd = fds[writable ? 1 : 0];
|
||||
int child_fd = fds[writable ? 0 : 1];
|
||||
int flags;
|
||||
|
||||
/* No need to create stream */
|
||||
if (!(container->flags & UV_CREATE_PIPE) || fd < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(child_fd >= 0);
|
||||
close(child_fd);
|
||||
|
||||
uv__nonblock(fd, 1);
|
||||
flags = uv__process_stdio_flags(container, writable);
|
||||
|
||||
return uv__stream_open((uv_stream_t*)container->data.stream, fd, flags);
|
||||
}
|
||||
|
||||
|
||||
static void uv__process_close_stream(uv_stdio_container_t* container) {
|
||||
if (!(container->flags & UV_CREATE_PIPE)) return;
|
||||
|
||||
uv__stream_close((uv_stream_t*)container->data.stream);
|
||||
}
|
||||
|
||||
|
||||
static void uv__process_child_init(uv_process_options_t options,
|
||||
int stdio_count,
|
||||
int* pipes) {
|
||||
int i;
|
||||
|
||||
if (options.flags & UV_PROCESS_DETACHED) {
|
||||
setsid();
|
||||
}
|
||||
|
||||
/* Dup fds */
|
||||
for (i = 0; i < stdio_count; i++) {
|
||||
/*
|
||||
* stdin has swapped ends of pipe
|
||||
* (it's the only one readable stream)
|
||||
*/
|
||||
int close_fd = i == 0 ? pipes[i * 2 + 1] : pipes[i * 2];
|
||||
int use_fd = i == 0 ? pipes[i * 2] : pipes[i * 2 + 1];
|
||||
|
||||
if (use_fd >= 0) {
|
||||
close(close_fd);
|
||||
} else if (i < 3) {
|
||||
/* `/dev/null` stdin, stdout, stderr even if they've flag UV_IGNORE */
|
||||
use_fd = open("/dev/null", i == 0 ? O_RDONLY : O_RDWR);
|
||||
|
||||
if (use_fd < 0) {
|
||||
perror("failed to open stdio");
|
||||
_exit(127);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i != use_fd) {
|
||||
dup2(use_fd, i);
|
||||
close(use_fd);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.cwd && chdir(options.cwd)) {
|
||||
perror("chdir()");
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) {
|
||||
perror("setgid()");
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) {
|
||||
perror("setuid()");
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
environ = options.env;
|
||||
|
||||
execvp(options.file, options.args);
|
||||
perror("execvp()");
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SPAWN_WAIT_EXEC
|
||||
# define SPAWN_WAIT_EXEC 1
|
||||
#endif
|
||||
|
||||
int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
uv_process_options_t options) {
|
||||
/*
|
||||
* Save environ in the case that we get it clobbered
|
||||
* by the child process.
|
||||
*/
|
||||
char** save_our_env = environ;
|
||||
|
||||
int stdio_count = options.stdio_count < 3 ? 3 : options.stdio_count;
|
||||
int* pipes = malloc(2 * stdio_count * sizeof(int));
|
||||
|
||||
#if SPAWN_WAIT_EXEC
|
||||
int signal_pipe[2] = { -1, -1 };
|
||||
struct pollfd pfd;
|
||||
#endif
|
||||
int status;
|
||||
pid_t pid;
|
||||
int i;
|
||||
|
||||
if (pipes == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
assert(options.file != NULL);
|
||||
assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
|
||||
UV_PROCESS_DETACHED |
|
||||
UV_PROCESS_SETGID |
|
||||
UV_PROCESS_SETUID)));
|
||||
|
||||
|
||||
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
|
||||
loop->counters.process_init++;
|
||||
uv__handle_start(process);
|
||||
|
||||
process->exit_cb = options.exit_cb;
|
||||
|
||||
/* Init pipe pairs */
|
||||
for (i = 0; i < stdio_count; i++) {
|
||||
pipes[i * 2] = -1;
|
||||
pipes[i * 2 + 1] = -1;
|
||||
}
|
||||
|
||||
/* Create socketpairs/pipes, or use raw fd */
|
||||
for (i = 0; i < options.stdio_count; i++) {
|
||||
if (uv__process_init_stdio(&options.stdio[i], pipes + i * 2, i != 0)) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* This pipe is used by the parent to wait until
|
||||
* the child has called `execve()`. We need this
|
||||
* to avoid the following race condition:
|
||||
*
|
||||
* if ((pid = fork()) > 0) {
|
||||
* kill(pid, SIGTERM);
|
||||
* }
|
||||
* else if (pid == 0) {
|
||||
* execve("/bin/cat", argp, envp);
|
||||
* }
|
||||
*
|
||||
* The parent sends a signal immediately after forking.
|
||||
* Since the child may not have called `execve()` yet,
|
||||
* there is no telling what process receives the signal,
|
||||
* our fork or /bin/cat.
|
||||
*
|
||||
* To avoid ambiguity, we create a pipe with both ends
|
||||
* marked close-on-exec. Then, after the call to `fork()`,
|
||||
* the parent polls the read end until it sees POLLHUP.
|
||||
*/
|
||||
#if SPAWN_WAIT_EXEC
|
||||
if (uv__make_pipe(signal_pipe, UV__F_NONBLOCK))
|
||||
goto error;
|
||||
#endif
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == -1) {
|
||||
#if SPAWN_WAIT_EXEC
|
||||
close(signal_pipe[0]);
|
||||
close(signal_pipe[1]);
|
||||
#endif
|
||||
environ = save_our_env;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child */
|
||||
uv__process_child_init(options, stdio_count, pipes);
|
||||
|
||||
/* Execution never reaches here. */
|
||||
}
|
||||
|
||||
/* Parent. */
|
||||
|
||||
/* Restore environment. */
|
||||
environ = save_our_env;
|
||||
|
||||
#if SPAWN_WAIT_EXEC
|
||||
/* POLLHUP signals child has exited or execve()'d. */
|
||||
close(signal_pipe[1]);
|
||||
do {
|
||||
pfd.fd = signal_pipe[0];
|
||||
pfd.events = POLLIN|POLLHUP;
|
||||
pfd.revents = 0;
|
||||
errno = 0, status = poll(&pfd, 1, -1);
|
||||
}
|
||||
while (status == -1 && (errno == EINTR || errno == ENOMEM));
|
||||
|
||||
assert((status == 1) && "poll() on pipe read end failed");
|
||||
close(signal_pipe[0]);
|
||||
#endif
|
||||
|
||||
process->pid = pid;
|
||||
|
||||
ev_child_init(&process->child_watcher, uv__chld, pid, 0);
|
||||
ev_child_start(process->loop->ev, &process->child_watcher);
|
||||
process->child_watcher.data = process;
|
||||
|
||||
for (i = 0; i < options.stdio_count; i++) {
|
||||
if (uv__process_open_stream(&options.stdio[i], pipes + i * 2, i == 0)) {
|
||||
int j;
|
||||
/* Close all opened streams */
|
||||
for (j = 0; j < i; j++) {
|
||||
uv__process_close_stream(&options.stdio[j]);
|
||||
}
|
||||
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
free(pipes);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
uv__set_sys_error(process->loop, errno);
|
||||
|
||||
for (i = 0; i < stdio_count; i++) {
|
||||
close(pipes[i * 2]);
|
||||
close(pipes[i * 2 + 1]);
|
||||
}
|
||||
|
||||
free(pipes);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int uv_process_kill(uv_process_t* process, int signum) {
|
||||
int r = kill(process->pid, signum);
|
||||
|
||||
if (r) {
|
||||
uv__set_sys_error(process->loop, errno);
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_kill(int pid, int signum) {
|
||||
int r = kill(pid, signum);
|
||||
|
||||
if (r) {
|
||||
return uv__new_sys_error(errno);
|
||||
} else {
|
||||
return uv_ok_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uv__process_close(uv_process_t* handle) {
|
||||
ev_child_stop(handle->loop->ev, &handle->child_watcher);
|
||||
uv__handle_stop(handle);
|
||||
}
|
||||
129
samples/C/rdiscount.c
Normal file
129
samples/C/rdiscount.c
Normal file
@@ -0,0 +1,129 @@
|
||||
#include <stdio.h>
|
||||
#include "ruby.h"
|
||||
#include "mkdio.h"
|
||||
|
||||
static VALUE rb_cRDiscount;
|
||||
|
||||
static VALUE
|
||||
rb_rdiscount_to_html(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
/* grab char pointer to markdown input text */
|
||||
char *res;
|
||||
int szres;
|
||||
VALUE encoding;
|
||||
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
||||
VALUE buf = rb_str_buf_new(1024);
|
||||
Check_Type(text, T_STRING);
|
||||
|
||||
int flags = rb_rdiscount__get_flags(self);
|
||||
|
||||
MMIOT *doc = mkd_string(RSTRING_PTR(text), RSTRING_LEN(text), flags);
|
||||
|
||||
if ( mkd_compile(doc, flags) ) {
|
||||
szres = mkd_document(doc, &res);
|
||||
|
||||
if ( szres != EOF ) {
|
||||
rb_str_cat(buf, res, szres);
|
||||
rb_str_cat(buf, "\n", 1);
|
||||
}
|
||||
}
|
||||
mkd_cleanup(doc);
|
||||
|
||||
|
||||
/* force the input encoding */
|
||||
if ( rb_respond_to(text, rb_intern("encoding")) ) {
|
||||
encoding = rb_funcall(text, rb_intern("encoding"), 0);
|
||||
rb_funcall(buf, rb_intern("force_encoding"), 1, encoding);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_rdiscount_toc_content(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
char *res;
|
||||
int szres;
|
||||
|
||||
int flags = rb_rdiscount__get_flags(self);
|
||||
|
||||
/* grab char pointer to markdown input text */
|
||||
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
||||
Check_Type(text, T_STRING);
|
||||
|
||||
/* allocate a ruby string buffer and wrap it in a stream */
|
||||
VALUE buf = rb_str_buf_new(4096);
|
||||
|
||||
MMIOT *doc = mkd_string(RSTRING_PTR(text), RSTRING_LEN(text), flags);
|
||||
|
||||
if ( mkd_compile(doc, flags) ) {
|
||||
szres = mkd_toc(doc, &res);
|
||||
|
||||
if ( szres != EOF ) {
|
||||
rb_str_cat(buf, res, szres);
|
||||
rb_str_cat(buf, "\n", 1);
|
||||
}
|
||||
}
|
||||
mkd_cleanup(doc);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int rb_rdiscount__get_flags(VALUE ruby_obj)
|
||||
{
|
||||
/* compile flags */
|
||||
int flags = MKD_TABSTOP | MKD_NOHEADER;
|
||||
|
||||
/* smart */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("smart"), 0) != Qtrue )
|
||||
flags = flags | MKD_NOPANTS;
|
||||
|
||||
/* filter_html */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("filter_html"), 0) == Qtrue )
|
||||
flags = flags | MKD_NOHTML;
|
||||
|
||||
/* generate_toc */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("generate_toc"), 0) == Qtrue)
|
||||
flags = flags | MKD_TOC;
|
||||
|
||||
/* no_image */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("no_image"), 0) == Qtrue)
|
||||
flags = flags | MKD_NOIMAGE;
|
||||
|
||||
/* no_links */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("no_links"), 0) == Qtrue)
|
||||
flags = flags | MKD_NOLINKS;
|
||||
|
||||
/* no_tables */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("no_tables"), 0) == Qtrue)
|
||||
flags = flags | MKD_NOTABLES;
|
||||
|
||||
/* strict */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("strict"), 0) == Qtrue)
|
||||
flags = flags | MKD_STRICT;
|
||||
|
||||
/* autolink */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("autolink"), 0) == Qtrue)
|
||||
flags = flags | MKD_AUTOLINK;
|
||||
|
||||
/* safelink */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("safelink"), 0) == Qtrue)
|
||||
flags = flags | MKD_SAFELINK;
|
||||
|
||||
/* no_pseudo_protocols */
|
||||
if ( rb_funcall(ruby_obj, rb_intern("no_pseudo_protocols"), 0) == Qtrue)
|
||||
flags = flags | MKD_NO_EXT;
|
||||
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
void Init_rdiscount()
|
||||
{
|
||||
rb_cRDiscount = rb_define_class("RDiscount", rb_cObject);
|
||||
rb_define_method(rb_cRDiscount, "to_html", rb_rdiscount_to_html, -1);
|
||||
rb_define_method(rb_cRDiscount, "toc_content", rb_rdiscount_toc_content, -1);
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4: */
|
||||
2538
samples/C/redis.c
Normal file
2538
samples/C/redis.c
Normal file
File diff suppressed because it is too large
Load Diff
1267
samples/C/rf_io.c
Normal file
1267
samples/C/rf_io.c
Normal file
File diff suppressed because it is too large
Load Diff
682
samples/C/rf_io.h
Normal file
682
samples/C/rf_io.h
Normal file
@@ -0,0 +1,682 @@
|
||||
/**
|
||||
** Copyright (c) 2011-2012, Karapetsas Eleftherios
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
** 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the distribution.
|
||||
** 3. Neither the name of the Original Author of Refu nor the names of its contributors may be used to endorse or promote products derived from
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
** SERVICES;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**/
|
||||
|
||||
|
||||
#ifndef REFU_IO_H
|
||||
#define REFU_IO_H
|
||||
|
||||
#include <rf_setup.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{// opening bracket for calling from C++
|
||||
#endif
|
||||
|
||||
// New line feed
|
||||
#define RF_LF 0xA
|
||||
// Carriage Return
|
||||
#define RF_CR 0xD
|
||||
|
||||
#ifdef REFU_WIN32_VERSION
|
||||
#define i_PLUSB_WIN32 "b"
|
||||
#else
|
||||
#define i_PLUSB_WIN32 ""
|
||||
#endif
|
||||
|
||||
// This is the type that represents the file offset
|
||||
#ifdef _MSC_VER
|
||||
typedef __int64 foff_rft;
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
typedef off64_t foff_rft;
|
||||
#endif
|
||||
///Fseek and Ftelll definitions
|
||||
#ifdef _MSC_VER
|
||||
#define rfFseek(i_FILE_,i_OFFSET_,i_WHENCE_) _fseeki64(i_FILE_,i_OFFSET_,i_WHENCE_)
|
||||
#define rfFtell(i_FILE_) _ftelli64(i_FILE_)
|
||||
#else
|
||||
#define rfFseek(i_FILE_,i_OFFSET_,i_WHENCE_) fseeko64(i_FILE_,i_OFFSET_,i_WHENCE_)
|
||||
#define rfFtell(i_FILE_) ftello64(i_FILE_)
|
||||
#endif
|
||||
|
||||
/**
|
||||
** @defgroup RF_IOGRP I/O
|
||||
** @addtogroup RF_IOGRP
|
||||
** @{
|
||||
**/
|
||||
|
||||
// @brief Reads a UTF-8 file descriptor until end of line or EOF is found and returns a UTF-8 byte buffer
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// When the compile flag @c RF_NEWLINE_CRLF is defined (the default case at Windows) then this function
|
||||
// shall not be adding any CR character that is found in the file behind a newline character since this is
|
||||
// the Windows line ending scheme. Beware though that the returned read bytes value shall still count the CR character inside.
|
||||
//
|
||||
// @param[in] f The file descriptor to read
|
||||
// @param[out] utf8 Give here a refence to an unitialized char* that will be allocated inside the function
|
||||
// and contain the utf8 byte buffer. Needs to be freed by the caller explicitly later
|
||||
// @param[out] byteLength Give an @c uint32_t here to receive the length of the @c utf8 buffer in bytes
|
||||
// @param[out] bufferSize Give an @c uint32_t here to receive the capacity of the @c utf8 buffer in bytes
|
||||
// @param[out] eof Pass a pointer to a char to receive a true or false value in case the end of file
|
||||
// with reading this line
|
||||
// @return Returns either a positive number for success that represents the number of bytes read from @c f and and error in case something goes wrong.
|
||||
// The possible errors to return are the same as rfFgets_UTF8()
|
||||
i_DECLIMEX_ int32_t rfFReadLine_UTF8(FILE* f,char** utf8,uint32_t* byteLength,uint32_t* bufferSize,char* eof);
|
||||
// @brief Reads a Big Endian UTF-16 file descriptor until end of line or EOF is found and returns a UTF-8 byte buffer
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// When the compile flag @c RF_NEWLINE_CRLF is defined (the default case at Windows) then this function
|
||||
// shall not be adding any CR character that is found in the file behind a newline character since this is
|
||||
// the Windows line ending scheme. Beware though that the returned read bytes value shall still count the CR character inside.
|
||||
//
|
||||
// @param[in] f The file descriptor to read
|
||||
// @param[out] utf8 Give here a refence to an unitialized char* that will be allocated inside the function
|
||||
// and contain the utf8 byte buffer. Needs to be freed by the caller explicitly later
|
||||
// @param[out] byteLength Give an @c uint32_t here to receive the length of the @c utf8 buffer in bytes
|
||||
// @param[out] eof Pass a pointer to a char to receive a true or false value in case the end of file
|
||||
// with reading this line
|
||||
// @return Returns either a positive number for success that represents the number of bytes read from @c f and and error in case something goes wrong.
|
||||
// + Any error that can be returned by @ref rfFgets_UTF16BE()
|
||||
// + @c RE_UTF16_INVALID_SEQUENCE: Failed to decode the UTF-16 byte stream of the file descriptor
|
||||
// + @c RE_UTF8_ENCODING: Failed to encode the UTF-16 of the file descriptor into UTF-8
|
||||
i_DECLIMEX_ int32_t rfFReadLine_UTF16BE(FILE* f,char** utf8,uint32_t* byteLength,char* eof);
|
||||
// @brief Reads a Little Endian UTF-16 file descriptor until end of line or EOF is found and returns a UTF-8 byte buffer
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// When the compile flag @c RF_NEWLINE_CRLF is defined (the default case at Windows) then this function
|
||||
// shall not be adding any CR character that is found in the file behind a newline character since this is
|
||||
// the Windows line ending scheme. Beware though that the returned read bytes value shall still count the CR character inside.
|
||||
//
|
||||
// @param[in] f The file descriptor to read
|
||||
// @param[out] utf8 Give here a refence to an unitialized char* that will be allocated inside the function
|
||||
// and contain the utf8 byte buffer. Needs to be freed by the caller explicitly later
|
||||
// @param[out] byteLength Give an @c uint32_t here to receive the length of the @c utf8 buffer in bytes
|
||||
// @param[out] eof Pass a pointer to a char to receive a true or false value in case the end of file
|
||||
// with reading this line
|
||||
// @return Returns either a positive number for success that represents the number of bytes read from @c f and and error in case something goes wrong.
|
||||
// + Any error that can be returned by @ref rfFgets_UTF16LE()
|
||||
// + @c RE_UTF16_INVALID_SEQUENCE: Failed to decode the UTF-16 byte stream of the file descriptor
|
||||
// + @c RE_UTF8_ENCODING: Failed to encode the UTF-16 of the file descriptor into UTF-8
|
||||
i_DECLIMEX_ int32_t rfFReadLine_UTF16LE(FILE* f,char** utf8,uint32_t* byteLength,char* eof);
|
||||
|
||||
// @brief Reads a Big Endian UTF-32 file descriptor until end of line or EOF is found and returns a UTF-8 byte buffer
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// When the compile flag @c RF_NEWLINE_CRLF is defined (the default case at Windows) then this function
|
||||
// shall not be adding any CR character that is found in the file behind a newline character since this is
|
||||
// the Windows line ending scheme. Beware though that the returned read bytes value shall still count the CR character inside.
|
||||
//
|
||||
// @param[in] f The file descriptor to read
|
||||
// @param[out] utf8 Give here a refence to an unitialized char* that will be allocated inside the function
|
||||
// and contain the utf8 byte buffer. Needs to be freed by the caller explicitly later
|
||||
// @param[out] byteLength Give an @c uint32_t here to receive the length of the @c utf8 buffer in bytes
|
||||
// @param[out] eof Pass a pointer to a char to receive a true or false value in case the end of file
|
||||
// with reading this line
|
||||
// @return Returns either a positive number for success that represents the number of bytes read from @c f and and error in case something goes wrong.
|
||||
// + Any error that can be returned by @ref rfFgets_UTF32BE()
|
||||
// + @c RE_UTF8_ENCODING: Failed to encode the UTF-16 of the file descriptor into UTF-8
|
||||
i_DECLIMEX_ int32_t rfFReadLine_UTF32BE(FILE* f,char** utf8,uint32_t* byteLength,char* eof);
|
||||
// @brief Reads a Little Endian UTF-32 file descriptor until end of line or EOF is found and returns a UTF-8 byte buffer
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// When the compile flag @c RF_NEWLINE_CRLF is defined (the default case at Windows) then this function
|
||||
// shall not be adding any CR character that is found in the file behind a newline character since this is
|
||||
// the Windows line ending scheme. Beware though that the returned read bytes value shall still count the CR character inside.
|
||||
//
|
||||
// @param[in] f The file descriptor to read
|
||||
// @param[out] utf8 Give here a refence to an unitialized char* that will be allocated inside the function
|
||||
// and contain the utf8 byte buffer. Needs to be freed by the caller explicitly later
|
||||
// @param[out] byteLength Give an @c uint32_t here to receive the length of the @c utf8 buffer in bytes
|
||||
// @param[out] eof Pass a pointer to a char to receive a true or false value in case the end of file
|
||||
// with reading this line
|
||||
// @return Returns either a positive number for success that represents the number of bytes read from @c f and and error in case something goes wrong.
|
||||
// + Any error that can be returned by @ref rfFgets_UTF32LE()
|
||||
// + @c RE_UTF8_ENCODING: Failed to encode the UTF-16 of the file descriptor into UTF-8
|
||||
i_DECLIMEX_ int32_t rfFReadLine_UTF32LE(FILE* f,char** utf8,uint32_t* byteLength,char* eof);
|
||||
|
||||
// @brief Gets a number of bytes from a BIG endian UTF-32 file descriptor
|
||||
//
|
||||
// This is a function that's similar to c library fgets but it also returns the number of bytes read. Reads in from the file until @c num bytes
|
||||
// have been read or new line or EOF character has been encountered.
|
||||
//
|
||||
// The function will read until @c num characters are read and if @c num
|
||||
// would take us to the middle of a UTF32 character then the next character shall also be read
|
||||
// and the function will return the number of bytes read.
|
||||
// Since the function null terminates the buffer the given @c buff needs to be of at least
|
||||
// @c num+7 size to cater for the worst case.
|
||||
//
|
||||
// The final bytestream stored inside @c buff is in the endianess of the system.
|
||||
//
|
||||
// If right after the last character read comes the EOF, the function
|
||||
// shall detect so and assign @c true to @c eof.
|
||||
//
|
||||
// In Windows where file endings are in the form of 2 bytes CR-LF (Carriage return - NewLine) this function
|
||||
// shall just ignore the carriage returns and not return it inside the return buffer at @c buff.
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// @param[in] buff A buffer to be filled with the contents of the file. Should be of size at least @c num+7
|
||||
// @param[in] num The maximum number of bytes to read from within the file NOT including the null terminating character(which in itelf is 4 bytes). Should be a multiple of 4
|
||||
// @param[in] f A valid FILE descriptor from which to read the bytes
|
||||
// @param[out] eof Pass a reference to a char to receive a true/false value for whether EOF has been reached.
|
||||
// @return Returns the actual number of bytes read or an error if there was a problem.
|
||||
// The possible errors are:
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgets_UTF32BE(char* buff,uint32_t num,FILE* f,char* eof);
|
||||
// @brief Gets a number of bytes from a Little endian UTF-32 file descriptor
|
||||
//
|
||||
// This is a function that's similar to c library fgets but it also returns the number of bytes read. Reads in from the file until @c num bytes
|
||||
// have been read or new line or EOF character has been encountered.
|
||||
//
|
||||
// The function will read until @c num characters are read and if @c num
|
||||
// would take us to the middle of a UTF32 character then the next character shall also be read
|
||||
// and the function will return the number of bytes read.
|
||||
// Since the function null terminates the buffer the given @c buff needs to be of at least
|
||||
// @c num+7 size to cater for the worst case.
|
||||
//
|
||||
// The final bytestream stored inside @c buff is in the endianess of the system.
|
||||
//
|
||||
// If right after the last character read comes the EOF, the function
|
||||
// shall detect so and assign @c true to @c eof.
|
||||
//
|
||||
// In Windows where file endings are in the form of 2 bytes CR-LF (Carriage return - NewLine) this function
|
||||
// shall just ignore the carriage returns and not return it inside the return buffer at @c buff.
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// @param[in] buff A buffer to be filled with the contents of the file. Should be of size at least @c num+7
|
||||
// @param[in] num The maximum number of bytes to read from within the file NOT including the null terminating character(which in itelf is 4 bytes). Should be a multiple of 4
|
||||
// @param[in] f A valid FILE descriptor from which to read the bytes
|
||||
// @param[out] eof Pass a reference to a char to receive a true/false value for whether EOF has been reached.
|
||||
// @return Returns the actual number of bytes read or an error if there was a problem.
|
||||
// The possible errors are:
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgets_UTF32LE(char* buff,uint32_t num,FILE* f,char* eof);
|
||||
|
||||
// @brief Gets a number of bytes from a BIG endian UTF-16 file descriptor
|
||||
//
|
||||
// This is a function that's similar to c library fgets but it also returns the number of bytes read. Reads in from the file until @c num bytes
|
||||
// have been read or new line or EOF character has been encountered.
|
||||
//
|
||||
// The function will read until @c num characters are read and if @c num
|
||||
// would take us to the middle of a UTF16 character then the next character shall also be read
|
||||
// and the function will return the number of bytes read.
|
||||
// Since the function null terminates the buffer the given @c buff needs to be of at least
|
||||
// @c num+5 size to cater for the worst case.
|
||||
//
|
||||
// The final bytestream stored inside @c buff is in the endianess of the system.
|
||||
//
|
||||
// If right after the last character read comes the EOF, the function
|
||||
// shall detect so and assign @c true to @c eof.
|
||||
//
|
||||
// In Windows where file endings are in the form of 2 bytes CR-LF (Carriage return - NewLine) this function
|
||||
// shall just ignore the carriage returns and not return it inside the return buffer at @c buff.
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// @param[in] buff A buffer to be filled with the contents of the file. Should be of size at least @c num+5
|
||||
// @param[in] num The maximum number of bytes to read from within the file NOT including the null terminating character(which in itelf is 2 bytes). Should be a multiple of 2
|
||||
// @param[in] f A valid FILE descriptor from which to read the bytes
|
||||
// @param[out] eof Pass a reference to a char to receive a true/false value for whether EOF has been reached.
|
||||
// @return Returns the actual number of bytes read or an error if there was a problem.
|
||||
// The possible errors are:
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgets_UTF16BE(char* buff,uint32_t num,FILE* f,char* eof);
|
||||
// @brief Gets a number of bytes from a Little endian UTF-16 file descriptor
|
||||
//
|
||||
// This is a function that's similar to c library fgets but it also returns the number of bytes read. Reads in from the file until @c num bytes
|
||||
// have been read or new line or EOF character has been encountered.
|
||||
//
|
||||
// The function will read until @c num characters are read and if @c num
|
||||
// would take us to the middle of a UTF16 character then the next character shall also be read
|
||||
// and the function will return the number of bytes read.
|
||||
// Since the function null terminates the buffer the given @c buff needs to be of at least
|
||||
// @c num+5 size to cater for the worst case.
|
||||
//
|
||||
// The final bytestream stored inside @c buff is in the endianess of the system.
|
||||
//
|
||||
// If right after the last character read comes the EOF, the function
|
||||
// shall detect so and assign @c true to @c eof.
|
||||
//
|
||||
// In Windows where file endings are in the form of 2 bytes CR-LF (Carriage return - NewLine) this function
|
||||
// shall just ignore the carriage returns and not return it inside the return buffer at @c buff.
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// @param[in] buff A buffer to be filled with the contents of the file. Should be of size at least @c num+2
|
||||
// @param[in] num The maximum number of bytes to read from within the file NOT including the null terminating character(which in itelf is 2 bytes). Should be a multiple of 2
|
||||
// @param[in] f A valid FILE descriptor from which to read the bytes
|
||||
// @param[out] eof Pass a reference to a char to receive a true/false value for whether EOF has been reached.
|
||||
// @return Returns the actual number of bytes read or an error if there was a problem.
|
||||
// The possible errors are:
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgets_UTF16LE(char* buff,uint32_t num,FILE* f,char* eof);
|
||||
// @brief Gets a number of bytes from a UTF-8 file descriptor
|
||||
//
|
||||
// This is a function that's similar to c library fgets but it also returns the number of bytes read. Reads in from the file until @c num characters
|
||||
// have been read or new line or EOF character has been encountered.
|
||||
//
|
||||
// The function automatically adds a null termination character at the end of
|
||||
// @c buff but this character is not included in the returned actual number of bytes.
|
||||
//
|
||||
// The function will read until @c num characters are read and if @c num
|
||||
// would take us to the middle of a UTF8 character then the next character shall also be read
|
||||
// and the function will return the number of bytes read.
|
||||
// Since the function null terminates the buffer the given @c buff needs to be of at least
|
||||
// @c num+4 size to cater for the worst case.
|
||||
//
|
||||
// If right after the last character read comes the EOF, the function
|
||||
// shall detect so and assign @c true to @c eof.
|
||||
//
|
||||
// In Windows where file endings are in the form of 2 bytes CR-LF (Carriage return - NewLine) this function
|
||||
// shall just ignore the carriage returns and not return it inside the return buffer at @c buff.
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// @param[in] buff A buffer to be filled with the contents of the file. Should of size at least @c num+4
|
||||
// @param[in] num The maximum number of bytes to read from within the file NOT including the null terminating character(which in itelf is 1 byte)
|
||||
// @param[in] f A valid FILE descriptor from which to read the bytes
|
||||
// @param[out] eof Pass a reference to a char to receive a true/false value for whether EOF has been reached.
|
||||
// @return Returns the actual number of bytes read or an error if there was a problem.
|
||||
// The possible errors are:
|
||||
// + @c RE_UTF8_INVALID_SEQUENCE_INVALID_BYTE: If an invalid UTF-8 byte has been found
|
||||
// + @c RE_UTF8_INVALID_SEQUENCE_CONBYTE: If during parsing the file we were expecting a continuation
|
||||
// byte and did not find it
|
||||
// + @c RE_UTF8_INVALID_SEQUENCE_END: If the null character is encountered in between bytes that should
|
||||
// have been continuation bytes
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgets_UTF8(char* buff,uint32_t num,FILE* f,char* eof);
|
||||
|
||||
// @brief Gets a unicode character from a UTF-8 file descriptor
|
||||
//
|
||||
// This function attempts to assume a more modern fgetc() role for UTF-8 encoded files.
|
||||
// Reads bytes from the File descriptor @c f until a full UTF-8 unicode character has been read
|
||||
//
|
||||
// After this function the file pointer will have moved either by @c 1, @c 2, @c 3 or @c 4
|
||||
// bytes if the return value is positive. You can see how much by checking the return value.
|
||||
//
|
||||
// You shall need to provide an integer at @c c to contain either the decoded Unicode
|
||||
// codepoint or the UTF-8 endoced byte depending on the value of the @c cp argument.
|
||||
//
|
||||
// @param f A valid FILE descriptor from which to read the bytes
|
||||
// @param c Pass an int that will receive either the unicode code point value or
|
||||
// the UTF8 bytes depending on the value of the @c cp flag
|
||||
// @param cp A boolean flag. If @c true then the int passed at @c c will contain the unicode code point
|
||||
// of the read character, so the UTF-8 will be decoded.
|
||||
// If @c false the int passed at @c c will contain the value of the read bytes in UTF-8 without any decoding
|
||||
// @return Returns the number of bytes read (either @c 1, @c 2, @c 3 or @c 4) or an error if the function
|
||||
// fails for some reason. Possible error values are:
|
||||
// + @c RE_FILE_EOF: The end of file has been found while reading. If the end of file is encountered
|
||||
// in the middle of a UTF-8 encoded character where we would be expecting something different
|
||||
// and @c RE_UTF8_INVALID_SEQUENCE_END error is also logged
|
||||
// + @c RE_UTF8_INVALID_SEQUENCE_INVALID_BYTE: If an invalid UTF-8 byte has been found
|
||||
// + @c RE_UTF8_INVALID_SEQUENCE_CONBYTE: If during parsing the file we were expecting a continuation
|
||||
// byte and did not find it
|
||||
// + @c RE_UTF8_INVALID_SEQUENCE_END: If the null character is encountered in between bytes that should
|
||||
// have been continuation bytes
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgetc_UTF8(FILE* f,uint32_t *c,char cp);
|
||||
// @brief Gets a unicode character from a UTF-16 Big Endian file descriptor
|
||||
//
|
||||
// This function attempts to assume a more modern fgetc() role for UTF-16 encoded files.
|
||||
// Reads bytes from the File descriptor @c f until a full UTF-16 unicode character has been read
|
||||
//
|
||||
// After this function the file pointer will have moved either by @c 2 or @c 4
|
||||
// bytes if the return value is positive. You can see how much by checking the return value.
|
||||
//
|
||||
// You shall need to provide an integer at @c c to contain either the decoded Unicode
|
||||
// codepoint or the Bigendian encoded UTF-16 bytes depending on the value of @c the cp argument.
|
||||
//
|
||||
// @param f A valid FILE descriptor from which to read the bytes
|
||||
// @param c Pass an int that will receive either the unicode code point value or
|
||||
// the UTF16 bytes depending on the value of the @c cp flag
|
||||
// @param cp A boolean flag. If @c true then the int passed at @c c will contain the unicode code point
|
||||
// of the read character, so the UTF-16 will be decoded.
|
||||
// If @c false the int passed at @c c will contain the value of the read bytes in UTF-16 without any decoding
|
||||
// @return Returns the number of bytes read (either @c 2 or @c 4) or an error if the function
|
||||
// fails for some reason. Possible error values are:
|
||||
// + @c RE_UTF16_INVALID_SEQUENCE: Either the read word or its surrogate pair if 4 bytes were read held illegal values
|
||||
// + @c RE_UTF16_NO_SURRPAIR: According to the first read word a surrogate pair was expected but none was found
|
||||
// + @c RE_FILE_EOF: The end of file has been found while reading. If the end of file is encountered
|
||||
// while we expect a UTF-16 surrogate pair an appropriate error is logged
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgetc_UTF16BE(FILE* f,uint32_t *c,char cp);
|
||||
// @brief Gets a unicode character from a UTF-16 Little Endian file descriptor
|
||||
//
|
||||
// This function attempts to assume a more modern fgetc() role for UTF-16 encoded files.
|
||||
// Reads bytes from the File descriptor @c f until a full UTF-16 unicode character has been read
|
||||
//
|
||||
// After this function the file pointer will have moved either by @c 2 or @c 4
|
||||
// bytes if the return value is positive. You can see how much by checking the return value.
|
||||
//
|
||||
// You shall need to provide an integer at @c c to contain either the decoded Unicode
|
||||
// codepoint or the Bigendian encoded UTF-16 bytes depending on the value of @c the cp argument.
|
||||
//
|
||||
// @param f A valid FILE descriptor from which to read the bytes
|
||||
// @param c Pass an int that will receive either the unicode code point value or
|
||||
// the UTF16 bytes depending on the value of the @c cp flag
|
||||
// @param cp A boolean flag. If @c true then the int passed at @c c will contain the unicode code point
|
||||
// of the read character, so the UTF-16 will be decoded.
|
||||
// If @c false the int passed at @c c will contain the value of the read bytes in UTF-16 without any decoding
|
||||
// @return Returns the number of bytes read (either @c 2 or @c 4) or an error if the function
|
||||
// fails for some reason. Possible error values are:
|
||||
// + @c RE_UTF16_INVALID_SEQUENCE: Either the read word or its surrogate pair if 4 bytes were read held illegal values
|
||||
// + @c RE_UTF16_NO_SURRPAIR: According to the first read word a surrogate pair was expected but none was found
|
||||
// + @c RE_FILE_EOF: The end of file has been found while reading. If the end of file is encountered
|
||||
// while we expect a UTF-16 surrogate pair an appropriate error is logged
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgetc_UTF16LE(FILE* f,uint32_t *c,char cp);
|
||||
// @brief Gets a unicode character from a UTF-32 Little Endian file descriptor
|
||||
//
|
||||
// This function attempts to assume a more modern fgetc() role for UTF-32 encoded files.
|
||||
// Reads bytes from the File descriptor @c f until a full UTF-32 unicode character has been read
|
||||
//
|
||||
// After this function the file pointer will have moved by @c 4
|
||||
// bytes if the return value is positive.
|
||||
//
|
||||
// You shall need to provide an integer at @c to contain the UTF-32 codepoint.
|
||||
//
|
||||
// @param f A valid FILE descriptor from which to read the bytes
|
||||
// @param c Pass an int that will receive either the unicode code point value or
|
||||
// the UTF16 bytes depending on the value of the @c cp flag
|
||||
// If @c false the int passed at @c c will contain the value of the read bytes in UTF-16 without any decoding
|
||||
// @return Returns either @c RF_SUCCESS for succesfull readin or one of the following errors:
|
||||
// + @c RE_FILE_EOF: The end of file has been found while reading.
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgetc_UTF32LE(FILE* f,uint32_t *c);
|
||||
// @brief Gets a unicode character from a UTF-32 Big Endian file descriptor
|
||||
//
|
||||
// This function attempts to assume a more modern fgetc() role for UTF-32 encoded files.
|
||||
// Reads bytes from the File descriptor @c f until a full UTF-32 unicode character has been read
|
||||
//
|
||||
// After this function the file pointer will have moved by @c 4
|
||||
// bytes if the return value is positive.
|
||||
//
|
||||
// You shall need to provide an integer at @c to contain the UTF-32 codepoint.
|
||||
//
|
||||
// @param f A valid FILE descriptor from which to read the bytes
|
||||
// @param c Pass an int that will receive either the unicode code point value or
|
||||
// the UTF16 bytes depending on the value of the @c cp flag
|
||||
// If @c false the int passed at @c c will contain the value of the read bytes in UTF-16 without any decoding
|
||||
// @return Returns either @c RF_SUCCESS for succesfull readin or one of the following errors:
|
||||
// + @c RE_FILE_EOF: The end of file has been found while reading.
|
||||
// + @c RE_FILE_READ: If during reading the file there was an unknown read error
|
||||
// + @c RE_FILE_READ_BLOCK: If the read operation failed due to the file descriptor being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the file descriptor's mode was not correctly set for reading
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during reading, the current file position can't be represented by the system
|
||||
// + @c RE_INTERRUPT: If during reading, there was a system interrupt
|
||||
// + @c RE_FILE_IO: If there was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: If reading failed due to insufficient storage space
|
||||
i_DECLIMEX_ int32_t rfFgetc_UTF32BE(FILE* f,uint32_t *c);
|
||||
|
||||
// @brief Moves a unicode character backwards in a big endian UTF-32 file stream
|
||||
//
|
||||
// @param f The file stream
|
||||
// @param c Returns the character we moved back to as a unicode codepoint
|
||||
// @return Returns either @c RF_SUCCESS for success or one of the following errors:
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during trying to read the current file's position it can't be represented by the system
|
||||
// + @c RE_FILE_BAD: If The file descriptor is corrupt/illegal
|
||||
// + @c RE_FILE_NOTFILE: If the file descriptor is not a file but something else. e.g. socket.
|
||||
// + @c RE_FILE_GETFILEPOS: If the file's position could not be retrieved for some unknown reason
|
||||
// + @c RE_FILE_WRITE_BLOCK: While attempting to move the file pointer, it was occupied by another thread, and the no block flag was set
|
||||
// + @c RE_INTERRUPT: Operating on the file failed due to a system interrupt
|
||||
// + @c RE_FILE_IO: There was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: There was no space on the device holding the file
|
||||
// + @c RE_FILE_NOTFILE: The device we attempted to manipulate is non-existent
|
||||
// + @c RE_FILE_READ: If during reading the file there was an error
|
||||
// + @c RE_FILE_READ_BLOCK: If during reading the file the read operation failed due to the file being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the underlying file descriptor's mode was not correctly set for reading
|
||||
i_DECLIMEX_ int32_t rfFback_UTF32BE(FILE* f,uint32_t *c);
|
||||
// @brief Moves a unicode character backwards in a little endian UTF-32 file stream
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// @param f The file stream
|
||||
// @param c Returns the character we moved back to as a unicode codepoint
|
||||
// @return Returns either @c RF_SUCCESS for success or one of the following errors:
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during trying to read the current file's position it can't be represented by the system
|
||||
// + @c RE_FILE_BAD: If The file descriptor is corrupt/illegal
|
||||
// + @c RE_FILE_NOTFILE: If the file descriptor is not a file but something else. e.g. socket.
|
||||
// + @c RE_FILE_GETFILEPOS: If the file's position could not be retrieved for some unknown reason
|
||||
// + @c RE_FILE_WRITE_BLOCK: While attempting to move the file pointer, it was occupied by another thread, and the no block flag was set
|
||||
// + @c RE_INTERRUPT: Operating on the file failed due to a system interrupt
|
||||
// + @c RE_FILE_IO: There was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: There was no space on the device holding the file
|
||||
// + @c RE_FILE_NOTFILE: The device we attempted to manipulate is non-existent
|
||||
// + @c RE_FILE_READ: If during reading the file there was an error
|
||||
// + @c RE_FILE_READ_BLOCK: If during reading the file the read operation failed due to the file being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the underlying file descriptor's mode was not correctly set for reading
|
||||
i_DECLIMEX_ int32_t rfFback_UTF32LE(FILE* f,uint32_t *c);
|
||||
// @brief Moves a unicode character backwards in a big endian UTF-16 file stream
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// @param f The file stream
|
||||
// @param c Returns the character we moved back to as a unicode codepoint
|
||||
// @return Returns either the number of bytes moved backwards (either @c 4 or @c 2) for success or one of the following errors:
|
||||
// + @c RE_UTF16_INVALID_SEQUENCE: Either the read word or its surrogate pair if 4 bytes were read held illegal values
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during trying to read the current file's position it can't be represented by the system
|
||||
// + @c RE_FILE_BAD: If The file descriptor is corrupt/illegal
|
||||
// + @c RE_FILE_NOTFILE: If the file descriptor is not a file but something else. e.g. socket.
|
||||
// + @c RE_FILE_GETFILEPOS: If the file's position could not be retrieved for some unknown reason
|
||||
// + @c RE_FILE_WRITE_BLOCK: While attempting to move the file pointer, it was occupied by another thread, and the no block flag was set
|
||||
// + @c RE_INTERRUPT: Operating on the file failed due to a system interrupt
|
||||
// + @c RE_FILE_IO: There was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: There was no space on the device holding the file
|
||||
// + @c RE_FILE_NOTFILE: The device we attempted to manipulate is non-existent
|
||||
// + @c RE_FILE_READ: If during reading the file there was an error
|
||||
// + @c RE_FILE_READ_BLOCK: If during reading the file the read operation failed due to the file being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the underlying file descriptor's mode was not correctly set for reading
|
||||
i_DECLIMEX_ int32_t rfFback_UTF16BE(FILE* f,uint32_t *c);
|
||||
// @brief Moves a unicode character backwards in a little endian UTF-16 file stream
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// @param f The file stream
|
||||
// @param c Returns the character we moved back to as a unicode codepoint
|
||||
// @return Returns either the number of bytes moved backwards (either @c 4 or @c 2) for success or one of the following errors:
|
||||
// + @c RE_UTF16_INVALID_SEQUENCE: Either the read word or its surrogate pair if 4 bytes were read held illegal values
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during trying to read the current file's position it can't be represented by the system
|
||||
// + @c RE_FILE_BAD: If The file descriptor is corrupt/illegal
|
||||
// + @c RE_FILE_NOTFILE: If the file descriptor is not a file but something else. e.g. socket.
|
||||
// + @c RE_FILE_GETFILEPOS: If the file's position could not be retrieved for some unknown reason
|
||||
// + @c RE_FILE_WRITE_BLOCK: While attempting to move the file pointer, it was occupied by another thread, and the no block flag was set
|
||||
// + @c RE_INTERRUPT: Operating on the file failed due to a system interrupt
|
||||
// + @c RE_FILE_IO: There was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: There was no space on the device holding the file
|
||||
// + @c RE_FILE_NOTFILE: The device we attempted to manipulate is non-existent
|
||||
// + @c RE_FILE_READ: If during reading the file there was an error
|
||||
// + @c RE_FILE_READ_BLOCK: If during reading the file the read operation failed due to the file being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the underlying file descriptor's mode was not correctly set for reading
|
||||
i_DECLIMEX_ int32_t rfFback_UTF16LE(FILE* f,uint32_t *c);
|
||||
// @brief Moves a unicode character backwards in a UTF-8 file stream
|
||||
//
|
||||
// The file descriptor at @c f must have been opened in <b>binary</b> and not text mode. That means that if under
|
||||
// Windows make sure to call fopen with "wb", "rb" e.t.c. instead of the simple "w", "r" e.t.c. since the initial
|
||||
// default value under Windows is text mode. Alternatively you can set the initial value using _get_fmode() and
|
||||
// _set_fmode(). For more information take a look at the msdn pages here:
|
||||
// http://msdn.microsoft.com/en-us/library/ktss1a9b.aspx
|
||||
//
|
||||
// @param f The file stream
|
||||
// @param c Returns the character we moved back to as a unicode codepoint
|
||||
// @return Returns either the number of bytes moved backwards for success (either @c 4, @c 3, @c 2 or @c 1) or one of the following errors:
|
||||
// + @c RE_UTF8_INVALID_SEQUENCE: If during moving bacwards in the file unexpected UTF-8 bytes were found
|
||||
// + @c RE_FILE_POS_OVERFLOW: If during trying to read the current file's position it can't be represented by the system
|
||||
// + @c RE_FILE_BAD: If The file descriptor is corrupt/illegal
|
||||
// + @c RE_FILE_NOTFILE: If the file descriptor is not a file but something else. e.g. socket.
|
||||
// + @c RE_FILE_GETFILEPOS: If the file's position could not be retrieved for some unknown reason
|
||||
// + @c RE_FILE_WRITE_BLOCK: While attempting to move the file pointer, it was occupied by another thread, and the no block flag was set
|
||||
// + @c RE_INTERRUPT: Operating on the file failed due to a system interrupt
|
||||
// + @c RE_FILE_IO: There was a physical I/O error
|
||||
// + @c RE_FILE_NOSPACE: There was no space on the device holding the file
|
||||
// + @c RE_FILE_NOTFILE: The device we attempted to manipulate is non-existent
|
||||
// + @c RE_FILE_READ: If during reading the file there was an error
|
||||
// + @c RE_FILE_READ_BLOCK: If during reading the file the read operation failed due to the file being occupied by another thread
|
||||
// + @c RE_FILE_MODE: If during reading the file the underlying file descriptor's mode was not correctly set for reading
|
||||
i_DECLIMEX_ int32_t rfFback_UTF8(FILE* f,uint32_t *c);
|
||||
|
||||
// @brief Opens another process as a pipe
|
||||
//
|
||||
// This function is a cross-platform popen wrapper. In linux it uses popen and in Windows it uses
|
||||
// _popen.
|
||||
// @lmsFunction
|
||||
// @param command The string with the command to execute. Is basically the name of the program/process you want to spawn
|
||||
// with its full path and its parameters. @inhtype{String,StringX} @tmpSTR
|
||||
// @param mode The mode you want the pipe to work in. There are two possible values:
|
||||
// + @c "r" The calling process can read the spawned command's standard output via the returned stream.
|
||||
// + @c "w" The calling process can write to the spawned command's standard input via the returned stream.
|
||||
//
|
||||
// Anything else will result in an error
|
||||
// @return For success popen will return a FILE descriptor that can be used to either read or write from the pipe.
|
||||
// If there was an error @c 0 is returned and an error is logged.
|
||||
#ifdef RF_IAMHERE_FOR_DOXYGEN
|
||||
i_DECLIMEX_ FILE* rfPopen(void* command,const char* mode);
|
||||
#else
|
||||
i_DECLIMEX_ FILE* i_rfPopen(void* command,const char* mode);
|
||||
#define rfPopen(i_CMD_,i_MODE_) i_rfLMS_WRAP2(FILE*,i_rfPopen,i_CMD_,i_MODE_)
|
||||
#endif
|
||||
|
||||
// @brief Closes a pipe
|
||||
//
|
||||
// This function is a cross-platform wrapper for pclose. It closes a file descriptor opened with @ref rfPopen() and
|
||||
// returns the exit code of the process that was running
|
||||
// @param stream The file descriptor of the pipe returned by @ref rfPopen() that we want to close
|
||||
// @return Returns the exit code of the process or -1 if there was an error
|
||||
i_DECLIMEX_ int rfPclose(FILE* stream);
|
||||
|
||||
// @} End of I/O group
|
||||
|
||||
#ifdef __cplusplus
|
||||
}///closing bracket for calling from C++
|
||||
#endif
|
||||
|
||||
|
||||
#endif//include guards end
|
||||
2348
samples/C/rfc_string.c
Normal file
2348
samples/C/rfc_string.c
Normal file
File diff suppressed because it is too large
Load Diff
1459
samples/C/rfc_string.h
Normal file
1459
samples/C/rfc_string.h
Normal file
File diff suppressed because it is too large
Load Diff
15669
samples/C/sgd_fast.c
Normal file
15669
samples/C/sgd_fast.c
Normal file
File diff suppressed because it is too large
Load Diff
1363
samples/C/wglew.h
Normal file
1363
samples/C/wglew.h
Normal file
File diff suppressed because it is too large
Load Diff
164
samples/C/yajl.c
Normal file
164
samples/C/yajl.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2010, Lloyd Hilaiel.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. Neither the name of Lloyd Hilaiel nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "api/yajl_parse.h"
|
||||
#include "yajl_lex.h"
|
||||
#include "yajl_parser.h"
|
||||
#include "yajl_alloc.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
const char *
|
||||
yajl_status_to_string(yajl_status stat)
|
||||
{
|
||||
const char * statStr = "unknown";
|
||||
switch (stat) {
|
||||
case yajl_status_ok:
|
||||
statStr = "ok, no error";
|
||||
break;
|
||||
case yajl_status_client_canceled:
|
||||
statStr = "client canceled parse";
|
||||
break;
|
||||
case yajl_status_insufficient_data:
|
||||
statStr = "eof was met before the parse could complete";
|
||||
break;
|
||||
case yajl_status_error:
|
||||
statStr = "parse error";
|
||||
break;
|
||||
}
|
||||
return statStr;
|
||||
}
|
||||
|
||||
yajl_handle
|
||||
yajl_alloc(const yajl_callbacks * callbacks,
|
||||
const yajl_parser_config * config,
|
||||
const yajl_alloc_funcs * afs,
|
||||
void * ctx)
|
||||
{
|
||||
unsigned int allowComments = 0;
|
||||
unsigned int validateUTF8 = 0;
|
||||
yajl_handle hand = NULL;
|
||||
yajl_alloc_funcs afsBuffer;
|
||||
|
||||
/* first order of business is to set up memory allocation routines */
|
||||
if (afs != NULL) {
|
||||
if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
yajl_set_default_alloc_funcs(&afsBuffer);
|
||||
afs = &afsBuffer;
|
||||
}
|
||||
|
||||
hand = (yajl_handle) YA_MALLOC(afs, sizeof(struct yajl_handle_t));
|
||||
|
||||
/* copy in pointers to allocation routines */
|
||||
memcpy((void *) &(hand->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
|
||||
|
||||
if (config != NULL) {
|
||||
allowComments = config->allowComments;
|
||||
validateUTF8 = config->checkUTF8;
|
||||
}
|
||||
|
||||
hand->callbacks = callbacks;
|
||||
hand->ctx = ctx;
|
||||
hand->lexer = yajl_lex_alloc(&(hand->alloc), allowComments, validateUTF8);
|
||||
hand->bytesConsumed = 0;
|
||||
hand->decodeBuf = yajl_buf_alloc(&(hand->alloc));
|
||||
yajl_bs_init(hand->stateStack, &(hand->alloc));
|
||||
|
||||
yajl_bs_push(hand->stateStack, yajl_state_start);
|
||||
|
||||
return hand;
|
||||
}
|
||||
|
||||
void
|
||||
yajl_reset_parser(yajl_handle hand) {
|
||||
hand->lexer = yajl_lex_realloc(hand->lexer);
|
||||
}
|
||||
|
||||
void
|
||||
yajl_free(yajl_handle handle)
|
||||
{
|
||||
yajl_bs_free(handle->stateStack);
|
||||
yajl_buf_free(handle->decodeBuf);
|
||||
yajl_lex_free(handle->lexer);
|
||||
YA_FREE(&(handle->alloc), handle);
|
||||
}
|
||||
|
||||
yajl_status
|
||||
yajl_parse(yajl_handle hand, const unsigned char * jsonText,
|
||||
unsigned int jsonTextLen)
|
||||
{
|
||||
yajl_status status;
|
||||
status = yajl_do_parse(hand, jsonText, jsonTextLen);
|
||||
return status;
|
||||
}
|
||||
|
||||
yajl_status
|
||||
yajl_parse_complete(yajl_handle hand)
|
||||
{
|
||||
/* The particular case we want to handle is a trailing number.
|
||||
* Further input consisting of digits could cause our interpretation
|
||||
* of the number to change (buffered "1" but "2" comes in).
|
||||
* A very simple approach to this is to inject whitespace to terminate
|
||||
* any number in the lex buffer.
|
||||
*/
|
||||
return yajl_parse(hand, (const unsigned char *)" ", 1);
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
yajl_get_error(yajl_handle hand, int verbose,
|
||||
const unsigned char * jsonText, unsigned int jsonTextLen)
|
||||
{
|
||||
return yajl_render_error_string(hand, jsonText, jsonTextLen, verbose);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
yajl_get_bytes_consumed(yajl_handle hand)
|
||||
{
|
||||
if (!hand) return 0;
|
||||
else return hand->bytesConsumed;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
yajl_free_error(yajl_handle hand, unsigned char * str)
|
||||
{
|
||||
/* use memory allocation functions if set */
|
||||
YA_FREE(&(hand->alloc), str);
|
||||
}
|
||||
|
||||
/* XXX: add utility routines to parse from file */
|
||||
15
samples/Ceylon/Foo.ceylon
Normal file
15
samples/Ceylon/Foo.ceylon
Normal file
@@ -0,0 +1,15 @@
|
||||
doc "Test function for Ceylon"
|
||||
by "Enrique"
|
||||
shared void test() {
|
||||
print("test");
|
||||
}
|
||||
|
||||
doc "Test class for Ceylon"
|
||||
shared class Test(name) satisfies Comparable<Test> {
|
||||
shared String name;
|
||||
shared actual String string = "Test " name ".";
|
||||
|
||||
shared actual Comparison compare(Test other) {
|
||||
return name<=>other.name;
|
||||
}
|
||||
}
|
||||
55
samples/CoffeeScript/browser.coffee
Normal file
55
samples/CoffeeScript/browser.coffee
Normal file
@@ -0,0 +1,55 @@
|
||||
# Override exported methods for non-Node.js engines.
|
||||
|
||||
CoffeeScript = require './coffee-script'
|
||||
CoffeeScript.require = require
|
||||
|
||||
# Use standard JavaScript `eval` to eval code.
|
||||
CoffeeScript.eval = (code, options = {}) ->
|
||||
options.bare ?= on
|
||||
eval CoffeeScript.compile code, options
|
||||
|
||||
# Running code does not provide access to this scope.
|
||||
CoffeeScript.run = (code, options = {}) ->
|
||||
options.bare = on
|
||||
Function(CoffeeScript.compile code, options)()
|
||||
|
||||
# If we're not in a browser environment, we're finished with the public API.
|
||||
return unless window?
|
||||
|
||||
# Load a remote script from the current domain via XHR.
|
||||
CoffeeScript.load = (url, callback) ->
|
||||
xhr = new (window.ActiveXObject or XMLHttpRequest)('Microsoft.XMLHTTP')
|
||||
xhr.open 'GET', url, true
|
||||
xhr.overrideMimeType 'text/plain' if 'overrideMimeType' of xhr
|
||||
xhr.onreadystatechange = ->
|
||||
if xhr.readyState is 4
|
||||
if xhr.status in [0, 200]
|
||||
CoffeeScript.run xhr.responseText
|
||||
else
|
||||
throw new Error "Could not load #{url}"
|
||||
callback() if callback
|
||||
xhr.send null
|
||||
|
||||
# Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
# all script tags with a content-type of `text/coffeescript`.
|
||||
# This happens on page load.
|
||||
runScripts = ->
|
||||
scripts = document.getElementsByTagName 'script'
|
||||
coffees = (s for s in scripts when s.type is 'text/coffeescript')
|
||||
index = 0
|
||||
length = coffees.length
|
||||
do execute = ->
|
||||
script = coffees[index++]
|
||||
if script?.type is 'text/coffeescript'
|
||||
if script.src
|
||||
CoffeeScript.load script.src, execute
|
||||
else
|
||||
CoffeeScript.run script.innerHTML
|
||||
execute()
|
||||
null
|
||||
|
||||
# Listen for window load, both in browsers and in IE.
|
||||
if window.addEventListener
|
||||
addEventListener 'DOMContentLoaded', runScripts, no
|
||||
else
|
||||
attachEvent 'onload', runScripts
|
||||
21
samples/CoffeeScript/classes.coffee
Normal file
21
samples/CoffeeScript/classes.coffee
Normal file
@@ -0,0 +1,21 @@
|
||||
class Animal
|
||||
constructor: (@name) ->
|
||||
|
||||
move: (meters) ->
|
||||
alert @name + " moved " + meters + "m."
|
||||
|
||||
class Snake extends Animal
|
||||
move: ->
|
||||
alert "Slithering..."
|
||||
super 5
|
||||
|
||||
class Horse extends Animal
|
||||
move: ->
|
||||
alert "Galloping..."
|
||||
super 45
|
||||
|
||||
sam = new Snake "Sammy the Python"
|
||||
tom = new Horse "Tommy the Palomino"
|
||||
|
||||
sam.move()
|
||||
tom.move()
|
||||
130
samples/CoffeeScript/coffee-script.coffee
Normal file
130
samples/CoffeeScript/coffee-script.coffee
Normal file
@@ -0,0 +1,130 @@
|
||||
# CoffeeScript can be used both on the server, as a command-line compiler based
|
||||
# on Node.js/V8, or to run CoffeeScripts directly in the browser. This module
|
||||
# contains the main entry functions for tokenizing, parsing, and compiling
|
||||
# source CoffeeScript into JavaScript.
|
||||
#
|
||||
# If included on a webpage, it will automatically sniff out, compile, and
|
||||
# execute all scripts present in `text/coffeescript` tags.
|
||||
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
{Lexer,RESERVED} = require './lexer'
|
||||
{parser} = require './parser'
|
||||
vm = require 'vm'
|
||||
|
||||
# TODO: Remove registerExtension when fully deprecated.
|
||||
if require.extensions
|
||||
require.extensions['.coffee'] = (module, filename) ->
|
||||
content = compile fs.readFileSync(filename, 'utf8'), {filename}
|
||||
module._compile content, filename
|
||||
else if require.registerExtension
|
||||
require.registerExtension '.coffee', (content) -> compile content
|
||||
|
||||
# The current CoffeeScript version number.
|
||||
exports.VERSION = '1.3.3'
|
||||
|
||||
# Words that cannot be used as identifiers in CoffeeScript code
|
||||
exports.RESERVED = RESERVED
|
||||
|
||||
# Expose helpers for testing.
|
||||
exports.helpers = require './helpers'
|
||||
|
||||
# Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
# compiler.
|
||||
exports.compile = compile = (code, options = {}) ->
|
||||
{merge} = exports.helpers
|
||||
try
|
||||
js = (parser.parse lexer.tokenize code).compile options
|
||||
return js unless options.header
|
||||
catch err
|
||||
err.message = "In #{options.filename}, #{err.message}" if options.filename
|
||||
throw err
|
||||
header = "Generated by CoffeeScript #{@VERSION}"
|
||||
"// #{header}\n#{js}"
|
||||
|
||||
# Tokenize a string of CoffeeScript code, and return the array of tokens.
|
||||
exports.tokens = (code, options) ->
|
||||
lexer.tokenize code, options
|
||||
|
||||
# Parse a string of CoffeeScript code or an array of lexed tokens, and
|
||||
# return the AST. You can then compile it by calling `.compile()` on the root,
|
||||
# or traverse it by using `.traverseChildren()` with a callback.
|
||||
exports.nodes = (source, options) ->
|
||||
if typeof source is 'string'
|
||||
parser.parse lexer.tokenize source, options
|
||||
else
|
||||
parser.parse source
|
||||
|
||||
# Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
# setting `__filename`, `__dirname`, and relative `require()`.
|
||||
exports.run = (code, options = {}) ->
|
||||
mainModule = require.main
|
||||
|
||||
# Set the filename.
|
||||
mainModule.filename = process.argv[1] =
|
||||
if options.filename then fs.realpathSync(options.filename) else '.'
|
||||
|
||||
# Clear the module cache.
|
||||
mainModule.moduleCache and= {}
|
||||
|
||||
# Assign paths for node_modules loading
|
||||
mainModule.paths = require('module')._nodeModulePaths path.dirname fs.realpathSync options.filename
|
||||
|
||||
# Compile.
|
||||
if path.extname(mainModule.filename) isnt '.coffee' or require.extensions
|
||||
mainModule._compile compile(code, options), mainModule.filename
|
||||
else
|
||||
mainModule._compile code, mainModule.filename
|
||||
|
||||
# Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
|
||||
# The CoffeeScript REPL uses this to run the input.
|
||||
exports.eval = (code, options = {}) ->
|
||||
return unless code = code.trim()
|
||||
Script = vm.Script
|
||||
if Script
|
||||
if options.sandbox?
|
||||
if options.sandbox instanceof Script.createContext().constructor
|
||||
sandbox = options.sandbox
|
||||
else
|
||||
sandbox = Script.createContext()
|
||||
sandbox[k] = v for own k, v of options.sandbox
|
||||
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox
|
||||
else
|
||||
sandbox = global
|
||||
sandbox.__filename = options.filename || 'eval'
|
||||
sandbox.__dirname = path.dirname sandbox.__filename
|
||||
# define module/require only if they chose not to specify their own
|
||||
unless sandbox isnt global or sandbox.module or sandbox.require
|
||||
Module = require 'module'
|
||||
sandbox.module = _module = new Module(options.modulename || 'eval')
|
||||
sandbox.require = _require = (path) -> Module._load path, _module, true
|
||||
_module.filename = sandbox.__filename
|
||||
_require[r] = require[r] for r in Object.getOwnPropertyNames require when r isnt 'paths'
|
||||
# use the same hack node currently uses for their own REPL
|
||||
_require.paths = _module.paths = Module._nodeModulePaths process.cwd()
|
||||
_require.resolve = (request) -> Module._resolveFilename request, _module
|
||||
o = {}
|
||||
o[k] = v for own k, v of options
|
||||
o.bare = on # ensure return value
|
||||
js = compile code, o
|
||||
if sandbox is global
|
||||
vm.runInThisContext js
|
||||
else
|
||||
vm.runInContext js, sandbox
|
||||
|
||||
# Instantiate a Lexer for our use here.
|
||||
lexer = new Lexer
|
||||
|
||||
# The real Lexer produces a generic stream of tokens. This object provides a
|
||||
# thin wrapper around it, compatible with the Jison API. We can then pass it
|
||||
# directly as a "Jison lexer".
|
||||
parser.lexer =
|
||||
lex: ->
|
||||
[tag, @yytext, @yylineno] = @tokens[@pos++] or ['']
|
||||
tag
|
||||
setInput: (@tokens) ->
|
||||
@pos = 0
|
||||
upcomingInput: ->
|
||||
""
|
||||
|
||||
parser.yy = require './nodes'
|
||||
0
samples/CoffeeScript/empty.coffee
Normal file
0
samples/CoffeeScript/empty.coffee
Normal file
1
samples/CoffeeScript/hello.coffee
Normal file
1
samples/CoffeeScript/hello.coffee
Normal file
@@ -0,0 +1 @@
|
||||
console.log "Hello, World!"
|
||||
28
samples/CoffeeScript/intro.coffee
Normal file
28
samples/CoffeeScript/intro.coffee
Normal file
@@ -0,0 +1,28 @@
|
||||
# Assignment:
|
||||
number = 42
|
||||
opposite = true
|
||||
|
||||
# Conditions:
|
||||
number = -42 if opposite
|
||||
|
||||
# Functions:
|
||||
square = (x) -> x * x
|
||||
|
||||
# Arrays:
|
||||
list = [1, 2, 3, 4, 5]
|
||||
|
||||
# Objects:
|
||||
math =
|
||||
root: Math.sqrt
|
||||
square: square
|
||||
cube: (x) -> x * square x
|
||||
|
||||
# Splats:
|
||||
race = (winner, runners...) ->
|
||||
print winner, runners
|
||||
|
||||
# Existence:
|
||||
alert "I knew it!" if elvis?
|
||||
|
||||
# Array comprehensions:
|
||||
cubes = (math.cube num for num in list)
|
||||
709
samples/CoffeeScript/lexer.coffee
Normal file
709
samples/CoffeeScript/lexer.coffee
Normal file
@@ -0,0 +1,709 @@
|
||||
# The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
|
||||
# matches against the beginning of the source code. When a match is found,
|
||||
# a token is produced, we consume the match, and start again. Tokens are in the
|
||||
# form:
|
||||
#
|
||||
# [tag, value, lineNumber]
|
||||
#
|
||||
# Which is a format that can be fed directly into [Jison](http://github.com/zaach/jison).
|
||||
|
||||
{Rewriter, INVERSES} = require './rewriter'
|
||||
|
||||
# Import the helpers we need.
|
||||
{count, starts, compact, last} = require './helpers'
|
||||
|
||||
# The Lexer Class
|
||||
# ---------------
|
||||
|
||||
# The Lexer class reads a stream of CoffeeScript and divvies it up into tagged
|
||||
# tokens. Some potential ambiguity in the grammar has been avoided by
|
||||
# pushing some extra smarts into the Lexer.
|
||||
exports.Lexer = class Lexer
|
||||
|
||||
# **tokenize** is the Lexer's main method. Scan by attempting to match tokens
|
||||
# one at a time, using a regular expression anchored at the start of the
|
||||
# remaining code, or a custom recursive token-matching method
|
||||
# (for interpolations). When the next token has been recorded, we move forward
|
||||
# within the code past the token, and begin again.
|
||||
#
|
||||
# Each tokenizing method is responsible for returning the number of characters
|
||||
# it has consumed.
|
||||
#
|
||||
# Before returning the token stream, run it through the [Rewriter](rewriter.html)
|
||||
# unless explicitly asked not to.
|
||||
tokenize: (code, opts = {}) ->
|
||||
code = "\n#{code}" if WHITESPACE.test code
|
||||
code = code.replace(/\r/g, '').replace TRAILING_SPACES, ''
|
||||
|
||||
@code = code # The remainder of the source code.
|
||||
@line = opts.line or 0 # The current line.
|
||||
@indent = 0 # The current indentation level.
|
||||
@indebt = 0 # The over-indentation at the current level.
|
||||
@outdebt = 0 # The under-outdentation at the current level.
|
||||
@indents = [] # The stack of all current indentation levels.
|
||||
@ends = [] # The stack for pairing up tokens.
|
||||
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, line]`.
|
||||
|
||||
# At every position, run through this list of attempted matches,
|
||||
# short-circuiting if any of them succeed. Their order determines precedence:
|
||||
# `@literalToken` is the fallback catch-all.
|
||||
i = 0
|
||||
while @chunk = code[i..]
|
||||
i += @identifierToken() or
|
||||
@commentToken() or
|
||||
@whitespaceToken() or
|
||||
@lineToken() or
|
||||
@heredocToken() or
|
||||
@stringToken() or
|
||||
@numberToken() or
|
||||
@regexToken() or
|
||||
@jsToken() or
|
||||
@literalToken()
|
||||
|
||||
@closeIndentation()
|
||||
@error "missing #{tag}" if tag = @ends.pop()
|
||||
return @tokens if opts.rewrite is off
|
||||
(new Rewriter).rewrite @tokens
|
||||
|
||||
# Tokenizers
|
||||
# ----------
|
||||
|
||||
# Matches identifying literals: variables, keywords, method names, etc.
|
||||
# Check to ensure that JavaScript reserved words aren't being used as
|
||||
# identifiers. Because CoffeeScript reserves a handful of keywords that are
|
||||
# allowed in JavaScript, we're careful not to tag them as keywords when
|
||||
# referenced as property names here, so you can still do `jQuery.is()` even
|
||||
# though `is` means `===` otherwise.
|
||||
identifierToken: ->
|
||||
return 0 unless match = IDENTIFIER.exec @chunk
|
||||
[input, id, colon] = match
|
||||
|
||||
if id is 'own' and @tag() is 'FOR'
|
||||
@token 'OWN', id
|
||||
return id.length
|
||||
forcedIdentifier = colon or
|
||||
(prev = last @tokens) and (prev[0] in ['.', '?.', '::'] or
|
||||
not prev.spaced and prev[0] is '@')
|
||||
tag = 'IDENTIFIER'
|
||||
|
||||
if not forcedIdentifier and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS)
|
||||
tag = id.toUpperCase()
|
||||
if tag is 'WHEN' and @tag() in LINE_BREAK
|
||||
tag = 'LEADING_WHEN'
|
||||
else if tag is 'FOR'
|
||||
@seenFor = yes
|
||||
else if tag is 'UNLESS'
|
||||
tag = 'IF'
|
||||
else if tag in UNARY
|
||||
tag = 'UNARY'
|
||||
else if tag in RELATION
|
||||
if tag isnt 'INSTANCEOF' and @seenFor
|
||||
tag = 'FOR' + tag
|
||||
@seenFor = no
|
||||
else
|
||||
tag = 'RELATION'
|
||||
if @value() is '!'
|
||||
@tokens.pop()
|
||||
id = '!' + id
|
||||
|
||||
if id in JS_FORBIDDEN
|
||||
if forcedIdentifier
|
||||
tag = 'IDENTIFIER'
|
||||
id = new String id
|
||||
id.reserved = yes
|
||||
else if id in RESERVED
|
||||
@error "reserved word \"#{id}\""
|
||||
|
||||
unless forcedIdentifier
|
||||
id = COFFEE_ALIAS_MAP[id] if id in COFFEE_ALIASES
|
||||
tag = switch id
|
||||
when '!' then 'UNARY'
|
||||
when '==', '!=' then 'COMPARE'
|
||||
when '&&', '||' then 'LOGIC'
|
||||
when 'true', 'false' then 'BOOL'
|
||||
when 'break', 'continue' then 'STATEMENT'
|
||||
else tag
|
||||
|
||||
@token tag, id
|
||||
@token ':', ':' if colon
|
||||
input.length
|
||||
|
||||
# Matches numbers, including decimals, hex, and exponential notation.
|
||||
# Be careful not to interfere with ranges-in-progress.
|
||||
numberToken: ->
|
||||
return 0 unless match = NUMBER.exec @chunk
|
||||
number = match[0]
|
||||
if /^0[BOX]/.test number
|
||||
@error "radix prefix '#{number}' must be lowercase"
|
||||
else if /E/.test(number) and not /^0x/.test number
|
||||
@error "exponential notation '#{number}' must be indicated with a lowercase 'e'"
|
||||
else if /^0\d*[89]/.test number
|
||||
@error "decimal literal '#{number}' must not be prefixed with '0'"
|
||||
else if /^0\d+/.test number
|
||||
@error "octal literal '#{number}' must be prefixed with '0o'"
|
||||
lexedLength = number.length
|
||||
if octalLiteral = /^0o([0-7]+)/.exec number
|
||||
number = '0x' + (parseInt octalLiteral[1], 8).toString 16
|
||||
if binaryLiteral = /^0b([01]+)/.exec number
|
||||
number = '0x' + (parseInt binaryLiteral[1], 2).toString 16
|
||||
@token 'NUMBER', number
|
||||
lexedLength
|
||||
|
||||
# Matches strings, including multi-line strings. Ensures that quotation marks
|
||||
# are balanced within the string's contents, and within nested interpolations.
|
||||
stringToken: ->
|
||||
switch @chunk.charAt 0
|
||||
when "'"
|
||||
return 0 unless match = SIMPLESTR.exec @chunk
|
||||
@token 'STRING', (string = match[0]).replace MULTILINER, '\\\n'
|
||||
when '"'
|
||||
return 0 unless string = @balancedString @chunk, '"'
|
||||
if 0 < string.indexOf '#{', 1
|
||||
@interpolateString string[1...-1]
|
||||
else
|
||||
@token 'STRING', @escapeLines string
|
||||
else
|
||||
return 0
|
||||
if octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test string
|
||||
@error "octal escape sequences #{string} are not allowed"
|
||||
@line += count string, '\n'
|
||||
string.length
|
||||
|
||||
# Matches heredocs, adjusting indentation to the correct level, as heredocs
|
||||
# preserve whitespace, but ignore indentation to the left.
|
||||
heredocToken: ->
|
||||
return 0 unless match = HEREDOC.exec @chunk
|
||||
heredoc = match[0]
|
||||
quote = heredoc.charAt 0
|
||||
doc = @sanitizeHeredoc match[2], quote: quote, indent: null
|
||||
if quote is '"' and 0 <= doc.indexOf '#{'
|
||||
@interpolateString doc, heredoc: yes
|
||||
else
|
||||
@token 'STRING', @makeString doc, quote, yes
|
||||
@line += count heredoc, '\n'
|
||||
heredoc.length
|
||||
|
||||
# Matches and consumes comments.
|
||||
commentToken: ->
|
||||
return 0 unless match = @chunk.match COMMENT
|
||||
[comment, here] = match
|
||||
if here
|
||||
@token 'HERECOMMENT', @sanitizeHeredoc here,
|
||||
herecomment: true, indent: Array(@indent + 1).join(' ')
|
||||
@line += count comment, '\n'
|
||||
comment.length
|
||||
|
||||
# Matches JavaScript interpolated directly into the source via backticks.
|
||||
jsToken: ->
|
||||
return 0 unless @chunk.charAt(0) is '`' and match = JSTOKEN.exec @chunk
|
||||
@token 'JS', (script = match[0])[1...-1]
|
||||
script.length
|
||||
|
||||
# Matches regular expression literals. Lexing regular expressions is difficult
|
||||
# to distinguish from division, so we borrow some basic heuristics from
|
||||
# JavaScript and Ruby.
|
||||
regexToken: ->
|
||||
return 0 if @chunk.charAt(0) isnt '/'
|
||||
if match = HEREGEX.exec @chunk
|
||||
length = @heregexToken match
|
||||
@line += count match[0], '\n'
|
||||
return length
|
||||
|
||||
prev = last @tokens
|
||||
return 0 if prev and (prev[0] in (if prev.spaced then NOT_REGEX else NOT_SPACED_REGEX))
|
||||
return 0 unless match = REGEX.exec @chunk
|
||||
[match, regex, flags] = match
|
||||
if regex[..1] is '/*' then @error 'regular expressions cannot begin with `*`'
|
||||
if regex is '//' then regex = '/(?:)/'
|
||||
@token 'REGEX', "#{regex}#{flags}"
|
||||
match.length
|
||||
|
||||
# Matches multiline extended regular expressions.
|
||||
heregexToken: (match) ->
|
||||
[heregex, body, flags] = match
|
||||
if 0 > body.indexOf '#{'
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/')
|
||||
if re.match /^\*/ then @error 'regular expressions cannot begin with `*`'
|
||||
@token 'REGEX', "/#{ re or '(?:)' }/#{flags}"
|
||||
return heregex.length
|
||||
@token 'IDENTIFIER', 'RegExp'
|
||||
@tokens.push ['CALL_START', '(']
|
||||
tokens = []
|
||||
for [tag, value] in @interpolateString(body, regex: yes)
|
||||
if tag is 'TOKENS'
|
||||
tokens.push value...
|
||||
else
|
||||
continue unless value = value.replace HEREGEX_OMIT, ''
|
||||
value = value.replace /\\/g, '\\\\'
|
||||
tokens.push ['STRING', @makeString(value, '"', yes)]
|
||||
tokens.push ['+', '+']
|
||||
tokens.pop()
|
||||
@tokens.push ['STRING', '""'], ['+', '+'] unless tokens[0]?[0] is 'STRING'
|
||||
@tokens.push tokens...
|
||||
@tokens.push [',', ','], ['STRING', '"' + flags + '"'] if flags
|
||||
@token ')', ')'
|
||||
heregex.length
|
||||
|
||||
# Matches newlines, indents, and outdents, and determines which is which.
|
||||
# If we can detect that the current line is continued onto the the next line,
|
||||
# then the newline is suppressed:
|
||||
#
|
||||
# elements
|
||||
# .each( ... )
|
||||
# .map( ... )
|
||||
#
|
||||
# Keeps track of the level of indentation, because a single outdent token
|
||||
# can close multiple indents, so we need to know how far in we happen to be.
|
||||
lineToken: ->
|
||||
return 0 unless match = MULTI_DENT.exec @chunk
|
||||
indent = match[0]
|
||||
@line += count indent, '\n'
|
||||
@seenFor = no
|
||||
size = indent.length - 1 - indent.lastIndexOf '\n'
|
||||
noNewlines = @unfinished()
|
||||
if size - @indebt is @indent
|
||||
if noNewlines then @suppressNewlines() else @newlineToken()
|
||||
return indent.length
|
||||
if size > @indent
|
||||
if noNewlines
|
||||
@indebt = size - @indent
|
||||
@suppressNewlines()
|
||||
return indent.length
|
||||
diff = size - @indent + @outdebt
|
||||
@token 'INDENT', diff
|
||||
@indents.push diff
|
||||
@ends.push 'OUTDENT'
|
||||
@outdebt = @indebt = 0
|
||||
else
|
||||
@indebt = 0
|
||||
@outdentToken @indent - size, noNewlines
|
||||
@indent = size
|
||||
indent.length
|
||||
|
||||
# Record an outdent token or multiple tokens, if we happen to be moving back
|
||||
# inwards past several recorded indents.
|
||||
outdentToken: (moveOut, noNewlines) ->
|
||||
while moveOut > 0
|
||||
len = @indents.length - 1
|
||||
if @indents[len] is undefined
|
||||
moveOut = 0
|
||||
else if @indents[len] is @outdebt
|
||||
moveOut -= @outdebt
|
||||
@outdebt = 0
|
||||
else if @indents[len] < @outdebt
|
||||
@outdebt -= @indents[len]
|
||||
moveOut -= @indents[len]
|
||||
else
|
||||
dent = @indents.pop() - @outdebt
|
||||
moveOut -= dent
|
||||
@outdebt = 0
|
||||
@pair 'OUTDENT'
|
||||
@token 'OUTDENT', dent
|
||||
@outdebt -= moveOut if dent
|
||||
@tokens.pop() while @value() is ';'
|
||||
@token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR' or noNewlines
|
||||
this
|
||||
|
||||
# Matches and consumes non-meaningful whitespace. Tag the previous token
|
||||
# as being "spaced", because there are some cases where it makes a difference.
|
||||
whitespaceToken: ->
|
||||
return 0 unless (match = WHITESPACE.exec @chunk) or
|
||||
(nline = @chunk.charAt(0) is '\n')
|
||||
prev = last @tokens
|
||||
prev[if match then 'spaced' else 'newLine'] = true if prev
|
||||
if match then match[0].length else 0
|
||||
|
||||
# Generate a newline token. Consecutive newlines get merged together.
|
||||
newlineToken: ->
|
||||
@tokens.pop() while @value() is ';'
|
||||
@token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR'
|
||||
this
|
||||
|
||||
# Use a `\` at a line-ending to suppress the newline.
|
||||
# The slash is removed here once its job is done.
|
||||
suppressNewlines: ->
|
||||
@tokens.pop() if @value() is '\\'
|
||||
this
|
||||
|
||||
# We treat all other single characters as a token. E.g.: `( ) , . !`
|
||||
# Multi-character operators are also literal tokens, so that Jison can assign
|
||||
# the proper order of operations. There are some symbols that we tag specially
|
||||
# here. `;` and newlines are both treated as a `TERMINATOR`, we distinguish
|
||||
# parentheses that indicate a method call from regular parentheses, and so on.
|
||||
literalToken: ->
|
||||
if match = OPERATOR.exec @chunk
|
||||
[value] = match
|
||||
@tagParameters() if CODE.test value
|
||||
else
|
||||
value = @chunk.charAt 0
|
||||
tag = value
|
||||
prev = last @tokens
|
||||
if value is '=' and prev
|
||||
if not prev[1].reserved and prev[1] in JS_FORBIDDEN
|
||||
@error "reserved word \"#{@value()}\" can't be assigned"
|
||||
if prev[1] in ['||', '&&']
|
||||
prev[0] = 'COMPOUND_ASSIGN'
|
||||
prev[1] += '='
|
||||
return value.length
|
||||
if value is ';'
|
||||
@seenFor = no
|
||||
tag = 'TERMINATOR'
|
||||
else if value in MATH then tag = 'MATH'
|
||||
else if value in COMPARE then tag = 'COMPARE'
|
||||
else if value in COMPOUND_ASSIGN then tag = 'COMPOUND_ASSIGN'
|
||||
else if value in UNARY then tag = 'UNARY'
|
||||
else if value in SHIFT then tag = 'SHIFT'
|
||||
else if value in LOGIC or value is '?' and prev?.spaced then tag = 'LOGIC'
|
||||
else if prev and not prev.spaced
|
||||
if value is '(' and prev[0] in CALLABLE
|
||||
prev[0] = 'FUNC_EXIST' if prev[0] is '?'
|
||||
tag = 'CALL_START'
|
||||
else if value is '[' and prev[0] in INDEXABLE
|
||||
tag = 'INDEX_START'
|
||||
switch prev[0]
|
||||
when '?' then prev[0] = 'INDEX_SOAK'
|
||||
switch value
|
||||
when '(', '{', '[' then @ends.push INVERSES[value]
|
||||
when ')', '}', ']' then @pair value
|
||||
@token tag, value
|
||||
value.length
|
||||
|
||||
# Token Manipulators
|
||||
# ------------------
|
||||
|
||||
# Sanitize a heredoc or herecomment by
|
||||
# erasing all external indentation on the left-hand side.
|
||||
sanitizeHeredoc: (doc, options) ->
|
||||
{indent, herecomment} = options
|
||||
if herecomment
|
||||
if HEREDOC_ILLEGAL.test doc
|
||||
@error "block comment cannot contain \"*/\", starting"
|
||||
return doc if doc.indexOf('\n') <= 0
|
||||
else
|
||||
while match = HEREDOC_INDENT.exec doc
|
||||
attempt = match[1]
|
||||
indent = attempt if indent is null or 0 < attempt.length < indent.length
|
||||
doc = doc.replace /// \n #{indent} ///g, '\n' if indent
|
||||
doc = doc.replace /^\n/, '' unless herecomment
|
||||
doc
|
||||
|
||||
# A source of ambiguity in our grammar used to be parameter lists in function
|
||||
# definitions versus argument lists in function calls. Walk backwards, tagging
|
||||
# parameters specially in order to make things easier for the parser.
|
||||
tagParameters: ->
|
||||
return this if @tag() isnt ')'
|
||||
stack = []
|
||||
{tokens} = this
|
||||
i = tokens.length
|
||||
tokens[--i][0] = 'PARAM_END'
|
||||
while tok = tokens[--i]
|
||||
switch tok[0]
|
||||
when ')'
|
||||
stack.push tok
|
||||
when '(', 'CALL_START'
|
||||
if stack.length then stack.pop()
|
||||
else if tok[0] is '('
|
||||
tok[0] = 'PARAM_START'
|
||||
return this
|
||||
else return this
|
||||
this
|
||||
|
||||
# Close up all remaining open blocks at the end of the file.
|
||||
closeIndentation: ->
|
||||
@outdentToken @indent
|
||||
|
||||
# Matches a balanced group such as a single or double-quoted string. Pass in
|
||||
# a series of delimiters, all of which must be nested correctly within the
|
||||
# contents of the string. This method allows us to have strings within
|
||||
# interpolations within strings, ad infinitum.
|
||||
balancedString: (str, end) ->
|
||||
continueCount = 0
|
||||
stack = [end]
|
||||
for i in [1...str.length]
|
||||
if continueCount
|
||||
--continueCount
|
||||
continue
|
||||
switch letter = str.charAt i
|
||||
when '\\'
|
||||
++continueCount
|
||||
continue
|
||||
when end
|
||||
stack.pop()
|
||||
unless stack.length
|
||||
return str[0..i]
|
||||
end = stack[stack.length - 1]
|
||||
continue
|
||||
if end is '}' and letter in ['"', "'"]
|
||||
stack.push end = letter
|
||||
else if end is '}' and letter is '/' and match = (HEREGEX.exec(str[i..]) or REGEX.exec(str[i..]))
|
||||
continueCount += match[0].length - 1
|
||||
else if end is '}' and letter is '{'
|
||||
stack.push end = '}'
|
||||
else if end is '"' and prev is '#' and letter is '{'
|
||||
stack.push end = '}'
|
||||
prev = letter
|
||||
@error "missing #{ stack.pop() }, starting"
|
||||
|
||||
# Expand variables and expressions inside double-quoted strings using
|
||||
# Ruby-like notation for substitution of arbitrary expressions.
|
||||
#
|
||||
# "Hello #{name.capitalize()}."
|
||||
#
|
||||
# If it encounters an interpolation, this method will recursively create a
|
||||
# new Lexer, tokenize the interpolated contents, and merge them into the
|
||||
# token stream.
|
||||
interpolateString: (str, options = {}) ->
|
||||
{heredoc, regex} = options
|
||||
tokens = []
|
||||
pi = 0
|
||||
i = -1
|
||||
while letter = str.charAt i += 1
|
||||
if letter is '\\'
|
||||
i += 1
|
||||
continue
|
||||
unless letter is '#' and str.charAt(i+1) is '{' and
|
||||
(expr = @balancedString str[i + 1..], '}')
|
||||
continue
|
||||
tokens.push ['NEOSTRING', str[pi...i]] if pi < i
|
||||
inner = expr[1...-1]
|
||||
if inner.length
|
||||
nested = new Lexer().tokenize inner, line: @line, rewrite: off
|
||||
nested.pop()
|
||||
nested.shift() if nested[0]?[0] is 'TERMINATOR'
|
||||
if len = nested.length
|
||||
if len > 1
|
||||
nested.unshift ['(', '(', @line]
|
||||
nested.push [')', ')', @line]
|
||||
tokens.push ['TOKENS', nested]
|
||||
i += expr.length
|
||||
pi = i + 1
|
||||
tokens.push ['NEOSTRING', str[pi..]] if i > pi < str.length
|
||||
return tokens if regex
|
||||
return @token 'STRING', '""' unless tokens.length
|
||||
tokens.unshift ['', ''] unless tokens[0][0] is 'NEOSTRING'
|
||||
@token '(', '(' if interpolated = tokens.length > 1
|
||||
for [tag, value], i in tokens
|
||||
@token '+', '+' if i
|
||||
if tag is 'TOKENS'
|
||||
@tokens.push value...
|
||||
else
|
||||
@token 'STRING', @makeString value, '"', heredoc
|
||||
@token ')', ')' if interpolated
|
||||
tokens
|
||||
|
||||
# Pairs up a closing token, ensuring that all listed pairs of tokens are
|
||||
# correctly balanced throughout the course of the token stream.
|
||||
pair: (tag) ->
|
||||
unless tag is wanted = last @ends
|
||||
@error "unmatched #{tag}" unless 'OUTDENT' is wanted
|
||||
# Auto-close INDENT to support syntax like this:
|
||||
#
|
||||
# el.click((event) ->
|
||||
# el.hide())
|
||||
#
|
||||
@indent -= size = last @indents
|
||||
@outdentToken size, true
|
||||
return @pair tag
|
||||
@ends.pop()
|
||||
|
||||
# Helpers
|
||||
# -------
|
||||
|
||||
# Add a token to the results, taking note of the line number.
|
||||
token: (tag, value) ->
|
||||
@tokens.push [tag, value, @line]
|
||||
|
||||
# Peek at a tag in the current token stream.
|
||||
tag: (index, tag) ->
|
||||
(tok = last @tokens, index) and if tag then tok[0] = tag else tok[0]
|
||||
|
||||
# Peek at a value in the current token stream.
|
||||
value: (index, val) ->
|
||||
(tok = last @tokens, index) and if val then tok[1] = val else tok[1]
|
||||
|
||||
# Are we in the midst of an unfinished expression?
|
||||
unfinished: ->
|
||||
LINE_CONTINUER.test(@chunk) or
|
||||
@tag() in ['\\', '.', '?.', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION'
|
||||
'COMPARE', 'LOGIC', 'THROW', 'EXTENDS']
|
||||
|
||||
# Converts newlines for string literals.
|
||||
escapeLines: (str, heredoc) ->
|
||||
str.replace MULTILINER, if heredoc then '\\n' else ''
|
||||
|
||||
# Constructs a string token by escaping quotes and newlines.
|
||||
makeString: (body, quote, heredoc) ->
|
||||
return quote + quote unless body
|
||||
body = body.replace /\\([\s\S])/g, (match, contents) ->
|
||||
if contents in ['\n', quote] then contents else match
|
||||
body = body.replace /// #{quote} ///g, '\\$&'
|
||||
quote + @escapeLines(body, heredoc) + quote
|
||||
|
||||
# Throws a syntax error on the current `@line`.
|
||||
error: (message) ->
|
||||
throw SyntaxError "#{message} on line #{ @line + 1}"
|
||||
|
||||
# Constants
|
||||
# ---------
|
||||
|
||||
# Keywords that CoffeeScript shares in common with JavaScript.
|
||||
JS_KEYWORDS = [
|
||||
'true', 'false', 'null', 'this'
|
||||
'new', 'delete', 'typeof', 'in', 'instanceof'
|
||||
'return', 'throw', 'break', 'continue', 'debugger'
|
||||
'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally'
|
||||
'class', 'extends', 'super'
|
||||
]
|
||||
|
||||
# CoffeeScript-only keywords.
|
||||
COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when']
|
||||
|
||||
COFFEE_ALIAS_MAP =
|
||||
and : '&&'
|
||||
or : '||'
|
||||
is : '=='
|
||||
isnt : '!='
|
||||
not : '!'
|
||||
yes : 'true'
|
||||
no : 'false'
|
||||
on : 'true'
|
||||
off : 'false'
|
||||
|
||||
COFFEE_ALIASES = (key for key of COFFEE_ALIAS_MAP)
|
||||
COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat COFFEE_ALIASES
|
||||
|
||||
# The list of keywords that are reserved by JavaScript, but not used, or are
|
||||
# used by CoffeeScript internally. We throw an error when these are encountered,
|
||||
# to avoid having a JavaScript error at runtime.
|
||||
RESERVED = [
|
||||
'case', 'default', 'function', 'var', 'void', 'with'
|
||||
'const', 'let', 'enum', 'export', 'import', 'native'
|
||||
'__hasProp', '__extends', '__slice', '__bind', '__indexOf'
|
||||
'implements', 'interface', 'let', 'package',
|
||||
'private', 'protected', 'public', 'static', 'yield'
|
||||
]
|
||||
|
||||
STRICT_PROSCRIBED = ['arguments', 'eval']
|
||||
|
||||
# The superset of both JavaScript keywords and reserved words, none of which may
|
||||
# be used as identifiers or properties.
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED)
|
||||
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED)
|
||||
exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED
|
||||
|
||||
# Token matching regexes.
|
||||
IDENTIFIER = /// ^
|
||||
( [$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]* )
|
||||
( [^\n\S]* : (?!:) )? # Is this a property name?
|
||||
///
|
||||
|
||||
NUMBER = ///
|
||||
^ 0b[01]+ | # binary
|
||||
^ 0o[0-7]+ | # octal
|
||||
^ 0x[\da-f]+ | # hex
|
||||
^ \d*\.?\d+ (?:e[+-]?\d+)? # decimal
|
||||
///i
|
||||
|
||||
HEREDOC = /// ^ ("""|''') ([\s\S]*?) (?:\n[^\n\S]*)? \1 ///
|
||||
|
||||
OPERATOR = /// ^ (
|
||||
?: [-=]> # function
|
||||
| [-+*/%<>&|^!?=]= # compound assign / compare
|
||||
| >>>=? # zero-fill right shift
|
||||
| ([-+:])\1 # doubles
|
||||
| ([&|<>])\2=? # logic / shift
|
||||
| \?\. # soak access
|
||||
| \.{2,3} # range or splat
|
||||
) ///
|
||||
|
||||
WHITESPACE = /^[^\n\S]+/
|
||||
|
||||
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/
|
||||
|
||||
CODE = /^[-=]>/
|
||||
|
||||
MULTI_DENT = /^(?:\n[^\n\S]*)+/
|
||||
|
||||
SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/
|
||||
|
||||
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/
|
||||
|
||||
# Regex-matching-regexes.
|
||||
REGEX = /// ^
|
||||
(/ (?! [\s=] ) # disallow leading whitespace or equals signs
|
||||
[^ [ / \n \\ ]* # every other thing
|
||||
(?:
|
||||
(?: \\[\s\S] # anything escaped
|
||||
| \[ # character class
|
||||
[^ \] \n \\ ]*
|
||||
(?: \\[\s\S] [^ \] \n \\ ]* )*
|
||||
]
|
||||
) [^ [ / \n \\ ]*
|
||||
)*
|
||||
/) ([imgy]{0,4}) (?!\w)
|
||||
///
|
||||
|
||||
HEREGEX = /// ^ /{3} ([\s\S]+?) /{3} ([imgy]{0,4}) (?!\w) ///
|
||||
|
||||
HEREGEX_OMIT = /\s+(?:#.*)?/g
|
||||
|
||||
# Token cleaning regexes.
|
||||
MULTILINER = /\n/g
|
||||
|
||||
HEREDOC_INDENT = /\n+([^\n\S]*)/g
|
||||
|
||||
HEREDOC_ILLEGAL = /\*\//
|
||||
|
||||
LINE_CONTINUER = /// ^ \s* (?: , | \??\.(?![.\d]) | :: ) ///
|
||||
|
||||
TRAILING_SPACES = /\s+$/
|
||||
|
||||
# Compound assignment tokens.
|
||||
COMPOUND_ASSIGN = [
|
||||
'-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='
|
||||
]
|
||||
|
||||
# Unary tokens.
|
||||
UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO']
|
||||
|
||||
# Logical tokens.
|
||||
LOGIC = ['&&', '||', '&', '|', '^']
|
||||
|
||||
# Bit-shifting tokens.
|
||||
SHIFT = ['<<', '>>', '>>>']
|
||||
|
||||
# Comparison tokens.
|
||||
COMPARE = ['==', '!=', '<', '>', '<=', '>=']
|
||||
|
||||
# Mathematical tokens.
|
||||
MATH = ['*', '/', '%']
|
||||
|
||||
# Relational tokens that are negatable with `not` prefix.
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF']
|
||||
|
||||
# Boolean tokens.
|
||||
BOOL = ['TRUE', 'FALSE']
|
||||
|
||||
# Tokens which a regular expression will never immediately follow, but which
|
||||
# a division operator might.
|
||||
#
|
||||
# See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
|
||||
#
|
||||
# Our list is shorter, due to sans-parentheses method calls.
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']']
|
||||
|
||||
# If the previous token is not spaced, there are more preceding tokens that
|
||||
# force a division parse:
|
||||
NOT_SPACED_REGEX = NOT_REGEX.concat ')', '}', 'THIS', 'IDENTIFIER', 'STRING'
|
||||
|
||||
# Tokens which could legitimately be invoked or indexed. An opening
|
||||
# parentheses or bracket following these tokens will be recorded as the start
|
||||
# of a function invocation or indexing operation.
|
||||
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER']
|
||||
INDEXABLE = CALLABLE.concat 'NUMBER', 'BOOL', 'NULL', 'UNDEFINED'
|
||||
|
||||
# Tokens that, when immediately preceding a `WHEN`, indicate that the `WHEN`
|
||||
# occurs at the start of a line. We disambiguate these from trailing whens to
|
||||
# avoid an ambiguity in the grammar.
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']
|
||||
256
samples/CoffeeScript/rack_application.coffee
Normal file
256
samples/CoffeeScript/rack_application.coffee
Normal file
@@ -0,0 +1,256 @@
|
||||
# The `RackApplication` class is responsible for managing a
|
||||
# [Nack](http://josh.github.com/nack/) pool for a given Rack
|
||||
# application. Incoming HTTP requests are dispatched to
|
||||
# `RackApplication` instances by an `HttpServer`, where they are
|
||||
# subsequently handled by a pool of Nack worker processes. By default,
|
||||
# Pow tells Nack to use a maximum of two worker processes per
|
||||
# application, but this can be overridden with the configuration's
|
||||
# `workers` option.
|
||||
#
|
||||
# Before creating the Nack pool, Pow executes the `.powrc` and
|
||||
# `.powenv` scripts if they're present in the application root,
|
||||
# captures their environment variables, and passes them along to the
|
||||
# Nack worker processes. This lets you modify your `RUBYOPT` to use
|
||||
# different Ruby options, for example.
|
||||
#
|
||||
# If [rvm](http://rvm.beginrescueend.com/) is installed and an
|
||||
# `.rvmrc` file is present in the application's root, Pow will load
|
||||
# both before creating the Nack pool. This makes it easy to run an
|
||||
# app with a specific version of Ruby.
|
||||
#
|
||||
# Nack workers remain running until they're killed, restarted (by
|
||||
# touching the `tmp/restart.txt` file in the application root), or
|
||||
# until the application has not served requests for the length of time
|
||||
# specified in the configuration's `timeout` option (15 minutes by
|
||||
# default).
|
||||
|
||||
async = require "async"
|
||||
fs = require "fs"
|
||||
nack = require "nack"
|
||||
|
||||
{bufferLines, pause, sourceScriptEnv} = require "./util"
|
||||
{join, exists, basename, resolve} = require "path"
|
||||
|
||||
module.exports = class RackApplication
|
||||
# Create a `RackApplication` for the given configuration and
|
||||
# root path. The application begins life in the uninitialized
|
||||
# state.
|
||||
constructor: (@configuration, @root, @firstHost) ->
|
||||
@logger = @configuration.getLogger join "apps", basename @root
|
||||
@readyCallbacks = []
|
||||
@quitCallbacks = []
|
||||
@statCallbacks = []
|
||||
|
||||
# Queue `callback` to be invoked when the application becomes ready,
|
||||
# then start the initialization process. If the application's state
|
||||
# is ready, the callback is invoked immediately.
|
||||
ready: (callback) ->
|
||||
if @state is "ready"
|
||||
callback()
|
||||
else
|
||||
@readyCallbacks.push callback
|
||||
@initialize()
|
||||
|
||||
# Tell the application to quit and queue `callback` to be invoked
|
||||
# when all workers have exited. If the application has already quit,
|
||||
# the callback is invoked immediately.
|
||||
quit: (callback) ->
|
||||
if @state
|
||||
@quitCallbacks.push callback if callback
|
||||
@terminate()
|
||||
else
|
||||
callback?()
|
||||
|
||||
# Stat `tmp/restart.txt` in the application root and invoke the
|
||||
# given callback with a single argument indicating whether or not
|
||||
# the file has been touched since the last call to
|
||||
# `queryRestartFile`.
|
||||
queryRestartFile: (callback) ->
|
||||
fs.stat join(@root, "tmp/restart.txt"), (err, stats) =>
|
||||
if err
|
||||
@mtime = null
|
||||
callback false
|
||||
else
|
||||
lastMtime = @mtime
|
||||
@mtime = stats.mtime.getTime()
|
||||
callback lastMtime isnt @mtime
|
||||
|
||||
# Check to see if `tmp/always_restart.txt` is present in the
|
||||
# application root, and set the pool's `runOnce` option
|
||||
# accordingly. Invoke `callback` when the existence check has
|
||||
# finished. (Multiple calls to this method are aggregated.)
|
||||
setPoolRunOnceFlag: (callback) ->
|
||||
unless @statCallbacks.length
|
||||
exists join(@root, "tmp/always_restart.txt"), (alwaysRestart) =>
|
||||
@pool.runOnce = alwaysRestart
|
||||
statCallback() for statCallback in @statCallbacks
|
||||
@statCallbacks = []
|
||||
|
||||
@statCallbacks.push callback
|
||||
|
||||
# Collect environment variables from `.powrc` and `.powenv`, in that
|
||||
# order, if present. The idea is that `.powrc` files can be checked
|
||||
# into a source code repository for global configuration, leaving
|
||||
# `.powenv` free for any necessary local overrides.
|
||||
loadScriptEnvironment: (env, callback) ->
|
||||
async.reduce [".powrc", ".envrc", ".powenv"], env, (env, filename, callback) =>
|
||||
exists script = join(@root, filename), (scriptExists) ->
|
||||
if scriptExists
|
||||
sourceScriptEnv script, env, callback
|
||||
else
|
||||
callback null, env
|
||||
, callback
|
||||
|
||||
# If `.rvmrc` and `$HOME/.rvm/scripts/rvm` are present, load rvm,
|
||||
# source `.rvmrc`, and invoke `callback` with the resulting
|
||||
# environment variables. If `.rvmrc` is present but rvm is not
|
||||
# installed, invoke `callback` without sourcing `.rvmrc`.
|
||||
# Before loading rvm, Pow invokes a helper script that shows a
|
||||
# deprecation notice if it has not yet been displayed.
|
||||
loadRvmEnvironment: (env, callback) ->
|
||||
exists script = join(@root, ".rvmrc"), (rvmrcExists) =>
|
||||
if rvmrcExists
|
||||
exists rvm = @configuration.rvmPath, (rvmExists) =>
|
||||
if rvmExists
|
||||
libexecPath = resolve "#{__dirname}/../libexec"
|
||||
before = """
|
||||
'#{libexecPath}/pow_rvm_deprecation_notice' '#{[@firstHost]}'
|
||||
source '#{rvm}' > /dev/null
|
||||
""".trim()
|
||||
sourceScriptEnv script, env, {before}, callback
|
||||
else
|
||||
callback null, env
|
||||
else
|
||||
callback null, env
|
||||
|
||||
# Stat `tmp/restart.txt` to cache its mtime, then load the
|
||||
# application's full environment from `.powrc`, `.powenv`, and
|
||||
# `.rvmrc`.
|
||||
loadEnvironment: (callback) ->
|
||||
@queryRestartFile =>
|
||||
@loadScriptEnvironment @configuration.env, (err, env) =>
|
||||
if err then callback err
|
||||
else @loadRvmEnvironment env, (err, env) =>
|
||||
if err then callback err
|
||||
else callback null, env
|
||||
|
||||
# Begin the initialization process if the application is in the
|
||||
# uninitialized state. (If the application is terminating, queue a
|
||||
# call to `initialize` after all workers have exited.)
|
||||
initialize: ->
|
||||
if @state
|
||||
if @state is "terminating"
|
||||
@quit => @initialize()
|
||||
return
|
||||
|
||||
@state = "initializing"
|
||||
|
||||
# Load the application's environment. If an error is raised or
|
||||
# either of the environment scripts exits with a non-zero status,
|
||||
# reset the application's state and log the error.
|
||||
@loadEnvironment (err, env) =>
|
||||
if err
|
||||
@state = null
|
||||
@logger.error err.message
|
||||
@logger.error "stdout: #{err.stdout}"
|
||||
@logger.error "stderr: #{err.stderr}"
|
||||
|
||||
# Set the application's state to ready. Then create the Nack
|
||||
# pool instance using the `workers` and `timeout` options from
|
||||
# the application's environment or the global configuration.
|
||||
else
|
||||
@state = "ready"
|
||||
|
||||
@pool = nack.createPool join(@root, "config.ru"),
|
||||
env: env
|
||||
size: env?.POW_WORKERS ? @configuration.workers
|
||||
idle: (env?.POW_TIMEOUT ? @configuration.timeout) * 1000
|
||||
|
||||
# Log the workers' stderr and stdout, and log each worker's
|
||||
# PID as it spawns and exits.
|
||||
bufferLines @pool.stdout, (line) => @logger.info line
|
||||
bufferLines @pool.stderr, (line) => @logger.warning line
|
||||
|
||||
@pool.on "worker:spawn", (process) =>
|
||||
@logger.debug "nack worker #{process.child.pid} spawned"
|
||||
|
||||
@pool.on "worker:exit", (process) =>
|
||||
@logger.debug "nack worker exited"
|
||||
|
||||
# Invoke and remove all queued callbacks, passing along the
|
||||
# error, if any.
|
||||
readyCallback err for readyCallback in @readyCallbacks
|
||||
@readyCallbacks = []
|
||||
|
||||
# Begin the termination process. (If the application is initializing,
|
||||
# wait until it is ready before shutting down.)
|
||||
terminate: ->
|
||||
if @state is "initializing"
|
||||
@ready => @terminate()
|
||||
|
||||
else if @state is "ready"
|
||||
@state = "terminating"
|
||||
|
||||
# Instruct all workers to exit. After the processes have
|
||||
# terminated, reset the application's state, then invoke and
|
||||
# remove all queued callbacks.
|
||||
@pool.quit =>
|
||||
@state = null
|
||||
@mtime = null
|
||||
@pool = null
|
||||
|
||||
quitCallback() for quitCallback in @quitCallbacks
|
||||
@quitCallbacks = []
|
||||
|
||||
# Handle an incoming HTTP request. Wait until the application is in
|
||||
# the ready state, restart the workers if necessary, then pass the
|
||||
# request along to the Nack pool. If the Nack worker raises an
|
||||
# exception handling the request, reset the application.
|
||||
handle: (req, res, next, callback) ->
|
||||
resume = pause req
|
||||
@ready (err) =>
|
||||
return next err if err
|
||||
@setPoolRunOnceFlag =>
|
||||
@restartIfNecessary =>
|
||||
req.proxyMetaVariables =
|
||||
SERVER_PORT: @configuration.dstPort.toString()
|
||||
try
|
||||
@pool.proxy req, res, (err) =>
|
||||
@quit() if err
|
||||
next err
|
||||
finally
|
||||
resume()
|
||||
callback?()
|
||||
|
||||
# Terminate the application, re-initialize it, and invoke the given
|
||||
# callback when the application's state becomes ready.
|
||||
restart: (callback) ->
|
||||
@quit =>
|
||||
@ready callback
|
||||
|
||||
# Restart the application if `tmp/restart.txt` has been touched
|
||||
# since the last call to this function.
|
||||
restartIfNecessary: (callback) ->
|
||||
@queryRestartFile (mtimeChanged) =>
|
||||
if mtimeChanged
|
||||
@restart callback
|
||||
else
|
||||
callback()
|
||||
|
||||
# Append RVM autoload boilerplate to the application's `.powrc`
|
||||
# file. This is called by the RVM deprecation notice mini-app.
|
||||
writeRvmBoilerplate: ->
|
||||
powrc = join @root, ".powrc"
|
||||
boilerplate = @constructor.rvmBoilerplate
|
||||
|
||||
fs.readFile powrc, "utf8", (err, contents) ->
|
||||
contents ?= ""
|
||||
if contents.indexOf(boilerplate) is -1
|
||||
fs.writeFile powrc, "#{boilerplate}\n#{contents}"
|
||||
|
||||
@rvmBoilerplate: """
|
||||
if [ -f "$rvm_path/scripts/rvm" ] && [ -f ".rvmrc" ]; then
|
||||
source "$rvm_path/scripts/rvm"
|
||||
source ".rvmrc"
|
||||
fi
|
||||
"""
|
||||
110
samples/CoffeeScript/xipd.coffee
Normal file
110
samples/CoffeeScript/xipd.coffee
Normal file
@@ -0,0 +1,110 @@
|
||||
dnsserver = require "dnsserver"
|
||||
|
||||
exports.Server = class Server extends dnsserver.Server
|
||||
NS_T_A = 1
|
||||
NS_T_NS = 2
|
||||
NS_T_CNAME = 5
|
||||
NS_T_SOA = 6
|
||||
NS_C_IN = 1
|
||||
NS_RCODE_NXDOMAIN = 3
|
||||
|
||||
constructor: (domain, @rootAddress) ->
|
||||
super
|
||||
@domain = domain.toLowerCase()
|
||||
@soa = createSOA @domain
|
||||
@on "request", @handleRequest
|
||||
|
||||
handleRequest: (req, res) =>
|
||||
question = req.question
|
||||
subdomain = @extractSubdomain question.name
|
||||
|
||||
if subdomain? and isARequest question
|
||||
res.addRR question.name, NS_T_A, NS_C_IN, 600, subdomain.getAddress()
|
||||
else if subdomain?.isEmpty() and isNSRequest question
|
||||
res.addRR question.name, NS_T_SOA, NS_C_IN, 600, @soa, true
|
||||
else
|
||||
res.header.rcode = NS_RCODE_NXDOMAIN
|
||||
|
||||
res.send()
|
||||
|
||||
extractSubdomain: (name) ->
|
||||
Subdomain.extract name, @domain, @rootAddress
|
||||
|
||||
isARequest = (question) ->
|
||||
question.type is NS_T_A and question.class is NS_C_IN
|
||||
|
||||
isNSRequest = (question) ->
|
||||
question.type is NS_T_NS and question.class is NS_C_IN
|
||||
|
||||
createSOA = (domain) ->
|
||||
mname = "ns-1.#{domain}"
|
||||
rname = "hostmaster.#{domain}"
|
||||
serial = parseInt new Date().getTime() / 1000
|
||||
refresh = 28800
|
||||
retry = 7200
|
||||
expire = 604800
|
||||
minimum = 3600
|
||||
dnsserver.createSOA mname, rname, serial, refresh, retry, expire, minimum
|
||||
|
||||
exports.createServer = (domain, address = "127.0.0.1") ->
|
||||
new Server domain, address
|
||||
|
||||
exports.Subdomain = class Subdomain
|
||||
@extract: (name, domain, address) ->
|
||||
return unless name
|
||||
name = name.toLowerCase()
|
||||
offset = name.length - domain.length
|
||||
|
||||
if domain is name.slice offset
|
||||
subdomain = if 0 >= offset then null else name.slice 0, offset - 1
|
||||
new constructor subdomain, address if constructor = @for subdomain
|
||||
|
||||
@for: (subdomain = "") ->
|
||||
if IPAddressSubdomain.pattern.test subdomain
|
||||
IPAddressSubdomain
|
||||
else if EncodedSubdomain.pattern.test subdomain
|
||||
EncodedSubdomain
|
||||
else
|
||||
Subdomain
|
||||
|
||||
constructor: (@subdomain, @address) ->
|
||||
@labels = subdomain?.split(".") ? []
|
||||
@length = @labels.length
|
||||
|
||||
isEmpty: ->
|
||||
@length is 0
|
||||
|
||||
getAddress: ->
|
||||
@address
|
||||
|
||||
class IPAddressSubdomain extends Subdomain
|
||||
@pattern = /// (^|\.)
|
||||
((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}
|
||||
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
|
||||
$ ///
|
||||
|
||||
getAddress: ->
|
||||
@labels.slice(-4).join "."
|
||||
|
||||
class EncodedSubdomain extends Subdomain
|
||||
@pattern = /(^|\.)[a-z0-9]{1,7}$/
|
||||
|
||||
getAddress: ->
|
||||
decode @labels[@length - 1]
|
||||
|
||||
exports.encode = encode = (ip) ->
|
||||
value = 0
|
||||
for byte, index in ip.split "."
|
||||
value += parseInt(byte, 10) << (index * 8)
|
||||
(value >>> 0).toString 36
|
||||
|
||||
PATTERN = /^[a-z0-9]{1,7}$/
|
||||
|
||||
exports.decode = decode = (string) ->
|
||||
return unless PATTERN.test string
|
||||
value = parseInt string, 36
|
||||
ip = []
|
||||
for i in [1..4]
|
||||
ip.push value & 0xFF
|
||||
value >>= 8
|
||||
ip.join "."
|
||||
707
samples/Coq/Basics.v
Executable file
707
samples/Coq/Basics.v
Executable file
@@ -0,0 +1,707 @@
|
||||
Inductive day : Type :=
|
||||
| monday : day
|
||||
| tuesday : day
|
||||
| wednesday : day
|
||||
| thursday : day
|
||||
| friday : day
|
||||
| saturday : day
|
||||
| sunday : day.
|
||||
|
||||
Definition next_weekday (d:day) : day :=
|
||||
match d with
|
||||
| monday => tuesday
|
||||
| tuesday => wednesday
|
||||
| wednesday => thursday
|
||||
| thursday => friday
|
||||
| friday => monday
|
||||
| saturday => monday
|
||||
| sunday => monday
|
||||
end.
|
||||
|
||||
Example test_next_weekday:
|
||||
(next_weekday (next_weekday saturday)) = tuesday.
|
||||
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Inductive bool : Type :=
|
||||
| true : bool
|
||||
| false : bool.
|
||||
|
||||
Definition negb (b:bool) : bool :=
|
||||
match b with
|
||||
| true => false
|
||||
| false => true
|
||||
end.
|
||||
|
||||
Definition andb (b1:bool) (b2:bool) : bool :=
|
||||
match b1 with
|
||||
| true => b2
|
||||
| false => false
|
||||
end.
|
||||
|
||||
Definition orb (b1:bool) (b2:bool) : bool :=
|
||||
match b1 with
|
||||
| true => true
|
||||
| false => b2
|
||||
end.
|
||||
|
||||
Example test_orb1: (orb true false) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Example test_orb2: (orb false false) = false.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Example test_orb3: (orb false true) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Example test_orb4: (orb true true) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Definition nandb (b1: bool) (b2:bool) : bool :=
|
||||
match b1 with
|
||||
| true => match b2 with
|
||||
| false => true
|
||||
| true => false
|
||||
end
|
||||
| false => true
|
||||
end.
|
||||
|
||||
Example test_nandb1: (nandb true false) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_nandb2: (nandb false false) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_nandb3: (nandb false true) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_nandb4: (nandb true true) = false.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Definition andb3 (b1: bool) (b2:bool) (b3:bool) : bool :=
|
||||
match b1 with
|
||||
| false => false
|
||||
| true => match b2 with
|
||||
| false => false
|
||||
| true => b3
|
||||
end
|
||||
end.
|
||||
|
||||
Example test_andb31: (andb3 true true true) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_andb32: (andb3 false true true) = false.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_andb33: (andb3 true false true) = false.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_andb34: (andb3 true true false) = false.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Module Playground1.
|
||||
|
||||
Inductive nat : Type :=
|
||||
| O : nat
|
||||
| S : nat -> nat.
|
||||
|
||||
Definition pred (n : nat) : nat :=
|
||||
match n with
|
||||
| O => O
|
||||
| S n' => n'
|
||||
end.
|
||||
|
||||
Definition minustwo (n : nat) : nat :=
|
||||
match n with
|
||||
| O => O
|
||||
| S O => O
|
||||
| S (S n') => n'
|
||||
end.
|
||||
|
||||
Fixpoint evenb (n : nat) : bool :=
|
||||
match n with
|
||||
| O => true
|
||||
| S O => false
|
||||
| S (S n') => evenb n'
|
||||
end.
|
||||
|
||||
Definition oddb (n : nat) : bool := negb (evenb n).
|
||||
|
||||
Example test_oddb1: (oddb (S O)) = true.
|
||||
Proof. reflexivity. Qed.
|
||||
Example test_oddb2: (oddb (S (S (S (S O))))) = false.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Fixpoint plus (n : nat) (m : nat) : nat :=
|
||||
match n with
|
||||
| O => m
|
||||
| S n' => S (plus n' m)
|
||||
end.
|
||||
|
||||
Fixpoint mult (n m : nat) : nat :=
|
||||
match n with
|
||||
| O => O
|
||||
| S n' => plus m (mult n' m)
|
||||
end.
|
||||
|
||||
Fixpoint minus (n m : nat) : nat :=
|
||||
match n, m with
|
||||
| O, _ => n
|
||||
| S n', O => S n'
|
||||
| S n', S m' => minus n' m'
|
||||
end.
|
||||
|
||||
Fixpoint exp (base power : nat) : nat :=
|
||||
match power with
|
||||
| O => S O
|
||||
| S p => mult base (exp base p)
|
||||
end.
|
||||
|
||||
Fixpoint factorial (n : nat) : nat :=
|
||||
match n with
|
||||
| O => S O
|
||||
| S n' => mult n (factorial n')
|
||||
end.
|
||||
|
||||
Example test_factorial1: (factorial (S (S (S O)))) = (S (S (S (S (S (S O)))))).
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Notation "x + y" := (plus x y) (at level 50, left associativity) : nat_scope.
|
||||
Notation "x - y" := (minus x y) (at level 50, left associativity) : nat_scope.
|
||||
Notation "x * y" := (mult x y) (at level 40, left associativity) : nat_scope.
|
||||
|
||||
Fixpoint beq_nat (n m : nat) : bool :=
|
||||
match n with
|
||||
| O => match m with
|
||||
| O => true
|
||||
| S m' => false
|
||||
end
|
||||
| S n' => match m with
|
||||
| O => false
|
||||
| S m' => beq_nat n' m'
|
||||
end
|
||||
end.
|
||||
|
||||
Fixpoint ble_nat (n m : nat) : bool :=
|
||||
match n with
|
||||
| O => true
|
||||
| S n' =>
|
||||
match m with
|
||||
| O => false
|
||||
| S m' => ble_nat n' m'
|
||||
end
|
||||
end.
|
||||
|
||||
Example test_ble_nat1: (ble_nat (S (S O)) (S (S O))) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_ble_nat2: (ble_nat (S (S O)) (S (S (S (S O))))) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_ble_nat3: (ble_nat (S (S (S (S O)))) (S (S O))) = false.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Definition blt_nat (n m : nat) : bool :=
|
||||
(andb (negb (beq_nat n m)) (ble_nat n m)).
|
||||
|
||||
Example test_blt_nat1: (blt_nat (S (S O)) (S (S O))) = false.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_blt_nat3: (blt_nat (S (S (S (S O)))) (S (S O))) = false.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
Example test_blt_nat2 : (blt_nat (S (S O)) (S (S (S (S O))))) = true.
|
||||
Proof. simpl. reflexivity. Qed.
|
||||
|
||||
Theorem plus_O_n : forall n : nat, O + n = n.
|
||||
Proof.
|
||||
simpl. reflexivity. Qed.
|
||||
|
||||
Theorem plus_O_n' : forall n : nat, O + n = n.
|
||||
Proof.
|
||||
reflexivity. Qed.
|
||||
|
||||
Theorem plus_O_n'' : forall n : nat, O + n = n.
|
||||
Proof.
|
||||
intros n. reflexivity. Qed.
|
||||
|
||||
Theorem plus_1_1 : forall n : nat, (S O) + n = S n.
|
||||
Proof.
|
||||
intros n. reflexivity. Qed.
|
||||
|
||||
Theorem mult_0_1: forall n : nat, O * n = O.
|
||||
Proof.
|
||||
intros n. reflexivity. Qed.
|
||||
|
||||
Theorem plus_id_example : forall n m:nat,
|
||||
n = m -> n + n = m + m.
|
||||
Proof.
|
||||
intros n m.
|
||||
intros H.
|
||||
rewrite -> H.
|
||||
reflexivity. Qed.
|
||||
|
||||
Theorem plus_id_exercise : forall n m o: nat,
|
||||
n = m -> m = o -> n + m = m + o.
|
||||
Proof.
|
||||
intros n m o.
|
||||
intros H.
|
||||
intros H'.
|
||||
rewrite -> H.
|
||||
rewrite <- H'.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem mult_0_plus : forall n m : nat,
|
||||
(O + n) * m = n * m.
|
||||
Proof.
|
||||
intros n m.
|
||||
rewrite -> plus_O_n.
|
||||
reflexivity. Qed.
|
||||
|
||||
Theorem mult_1_plus : forall n m: nat,
|
||||
((S O) + n) * m = m + (n * m).
|
||||
Proof.
|
||||
intros n m.
|
||||
rewrite -> plus_1_1.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem mult_1 : forall n : nat,
|
||||
n * (S O) = n.
|
||||
Proof.
|
||||
intros n.
|
||||
induction n as [| n'].
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> IHn'.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem plus_1_neq_0 : forall n : nat,
|
||||
beq_nat (n + (S O)) O = false.
|
||||
Proof.
|
||||
intros n.
|
||||
destruct n as [| n'].
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem zero_nbeq_plus_1 : forall n : nat,
|
||||
beq_nat O (n + (S O)) = false.
|
||||
Proof.
|
||||
intros n.
|
||||
destruct n.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Require String. Open Scope string_scope.
|
||||
|
||||
Ltac move_to_top x :=
|
||||
match reverse goal with
|
||||
| H : _ |- _ => try move x after H
|
||||
end.
|
||||
|
||||
Tactic Notation "assert_eq" ident(x) constr(v) :=
|
||||
let H := fresh in
|
||||
assert (x = v) as H by reflexivity;
|
||||
clear H.
|
||||
|
||||
Tactic Notation "Case_aux" ident(x) constr(name) :=
|
||||
first [
|
||||
set (x := name); move_to_top x
|
||||
| assert_eq x name; move_to_top x
|
||||
| fail 1 "because we are working on a different case" ].
|
||||
|
||||
Ltac Case name := Case_aux Case name.
|
||||
Ltac SCase name := Case_aux SCase name.
|
||||
Ltac SSCase name := Case_aux SSCase name.
|
||||
Ltac SSSCase name := Case_aux SSSCase name.
|
||||
Ltac SSSSCase name := Case_aux SSSSCase name.
|
||||
Ltac SSSSSCase name := Case_aux SSSSSCase name.
|
||||
Ltac SSSSSSCase name := Case_aux SSSSSSCase name.
|
||||
Ltac SSSSSSSCase name := Case_aux SSSSSSSCase name.
|
||||
|
||||
Theorem andb_true_elim1 : forall b c : bool,
|
||||
andb b c = true -> b = true.
|
||||
Proof.
|
||||
intros b c H.
|
||||
destruct b.
|
||||
Case "b = true".
|
||||
reflexivity.
|
||||
Case "b = false".
|
||||
rewrite <- H. reflexivity. Qed.
|
||||
|
||||
Theorem plus_0_r : forall n : nat, n + O = n.
|
||||
Proof.
|
||||
intros n. induction n as [| n'].
|
||||
Case "n = 0". reflexivity.
|
||||
Case "n = S n'". simpl. rewrite -> IHn'. reflexivity. Qed.
|
||||
|
||||
Theorem minus_diag : forall n,
|
||||
minus n n = O.
|
||||
Proof.
|
||||
intros n. induction n as [| n'].
|
||||
Case "n = 0".
|
||||
simpl. reflexivity.
|
||||
Case "n = S n'".
|
||||
simpl. rewrite -> IHn'. reflexivity. Qed.
|
||||
|
||||
|
||||
Theorem mult_0_r : forall n:nat,
|
||||
n * O = O.
|
||||
Proof.
|
||||
intros n. induction n as [| n'].
|
||||
Case "n = 0".
|
||||
reflexivity.
|
||||
Case "n = S n'".
|
||||
simpl. rewrite -> IHn'. reflexivity. Qed.
|
||||
|
||||
Theorem plus_n_Sm : forall n m : nat,
|
||||
S (n + m) = n + (S m).
|
||||
Proof.
|
||||
intros n m. induction n as [| n'].
|
||||
Case "n = 0".
|
||||
reflexivity.
|
||||
Case "n = S n'".
|
||||
simpl. rewrite -> IHn'. reflexivity. Qed.
|
||||
|
||||
Theorem plus_assoc : forall n m p : nat,
|
||||
n + (m + p) = (n + m) + p.
|
||||
Proof.
|
||||
intros n m p.
|
||||
induction n as [| n'].
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> IHn'.
|
||||
reflexivity. Qed.
|
||||
|
||||
Theorem plus_distr : forall n m: nat, S (n + m) = n + (S m).
|
||||
Proof.
|
||||
intros n m. induction n as [| n'].
|
||||
Case "n = 0".
|
||||
reflexivity.
|
||||
Case "n = S n'".
|
||||
simpl. rewrite -> IHn'. reflexivity. Qed.
|
||||
|
||||
Theorem mult_distr : forall n m: nat, n * ((S O) + m) = n * (S m).
|
||||
Proof.
|
||||
intros n m.
|
||||
induction n as [| n'].
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem plus_comm : forall n m : nat,
|
||||
n + m = m + n.
|
||||
Proof.
|
||||
intros n m.
|
||||
induction n as [| n'].
|
||||
Case "n = 0".
|
||||
simpl.
|
||||
rewrite -> plus_0_r.
|
||||
reflexivity.
|
||||
Case "n = S n'".
|
||||
simpl.
|
||||
rewrite -> IHn'.
|
||||
rewrite -> plus_distr.
|
||||
reflexivity. Qed.
|
||||
|
||||
Fixpoint double (n:nat) :=
|
||||
match n with
|
||||
| O => O
|
||||
| S n' => S (S (double n'))
|
||||
end.
|
||||
|
||||
Lemma double_plus : forall n, double n = n + n.
|
||||
Proof.
|
||||
intros n. induction n as [| n'].
|
||||
Case "n = 0".
|
||||
reflexivity.
|
||||
Case "n = S n'".
|
||||
simpl. rewrite -> IHn'.
|
||||
rewrite -> plus_distr. reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem beq_nat_refl : forall n : nat,
|
||||
true = beq_nat n n.
|
||||
Proof.
|
||||
intros n. induction n as [| n'].
|
||||
Case "n = 0".
|
||||
reflexivity.
|
||||
Case "n = S n".
|
||||
simpl. rewrite <- IHn'.
|
||||
reflexivity. Qed.
|
||||
|
||||
Theorem plus_rearrange: forall n m p q : nat,
|
||||
(n + m) + (p + q) = (m + n) + (p + q).
|
||||
Proof.
|
||||
intros n m p q.
|
||||
assert(H: n + m = m + n).
|
||||
Case "Proof by assertion".
|
||||
rewrite -> plus_comm. reflexivity.
|
||||
rewrite -> H. reflexivity. Qed.
|
||||
|
||||
Theorem plus_swap : forall n m p: nat,
|
||||
n + (m + p) = m + (n + p).
|
||||
Proof.
|
||||
intros n m p.
|
||||
rewrite -> plus_assoc.
|
||||
assert(H: m + (n + p) = (m + n) + p).
|
||||
rewrite -> plus_assoc.
|
||||
reflexivity.
|
||||
rewrite -> H.
|
||||
assert(H2: m + n = n + m).
|
||||
rewrite -> plus_comm.
|
||||
reflexivity.
|
||||
rewrite -> H2.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem plus_swap' : forall n m p: nat,
|
||||
n + (m + p) = m + (n + p).
|
||||
Proof.
|
||||
intros n m p.
|
||||
rewrite -> plus_assoc.
|
||||
assert(H: m + (n + p) = (m + n) + p).
|
||||
rewrite -> plus_assoc.
|
||||
reflexivity.
|
||||
rewrite -> H.
|
||||
replace (m + n) with (n + m).
|
||||
rewrite -> plus_comm.
|
||||
reflexivity.
|
||||
rewrite -> plus_comm.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem mult_1_distr: forall m n: nat,
|
||||
n * ((S O) + m) = n * (S O) + n * m.
|
||||
Proof.
|
||||
intros n m.
|
||||
rewrite -> mult_1.
|
||||
rewrite -> plus_1_1.
|
||||
simpl.
|
||||
induction m as [|m'].
|
||||
simpl.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> plus_swap.
|
||||
rewrite <- IHm'.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem mult_comm: forall m n : nat,
|
||||
m * n = n * m.
|
||||
Proof.
|
||||
intros m n.
|
||||
induction n as [| n'].
|
||||
Case "n = 0".
|
||||
simpl.
|
||||
rewrite -> mult_0_r.
|
||||
reflexivity.
|
||||
Case "n = S n'".
|
||||
simpl.
|
||||
rewrite <- mult_distr.
|
||||
rewrite -> mult_1_distr.
|
||||
rewrite -> mult_1.
|
||||
rewrite -> IHn'.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem evenb_next : forall n : nat,
|
||||
evenb n = evenb (S (S n)).
|
||||
Proof.
|
||||
intros n.
|
||||
Admitted.
|
||||
|
||||
Theorem negb_negb : forall n : bool,
|
||||
n = negb (negb n).
|
||||
Proof.
|
||||
intros n.
|
||||
destruct n.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem evenb_n_oddb_Sn : forall n : nat,
|
||||
evenb n = negb (evenb (S n)).
|
||||
Proof.
|
||||
intros n.
|
||||
induction n as [|n'].
|
||||
reflexivity.
|
||||
assert(H: evenb n' = evenb (S (S n'))).
|
||||
reflexivity.
|
||||
rewrite <- H.
|
||||
rewrite -> IHn'.
|
||||
rewrite <- negb_negb.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
(*Fixpoint bad (n : nat) : bool :=
|
||||
match n with
|
||||
| O => true
|
||||
| S O => bad (S n)
|
||||
| S (S n') => bad n'
|
||||
end.*)
|
||||
|
||||
Theorem ble_nat_refl : forall n:nat,
|
||||
true = ble_nat n n.
|
||||
Proof.
|
||||
intros n.
|
||||
induction n as [|n'].
|
||||
Case "n = 0".
|
||||
reflexivity.
|
||||
Case "n = S n".
|
||||
simpl.
|
||||
rewrite <- IHn'.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem zero_nbeq_S : forall n: nat,
|
||||
beq_nat O (S n) = false.
|
||||
Proof.
|
||||
intros n.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem andb_false_r : forall b : bool,
|
||||
andb b false = false.
|
||||
Proof.
|
||||
intros b.
|
||||
destruct b.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem plus_ble_compat_1 : forall n m p : nat,
|
||||
ble_nat n m = true -> ble_nat (p + n) (p + m) = true.
|
||||
Proof.
|
||||
intros n m p.
|
||||
intros H.
|
||||
induction p.
|
||||
Case "p = 0".
|
||||
simpl.
|
||||
rewrite -> H.
|
||||
reflexivity.
|
||||
Case "p = S p'".
|
||||
simpl.
|
||||
rewrite -> IHp.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem S_nbeq_0 : forall n:nat,
|
||||
beq_nat (S n) O = false.
|
||||
Proof.
|
||||
intros n.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem mult_1_1 : forall n:nat, (S O) * n = n.
|
||||
Proof.
|
||||
intros n.
|
||||
simpl.
|
||||
rewrite -> plus_0_r.
|
||||
reflexivity. Qed.
|
||||
|
||||
Theorem all3_spec : forall b c : bool,
|
||||
orb (andb b c)
|
||||
(orb (negb b)
|
||||
(negb c))
|
||||
= true.
|
||||
Proof.
|
||||
intros b c.
|
||||
destruct b.
|
||||
destruct c.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Lemma mult_plus_1 : forall n m : nat,
|
||||
S(m + n) = m + (S n).
|
||||
Proof.
|
||||
intros n m.
|
||||
induction m.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> IHm.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem mult_mult : forall n m : nat,
|
||||
n * (S m) = n * m + n.
|
||||
Proof.
|
||||
intros n m.
|
||||
induction n.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> IHn.
|
||||
rewrite -> plus_assoc.
|
||||
rewrite -> mult_plus_1.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem mult_plus_distr_r : forall n m p:nat,
|
||||
(n + m) * p = (n * p) + (m * p).
|
||||
Proof.
|
||||
intros n m p.
|
||||
induction p.
|
||||
rewrite -> mult_0_r.
|
||||
rewrite -> mult_0_r.
|
||||
rewrite -> mult_0_r.
|
||||
reflexivity.
|
||||
rewrite -> mult_mult.
|
||||
rewrite -> mult_mult.
|
||||
rewrite -> mult_mult.
|
||||
rewrite -> IHp.
|
||||
assert(H1: ((n * p) + n) + (m * p + m) = (n * p) + (n + (m * p + m))).
|
||||
rewrite <- plus_assoc.
|
||||
reflexivity.
|
||||
rewrite -> H1.
|
||||
assert(H2: (n + (m * p + m)) = (m * p + (n + m))).
|
||||
rewrite -> plus_swap.
|
||||
reflexivity.
|
||||
rewrite -> H2.
|
||||
assert(H3: (n * p) + (m * p + (n + m)) = ((n * p ) + (m * p)) + (n + m)).
|
||||
rewrite -> plus_assoc.
|
||||
reflexivity.
|
||||
rewrite -> H3.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem mult_assoc : forall n m p : nat,
|
||||
n * (m * p) = (n * m) * p.
|
||||
Proof.
|
||||
intros n m p.
|
||||
induction n.
|
||||
simpl.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> mult_plus_distr_r.
|
||||
rewrite -> IHn.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Inductive bin : Type :=
|
||||
| BO : bin
|
||||
| D : bin -> bin
|
||||
| M : bin -> bin.
|
||||
|
||||
Fixpoint incbin (n : bin) : bin :=
|
||||
match n with
|
||||
| BO => M (BO)
|
||||
| D n' => M n'
|
||||
| M n' => D (incbin n')
|
||||
end.
|
||||
|
||||
Fixpoint bin2un (n : bin) : nat :=
|
||||
match n with
|
||||
| BO => O
|
||||
| D n' => double (bin2un n')
|
||||
| M n' => S (double (bin2un n'))
|
||||
end.
|
||||
|
||||
Theorem bin_comm : forall n : bin,
|
||||
bin2un(incbin n) = S (bin2un n).
|
||||
Proof.
|
||||
intros n.
|
||||
induction n.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> IHn.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
End Playground1.
|
||||
290
samples/Coq/Heap.v
Executable file
290
samples/Coq/Heap.v
Executable file
@@ -0,0 +1,290 @@
|
||||
(** A development of Treesort on Heap trees. It has an average
|
||||
complexity of O(n.log n) but of O(n²) in the worst case (e.g. if
|
||||
the list is already sorted) *)
|
||||
|
||||
(* G. Huet 1-9-95 uses Multiset *)
|
||||
|
||||
Require Import List Multiset PermutSetoid Relations Sorting.
|
||||
|
||||
Section defs.
|
||||
|
||||
(** * Trees and heap trees *)
|
||||
|
||||
(** ** Definition of trees over an ordered set *)
|
||||
|
||||
Variable A : Type.
|
||||
Variable leA : relation A.
|
||||
Variable eqA : relation A.
|
||||
|
||||
Let gtA (x y:A) := ~ leA x y.
|
||||
|
||||
Hypothesis leA_dec : forall x y:A, {leA x y} + {leA y x}.
|
||||
Hypothesis eqA_dec : forall x y:A, {eqA x y} + {~ eqA x y}.
|
||||
Hypothesis leA_refl : forall x y:A, eqA x y -> leA x y.
|
||||
Hypothesis leA_trans : forall x y z:A, leA x y -> leA y z -> leA x z.
|
||||
Hypothesis leA_antisym : forall x y:A, leA x y -> leA y x -> eqA x y.
|
||||
|
||||
Hint Resolve leA_refl.
|
||||
Hint Immediate eqA_dec leA_dec leA_antisym.
|
||||
|
||||
Let emptyBag := EmptyBag A.
|
||||
Let singletonBag := SingletonBag _ eqA_dec.
|
||||
|
||||
Inductive Tree :=
|
||||
| Tree_Leaf : Tree
|
||||
| Tree_Node : A -> Tree -> Tree -> Tree.
|
||||
|
||||
(** [a] is lower than a Tree [T] if [T] is a Leaf
|
||||
or [T] is a Node holding [b>a] *)
|
||||
|
||||
Definition leA_Tree (a:A) (t:Tree) :=
|
||||
match t with
|
||||
| Tree_Leaf => True
|
||||
| Tree_Node b T1 T2 => leA a b
|
||||
end.
|
||||
|
||||
Lemma leA_Tree_Leaf : forall a:A, leA_Tree a Tree_Leaf.
|
||||
Proof.
|
||||
simpl; auto with datatypes.
|
||||
Qed.
|
||||
|
||||
Lemma leA_Tree_Node :
|
||||
forall (a b:A) (G D:Tree), leA a b -> leA_Tree a (Tree_Node b G D).
|
||||
Proof.
|
||||
simpl; auto with datatypes.
|
||||
Qed.
|
||||
|
||||
|
||||
(** ** The heap property *)
|
||||
|
||||
Inductive is_heap : Tree -> Prop :=
|
||||
| nil_is_heap : is_heap Tree_Leaf
|
||||
| node_is_heap :
|
||||
forall (a:A) (T1 T2:Tree),
|
||||
leA_Tree a T1 ->
|
||||
leA_Tree a T2 ->
|
||||
is_heap T1 -> is_heap T2 -> is_heap (Tree_Node a T1 T2).
|
||||
|
||||
Lemma invert_heap :
|
||||
forall (a:A) (T1 T2:Tree),
|
||||
is_heap (Tree_Node a T1 T2) ->
|
||||
leA_Tree a T1 /\ leA_Tree a T2 /\ is_heap T1 /\ is_heap T2.
|
||||
Proof.
|
||||
intros; inversion H; auto with datatypes.
|
||||
Qed.
|
||||
|
||||
(* This lemma ought to be generated automatically by the Inversion tools *)
|
||||
Lemma is_heap_rect :
|
||||
forall P:Tree -> Type,
|
||||
P Tree_Leaf ->
|
||||
(forall (a:A) (T1 T2:Tree),
|
||||
leA_Tree a T1 ->
|
||||
leA_Tree a T2 ->
|
||||
is_heap T1 -> P T1 -> is_heap T2 -> P T2 -> P (Tree_Node a T1 T2)) ->
|
||||
forall T:Tree, is_heap T -> P T.
|
||||
Proof.
|
||||
simple induction T; auto with datatypes.
|
||||
intros a G PG D PD PN.
|
||||
elim (invert_heap a G D); auto with datatypes.
|
||||
intros H1 H2; elim H2; intros H3 H4; elim H4; intros.
|
||||
apply X0; auto with datatypes.
|
||||
Qed.
|
||||
|
||||
(* This lemma ought to be generated automatically by the Inversion tools *)
|
||||
Lemma is_heap_rec :
|
||||
forall P:Tree -> Set,
|
||||
P Tree_Leaf ->
|
||||
(forall (a:A) (T1 T2:Tree),
|
||||
leA_Tree a T1 ->
|
||||
leA_Tree a T2 ->
|
||||
is_heap T1 -> P T1 -> is_heap T2 -> P T2 -> P (Tree_Node a T1 T2)) ->
|
||||
forall T:Tree, is_heap T -> P T.
|
||||
Proof.
|
||||
simple induction T; auto with datatypes.
|
||||
intros a G PG D PD PN.
|
||||
elim (invert_heap a G D); auto with datatypes.
|
||||
intros H1 H2; elim H2; intros H3 H4; elim H4; intros.
|
||||
apply X; auto with datatypes.
|
||||
Qed.
|
||||
|
||||
Lemma low_trans :
|
||||
forall (T:Tree) (a b:A), leA a b -> leA_Tree b T -> leA_Tree a T.
|
||||
Proof.
|
||||
simple induction T; auto with datatypes.
|
||||
intros; simpl; apply leA_trans with b; auto with datatypes.
|
||||
Qed.
|
||||
|
||||
(** ** Merging two sorted lists *)
|
||||
|
||||
Inductive merge_lem (l1 l2:list A) : Type :=
|
||||
merge_exist :
|
||||
forall l:list A,
|
||||
Sorted leA l ->
|
||||
meq (list_contents _ eqA_dec l)
|
||||
(munion (list_contents _ eqA_dec l1) (list_contents _ eqA_dec l2)) ->
|
||||
(forall a, HdRel leA a l1 -> HdRel leA a l2 -> HdRel leA a l) ->
|
||||
merge_lem l1 l2.
|
||||
Require Import Morphisms.
|
||||
|
||||
Instance: Equivalence (@meq A).
|
||||
Proof. constructor; auto with datatypes. red. apply meq_trans. Defined.
|
||||
|
||||
Instance: Proper (@meq A ++> @meq _ ++> @meq _) (@munion A).
|
||||
Proof. intros x y H x' y' H'. now apply meq_congr. Qed.
|
||||
|
||||
Lemma merge :
|
||||
forall l1:list A, Sorted leA l1 ->
|
||||
forall l2:list A, Sorted leA l2 -> merge_lem l1 l2.
|
||||
Proof.
|
||||
fix 1; intros; destruct l1.
|
||||
apply merge_exist with l2; auto with datatypes.
|
||||
rename l1 into l.
|
||||
revert l2 H0. fix 1. intros.
|
||||
destruct l2 as [|a0 l0].
|
||||
apply merge_exist with (a :: l); simpl; auto with datatypes.
|
||||
elim (leA_dec a a0); intros.
|
||||
|
||||
(* 1 (leA a a0) *)
|
||||
apply Sorted_inv in H. destruct H.
|
||||
destruct (merge l H (a0 :: l0) H0).
|
||||
apply merge_exist with (a :: l1). clear merge merge0.
|
||||
auto using cons_sort, cons_leA with datatypes.
|
||||
simpl. rewrite m. now rewrite munion_ass.
|
||||
intros. apply cons_leA.
|
||||
apply (@HdRel_inv _ leA) with l; trivial with datatypes.
|
||||
|
||||
(* 2 (leA a0 a) *)
|
||||
apply Sorted_inv in H0. destruct H0.
|
||||
destruct (merge0 l0 H0). clear merge merge0.
|
||||
apply merge_exist with (a0 :: l1);
|
||||
auto using cons_sort, cons_leA with datatypes.
|
||||
simpl; rewrite m. simpl. setoid_rewrite munion_ass at 1. rewrite munion_comm.
|
||||
repeat rewrite munion_ass. setoid_rewrite munion_comm at 3. reflexivity.
|
||||
intros. apply cons_leA.
|
||||
apply (@HdRel_inv _ leA) with l0; trivial with datatypes.
|
||||
Qed.
|
||||
|
||||
(** ** From trees to multisets *)
|
||||
|
||||
(** contents of a tree as a multiset *)
|
||||
|
||||
(** Nota Bene : In what follows the definition of SingletonBag
|
||||
in not used. Actually, we could just take as postulate:
|
||||
[Parameter SingletonBag : A->multiset]. *)
|
||||
|
||||
Fixpoint contents (t:Tree) : multiset A :=
|
||||
match t with
|
||||
| Tree_Leaf => emptyBag
|
||||
| Tree_Node a t1 t2 =>
|
||||
munion (contents t1) (munion (contents t2) (singletonBag a))
|
||||
end.
|
||||
|
||||
|
||||
(** equivalence of two trees is equality of corresponding multisets *)
|
||||
Definition equiv_Tree (t1 t2:Tree) := meq (contents t1) (contents t2).
|
||||
|
||||
|
||||
|
||||
(** * From lists to sorted lists *)
|
||||
|
||||
(** ** Specification of heap insertion *)
|
||||
|
||||
Inductive insert_spec (a:A) (T:Tree) : Type :=
|
||||
insert_exist :
|
||||
forall T1:Tree,
|
||||
is_heap T1 ->
|
||||
meq (contents T1) (munion (contents T) (singletonBag a)) ->
|
||||
(forall b:A, leA b a -> leA_Tree b T -> leA_Tree b T1) ->
|
||||
insert_spec a T.
|
||||
|
||||
|
||||
Lemma insert : forall T:Tree, is_heap T -> forall a:A, insert_spec a T.
|
||||
Proof.
|
||||
simple induction 1; intros.
|
||||
apply insert_exist with (Tree_Node a Tree_Leaf Tree_Leaf);
|
||||
auto using node_is_heap, nil_is_heap, leA_Tree_Leaf with datatypes.
|
||||
simpl; unfold meq, munion; auto using node_is_heap with datatypes.
|
||||
elim (leA_dec a a0); intros.
|
||||
elim (X a0); intros.
|
||||
apply insert_exist with (Tree_Node a T2 T0);
|
||||
auto using node_is_heap, nil_is_heap, leA_Tree_Leaf with datatypes.
|
||||
simpl; apply treesort_twist1; trivial with datatypes.
|
||||
elim (X a); intros T3 HeapT3 ConT3 LeA.
|
||||
apply insert_exist with (Tree_Node a0 T2 T3);
|
||||
auto using node_is_heap, nil_is_heap, leA_Tree_Leaf with datatypes.
|
||||
apply node_is_heap; auto using node_is_heap, nil_is_heap, leA_Tree_Leaf with datatypes.
|
||||
apply low_trans with a; auto with datatypes.
|
||||
apply LeA; auto with datatypes.
|
||||
apply low_trans with a; auto with datatypes.
|
||||
simpl; apply treesort_twist2; trivial with datatypes.
|
||||
Qed.
|
||||
|
||||
|
||||
(** ** Building a heap from a list *)
|
||||
|
||||
Inductive build_heap (l:list A) : Type :=
|
||||
heap_exist :
|
||||
forall T:Tree,
|
||||
is_heap T ->
|
||||
meq (list_contents _ eqA_dec l) (contents T) -> build_heap l.
|
||||
|
||||
Lemma list_to_heap : forall l:list A, build_heap l.
|
||||
Proof.
|
||||
simple induction l.
|
||||
apply (heap_exist nil Tree_Leaf); auto with datatypes.
|
||||
simpl; unfold meq; exact nil_is_heap.
|
||||
simple induction 1.
|
||||
intros T i m; elim (insert T i a).
|
||||
intros; apply heap_exist with T1; simpl; auto with datatypes.
|
||||
apply meq_trans with (munion (contents T) (singletonBag a)).
|
||||
apply meq_trans with (munion (singletonBag a) (contents T)).
|
||||
apply meq_right; trivial with datatypes.
|
||||
apply munion_comm.
|
||||
apply meq_sym; trivial with datatypes.
|
||||
Qed.
|
||||
|
||||
|
||||
(** ** Building the sorted list *)
|
||||
|
||||
Inductive flat_spec (T:Tree) : Type :=
|
||||
flat_exist :
|
||||
forall l:list A,
|
||||
Sorted leA l ->
|
||||
(forall a:A, leA_Tree a T -> HdRel leA a l) ->
|
||||
meq (contents T) (list_contents _ eqA_dec l) -> flat_spec T.
|
||||
|
||||
Lemma heap_to_list : forall T:Tree, is_heap T -> flat_spec T.
|
||||
Proof.
|
||||
intros T h; elim h; intros.
|
||||
apply flat_exist with (nil (A:=A)); auto with datatypes.
|
||||
elim X; intros l1 s1 i1 m1; elim X0; intros l2 s2 i2 m2.
|
||||
elim (merge _ s1 _ s2); intros.
|
||||
apply flat_exist with (a :: l); simpl; auto with datatypes.
|
||||
apply meq_trans with
|
||||
(munion (list_contents _ eqA_dec l1)
|
||||
(munion (list_contents _ eqA_dec l2) (singletonBag a))).
|
||||
apply meq_congr; auto with datatypes.
|
||||
apply meq_trans with
|
||||
(munion (singletonBag a)
|
||||
(munion (list_contents _ eqA_dec l1) (list_contents _ eqA_dec l2))).
|
||||
apply munion_rotate.
|
||||
apply meq_right; apply meq_sym; trivial with datatypes.
|
||||
Qed.
|
||||
|
||||
|
||||
(** * Specification of treesort *)
|
||||
|
||||
Theorem treesort :
|
||||
forall l:list A,
|
||||
{m : list A | Sorted leA m & permutation _ eqA_dec l m}.
|
||||
Proof.
|
||||
intro l; unfold permutation.
|
||||
elim (list_to_heap l).
|
||||
intros.
|
||||
elim (heap_to_list T); auto with datatypes.
|
||||
intros.
|
||||
exists l0; auto with datatypes.
|
||||
apply meq_trans with (contents T); trivial with datatypes.
|
||||
Qed.
|
||||
|
||||
End defs.
|
||||
1558
samples/Coq/Imp.v
Executable file
1558
samples/Coq/Imp.v
Executable file
File diff suppressed because it is too large
Load Diff
591
samples/Coq/Lists.v
Executable file
591
samples/Coq/Lists.v
Executable file
@@ -0,0 +1,591 @@
|
||||
Require Export Basics.
|
||||
Module NatList.
|
||||
Import Playground1.
|
||||
|
||||
Inductive natprod : Type :=
|
||||
pair : nat -> nat -> natprod.
|
||||
|
||||
Definition fst (p : natprod) : nat :=
|
||||
match p with
|
||||
| pair x y => x
|
||||
end.
|
||||
|
||||
Definition snd (p : natprod) : nat :=
|
||||
match p with
|
||||
| pair x y => y
|
||||
end.
|
||||
|
||||
Notation "( x , y )" := (pair x y).
|
||||
|
||||
Definition swap_pair (p : natprod) : natprod :=
|
||||
match p with
|
||||
| (x, y) => (y, x)
|
||||
end.
|
||||
|
||||
Theorem surjective_pairing' : forall (n m : nat),
|
||||
(n, m) = (fst (n, m), snd (n, m)).
|
||||
Proof.
|
||||
reflexivity. Qed.
|
||||
|
||||
Theorem surjective_pairing : forall (p : natprod),
|
||||
p = (fst p, snd p).
|
||||
Proof.
|
||||
intros p.
|
||||
destruct p as (n, m).
|
||||
simpl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem snd_fst_is_swap : forall (p : natprod),
|
||||
(snd p, fst p) = swap_pair p.
|
||||
Proof.
|
||||
intros p.
|
||||
destruct p.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem fst_swap_is_snd : forall (p : natprod),
|
||||
fst (swap_pair p) = snd p.
|
||||
Proof.
|
||||
intros p.
|
||||
destruct p.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Inductive natlist : Type :=
|
||||
| nil : natlist
|
||||
| cons : nat -> natlist -> natlist.
|
||||
|
||||
Definition l_123 := cons (S O) (cons (S (S O)) (cons (S (S (S O))) nil)).
|
||||
|
||||
Notation "x :: l" := (cons x l) (at level 60, right associativity).
|
||||
Notation "[ ]" := nil.
|
||||
Notation "[]" := nil.
|
||||
Notation "[ x , .. , y ]" := (cons x .. (cons y nil) ..).
|
||||
|
||||
Fixpoint repeat (n count : nat) : natlist :=
|
||||
match count with
|
||||
| O => nil
|
||||
| S count' => n :: (repeat n count')
|
||||
end.
|
||||
|
||||
Fixpoint length (l:natlist) : nat :=
|
||||
match l with
|
||||
| nil => O
|
||||
| h :: t => S (length t)
|
||||
end.
|
||||
|
||||
Fixpoint app (l1 l2 : natlist) : natlist :=
|
||||
match l1 with
|
||||
| nil => l2
|
||||
| h :: t => h :: (app t l2)
|
||||
end.
|
||||
|
||||
Notation "x ++ y" := (app x y) (right associativity, at level 60).
|
||||
|
||||
(*
|
||||
Example test_app1: [1,2,3] ++ [4,5] = [1,2,3,4,5].
|
||||
Proof. reflexivity. Qed.
|
||||
Example test_app2: nil ++ [4,5] = [4,5].
|
||||
Proof. reflexivity. Qed.
|
||||
Example test_app3: [1,2,3] ++ [] = [1,2,3].
|
||||
Proof. reflexivity. Qed.
|
||||
*)
|
||||
|
||||
Definition head (l : natlist) : nat :=
|
||||
match l with
|
||||
| nil => O
|
||||
| h :: t => h
|
||||
end.
|
||||
|
||||
Definition tl (l : natlist) : natlist :=
|
||||
match l with
|
||||
| nil => nil
|
||||
| h :: t => t
|
||||
end.
|
||||
|
||||
(*
|
||||
Example test_tl: tl [1,2,3] = [2,3].
|
||||
Proof. reflexivity. Qed.
|
||||
*)
|
||||
|
||||
Fixpoint nonzeros (l:natlist) : natlist :=
|
||||
match l with
|
||||
| nil => nil
|
||||
| O :: r => nonzeros r
|
||||
| n :: r => n :: (nonzeros r)
|
||||
end.
|
||||
|
||||
Example test_nonzeros: nonzeros [O,S O,O,S (S O), S (S (S O)),O,O] = [S O,S (S O), S (S (S O))].
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Fixpoint oddmembers (l:natlist) : natlist :=
|
||||
match l with
|
||||
| nil => nil
|
||||
| n :: r => match (oddb n) with
|
||||
| true => n :: (oddmembers r)
|
||||
| false => oddmembers r
|
||||
end
|
||||
end.
|
||||
|
||||
Example test_oddmembers: oddmembers [O, S O, O, S (S O), S (S (S O)), O, O] = [S O, S (S (S O))].
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Fixpoint countoddmembers (l:natlist) : nat :=
|
||||
length (oddmembers l).
|
||||
|
||||
Example test_countoddmembers2: countoddmembers [O, S (S O), S (S (S (S O)))] = O.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Example test_countoddmembers3: countoddmembers [] = O.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Fixpoint alternate (l1 l2 : natlist) : natlist :=
|
||||
match l1 with
|
||||
| nil => l2
|
||||
| a :: r1 => match l2 with
|
||||
| nil => l1
|
||||
| b :: r2 => a :: b :: (alternate r1 r2)
|
||||
end
|
||||
end.
|
||||
|
||||
Example test_alternative1: alternate [S O, S (S O), S (S (S O))] [S (S (S (S O))), S (S (S (S (S O)))), S (S (S (S (S (S O)))))] =
|
||||
[S O, S (S (S (S O))), S (S O), S (S (S (S (S O)))), S (S (S O)), S (S (S (S (S (S O)))))].
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Definition bag := natlist.
|
||||
|
||||
Fixpoint count (v : nat) (s: bag) : nat :=
|
||||
match s with
|
||||
| nil => O
|
||||
| v' :: r => match (beq_nat v' v) with
|
||||
| true => S (count v r)
|
||||
| false => count v r
|
||||
end
|
||||
end.
|
||||
|
||||
Example test_count1: count (S O) [S O, S (S O), S (S (S O)), S O, S (S (S (S O))), S O] = S (S (S O)).
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Definition sum : bag -> bag -> bag := app.
|
||||
|
||||
Example test_sum1: count (S O) (sum [S O, S (S O), S (S (S O))] [S O, S (S (S (S O))), S O]) = S (S (S O)).
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Definition add (v:nat) (s:bag) : bag := v :: s.
|
||||
|
||||
Example test_add1: count (S O) (add (S O) [S O, S (S (S (S O))), S O]) = S (S (S O)).
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Definition member (v:nat) (s:bag) : bool :=
|
||||
ble_nat (S O) (count v s).
|
||||
|
||||
Example test_member1: member (S O) [S O, S (S (S (S O))), S O] = true.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Example test_member2: member (S (S O)) [S O, S (S (S (S O))), S O] = false.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Fixpoint remove_one (v:nat) (s:bag) : bag :=
|
||||
match s with
|
||||
| nil => nil
|
||||
| v' :: r => match (beq_nat v v') with
|
||||
| true => r
|
||||
| false => v' :: (remove_one v r)
|
||||
end
|
||||
end.
|
||||
|
||||
Example test_remove_one1: count (S (S (S (S (S O)))))
|
||||
(remove_one (S (S (S (S (S O)))))
|
||||
[S (S O), S O, S (S (S (S (S O)))), S (S (S (S O))), S O]) = O.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Fixpoint remove_all (v:nat) (s:bag) : bag :=
|
||||
match s with
|
||||
| nil => nil
|
||||
| v' :: r => match (beq_nat v v') with
|
||||
| true => remove_all v r
|
||||
| false => v' :: (remove_all v r)
|
||||
end
|
||||
end.
|
||||
|
||||
Example test_remove_all1: count (S (S (S (S (S O)))))
|
||||
(remove_all (S (S (S (S (S O)))))
|
||||
[S (S O), S O, S (S (S (S (S O)))), S (S (S (S O))), S O]) = O.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Fixpoint subset (s1:bag) (s2:bag) : bool :=
|
||||
match s1 with
|
||||
| nil => true
|
||||
| v :: r => andb (member v s2)
|
||||
(subset r (remove_one v s2))
|
||||
end.
|
||||
|
||||
Definition test_subset1: subset [S O, S (S O)] [S (S O), S O, S (S (S (S O))), S O] = true.
|
||||
Proof. reflexivity. Qed.
|
||||
Definition test_subset2: subset [S O, S (S O), S (S O)] [S (S O), S O, S (S (S (S O))), S O] = false.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Theorem bag_count_add : forall n t: nat, forall s : bag,
|
||||
count n s = t -> count n (add n s) = S t.
|
||||
Proof.
|
||||
intros n t s.
|
||||
intros H.
|
||||
induction s.
|
||||
simpl.
|
||||
rewrite <- beq_nat_refl.
|
||||
rewrite <- H.
|
||||
reflexivity.
|
||||
rewrite <- H.
|
||||
simpl.
|
||||
rewrite <- beq_nat_refl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem nil_app : forall l:natlist,
|
||||
[] ++ l = l.
|
||||
Proof.
|
||||
reflexivity. Qed.
|
||||
|
||||
Theorem tl_length_pred : forall l:natlist,
|
||||
pred (length l) = length (tl l).
|
||||
Proof.
|
||||
intros l. destruct l as [| n l'].
|
||||
Case "l = nil".
|
||||
reflexivity.
|
||||
Case "l = cons n l'".
|
||||
reflexivity. Qed.
|
||||
|
||||
Theorem app_ass:forall l1 l2 l3 : natlist,
|
||||
(l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3).
|
||||
Proof.
|
||||
intros l1 l2 l3. induction l1 as [| n l1'].
|
||||
Case "l1 = nil".
|
||||
reflexivity.
|
||||
Case "l1 = cons n l1'".
|
||||
simpl. rewrite -> IHl1'. reflexivity. Qed.
|
||||
|
||||
Theorem app_length: forall l1 l2 : natlist,
|
||||
length (l1 ++ l2) = (length l1) + (length l2).
|
||||
Proof.
|
||||
intros l1 l2. induction l1 as [| n l1'].
|
||||
Case "l1 = nil".
|
||||
reflexivity.
|
||||
Case "l1 = cons".
|
||||
simpl. rewrite -> IHl1'. reflexivity. Qed.
|
||||
|
||||
Fixpoint snoc (l:natlist) (v:nat) : natlist :=
|
||||
match l with
|
||||
| nil => [v]
|
||||
| h :: t => h :: (snoc t v)
|
||||
end.
|
||||
|
||||
Fixpoint rev (l:natlist) : natlist :=
|
||||
match l with
|
||||
| nil => nil
|
||||
| h :: t => snoc (rev t) h
|
||||
end.
|
||||
|
||||
Example test_rev1: rev [S O, S (S O), S (S (S O))] = [S (S (S O)), S (S O), S O].
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Theorem length_snoc : forall n : nat, forall l : natlist,
|
||||
length (snoc l n) = S (length l).
|
||||
Proof.
|
||||
intros n l. induction l as [| n' l'].
|
||||
Case "l = nil".
|
||||
reflexivity.
|
||||
Case "l = cons n' l'".
|
||||
simpl. rewrite -> IHl'. reflexivity. Qed.
|
||||
|
||||
Theorem rev_length : forall l : natlist,
|
||||
length (rev l) = length l.
|
||||
Proof.
|
||||
intros l. induction l as [| n l'].
|
||||
Case "l = nil".
|
||||
reflexivity.
|
||||
Case "l = cons".
|
||||
simpl. rewrite -> length_snoc.
|
||||
rewrite -> IHl'. reflexivity. Qed.
|
||||
|
||||
Theorem app_nil_end : forall l :natlist,
|
||||
l ++ [] = l.
|
||||
Proof.
|
||||
intros l.
|
||||
induction l.
|
||||
Case "l = nil".
|
||||
reflexivity.
|
||||
Case "l = cons".
|
||||
simpl. rewrite -> IHl. reflexivity. Qed.
|
||||
|
||||
|
||||
|
||||
Theorem rev_snoc : forall l: natlist, forall n : nat,
|
||||
rev (snoc l n) = n :: (rev l).
|
||||
Proof.
|
||||
intros l n.
|
||||
induction l.
|
||||
Case "l = nil".
|
||||
reflexivity.
|
||||
Case "l = cons".
|
||||
simpl.
|
||||
rewrite -> IHl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem rev_involutive : forall l : natlist,
|
||||
rev (rev l) = l.
|
||||
Proof.
|
||||
intros l.
|
||||
induction l.
|
||||
Case "l = nil".
|
||||
reflexivity.
|
||||
Case "l = cons".
|
||||
simpl.
|
||||
rewrite -> rev_snoc.
|
||||
rewrite -> IHl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem app_ass4 : forall l1 l2 l3 l4 : natlist,
|
||||
l1 ++ (l2 ++ (l3 ++ l4)) = ((l1 ++ l2) ++ l3) ++ l4.
|
||||
Proof.
|
||||
intros l1 l2 l3 l4.
|
||||
rewrite -> app_ass.
|
||||
rewrite -> app_ass.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem snoc_append : forall (l : natlist) (n : nat),
|
||||
snoc l n = l ++ [n].
|
||||
Proof.
|
||||
intros l n.
|
||||
induction l.
|
||||
Case "l = nil".
|
||||
reflexivity.
|
||||
Case "l = cons".
|
||||
simpl.
|
||||
rewrite -> IHl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem nonzeros_length : forall l1 l2 : natlist,
|
||||
nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2).
|
||||
Proof.
|
||||
intros l1 l2.
|
||||
induction l1.
|
||||
Case "l1 = nil".
|
||||
reflexivity.
|
||||
Case "l1 = cons".
|
||||
simpl.
|
||||
rewrite -> IHl1.
|
||||
destruct n.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem distr_rev : forall l1 l2 : natlist,
|
||||
rev (l1 ++ l2) = (rev l2) ++ (rev l1).
|
||||
Proof.
|
||||
intros l1 l2.
|
||||
induction l1.
|
||||
Case "l1 = nil".
|
||||
simpl.
|
||||
rewrite -> app_nil_end.
|
||||
reflexivity.
|
||||
Case "l1 = cons".
|
||||
simpl.
|
||||
rewrite -> IHl1.
|
||||
simpl.
|
||||
rewrite -> snoc_append.
|
||||
rewrite -> snoc_append.
|
||||
rewrite -> app_ass.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem count_number_nonzero : forall (s : bag),
|
||||
ble_nat O (count (S O) (S O :: s)) = true.
|
||||
Proof.
|
||||
intros s.
|
||||
induction s.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem ble_n_Sn : forall n,
|
||||
ble_nat n (S n) = true.
|
||||
Proof.
|
||||
intros n. induction n as [| n'].
|
||||
Case "0".
|
||||
simpl. reflexivity.
|
||||
Case "S n'".
|
||||
simpl. rewrite -> IHn'. reflexivity. Qed.
|
||||
|
||||
Theorem remove_decreases_count: forall (s : bag),
|
||||
ble_nat (count O (remove_one O s)) (count O s) = true.
|
||||
Proof.
|
||||
intros s.
|
||||
induction s.
|
||||
Case "s = nil".
|
||||
reflexivity.
|
||||
Case "s = cons".
|
||||
simpl.
|
||||
induction n.
|
||||
SCase "n = O".
|
||||
simpl. rewrite -> ble_n_Sn.
|
||||
reflexivity.
|
||||
SCase "n = S n'".
|
||||
simpl.
|
||||
rewrite -> IHs.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Inductive natoption : Type :=
|
||||
| Some : nat -> natoption
|
||||
| None : natoption.
|
||||
|
||||
Fixpoint index (n:nat) (l:natlist) : natoption :=
|
||||
match l with
|
||||
| nil => None
|
||||
| a :: l' => if beq_nat n O then Some a else index (pred n) l'
|
||||
end.
|
||||
|
||||
Definition option_elim (o : natoption) (d : nat) : nat :=
|
||||
match o with
|
||||
| Some n' => n'
|
||||
| None => d
|
||||
end.
|
||||
|
||||
Definition hd_opt (l : natlist) : natoption :=
|
||||
match l with
|
||||
| nil => None
|
||||
| v :: r => Some v
|
||||
end.
|
||||
|
||||
Example test_hd_opt1 : hd_opt [] = None.
|
||||
Proof. reflexivity. Qed.
|
||||
Example test_hd_opt2 : hd_opt [S O] = Some (S O).
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Theorem option_elim_hd : forall l:natlist,
|
||||
head l = option_elim (hd_opt l) O.
|
||||
Proof.
|
||||
intros l.
|
||||
destruct l.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Fixpoint beq_natlist (l1 l2 : natlist) : bool :=
|
||||
match l1 with
|
||||
| nil => match l2 with
|
||||
| nil => true
|
||||
| _ => false
|
||||
end
|
||||
| v1 :: r1 => match l2 with
|
||||
| nil => false
|
||||
| v2 :: r2 => if beq_nat v1 v2 then beq_natlist r1 r2
|
||||
else false
|
||||
end
|
||||
end.
|
||||
|
||||
Example test_beq_natlist1 : (beq_natlist nil nil = true).
|
||||
Proof. reflexivity. Qed.
|
||||
Example test_beq_natlist2 : (beq_natlist [S O, S (S O), S (S (S O))]
|
||||
[S O, S (S O), S (S (S O))] = true).
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Theorem beq_natlist_refl : forall l:natlist,
|
||||
beq_natlist l l = true.
|
||||
Proof.
|
||||
intros l.
|
||||
induction l.
|
||||
Case "l = nil".
|
||||
reflexivity.
|
||||
Case "l = cons".
|
||||
simpl.
|
||||
rewrite <- beq_nat_refl.
|
||||
rewrite -> IHl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem silly1 : forall (n m o p : nat),
|
||||
n = m -> [n, o] = [n, p] -> [n, o] = [m, p].
|
||||
Proof.
|
||||
intros n m o p eq1 eq2.
|
||||
rewrite <- eq1.
|
||||
apply eq2. Qed.
|
||||
|
||||
Theorem silly2a : forall (n m : nat),
|
||||
(n,n) = (m,m) ->
|
||||
(forall (q r : nat), (q, q) = (r, r) -> [q] = [r]) ->
|
||||
[n] = [m].
|
||||
Proof.
|
||||
intros n m eq1 eq2.
|
||||
apply eq2.
|
||||
apply eq1.
|
||||
Qed.
|
||||
|
||||
Theorem silly_ex :
|
||||
(forall n, evenb n = true -> oddb (S n) = true) ->
|
||||
evenb (S (S (S O))) = true ->
|
||||
oddb (S (S (S (S O)))) = true.
|
||||
Proof.
|
||||
intros eq1 eq2.
|
||||
apply eq1.
|
||||
apply eq2.
|
||||
Qed.
|
||||
|
||||
Theorem silly3 : forall (n : nat),
|
||||
true = beq_nat n (S (S (S (S (S O))))) ->
|
||||
beq_nat (S (S n)) (S (S (S (S (S (S (S O))))))) = true.
|
||||
Proof.
|
||||
intros n H.
|
||||
symmetry.
|
||||
apply H.
|
||||
Qed.
|
||||
|
||||
Theorem rev_exercise : forall (l l' : natlist),
|
||||
l = rev l' -> l' = rev l.
|
||||
Proof.
|
||||
intros l l' H.
|
||||
rewrite -> H.
|
||||
rewrite -> rev_involutive.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem beq_nat_sym : forall (n m:nat), forall (b: bool),
|
||||
beq_nat n m = b -> beq_nat m n = b.
|
||||
Proof.
|
||||
intros n.
|
||||
induction n as [| n'].
|
||||
Case "n = O".
|
||||
intros m b eq1.
|
||||
induction m.
|
||||
SCase "m = 0".
|
||||
apply eq1.
|
||||
SCase "m = S m'".
|
||||
apply eq1.
|
||||
Case "n = S n'".
|
||||
induction m.
|
||||
SCase "m = 0".
|
||||
intros b eq1.
|
||||
apply eq1.
|
||||
SCase "m = S m'".
|
||||
intros b eq1.
|
||||
apply IHn'.
|
||||
apply eq1.
|
||||
Qed.
|
||||
|
||||
Theorem app_ass' : forall l1 l2 l3 : natlist,
|
||||
(l1 ++ l2) ++ l3 = l1 ++ (l2 ++ l3).
|
||||
Proof.
|
||||
intros l1. induction l1 as [ | n l1'].
|
||||
reflexivity.
|
||||
simpl.
|
||||
intros l2 l3.
|
||||
rewrite -> IHl1'.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
End NatList.
|
||||
539
samples/Coq/PermutSetoid.v
Executable file
539
samples/Coq/PermutSetoid.v
Executable file
@@ -0,0 +1,539 @@
|
||||
Require Import Omega Relations Multiset SetoidList.
|
||||
|
||||
(** This file is deprecated, use [Permutation.v] instead.
|
||||
|
||||
Indeed, this file defines a notion of permutation based on
|
||||
multisets (there exists a permutation between two lists iff every
|
||||
elements have the same multiplicity in the two lists) which
|
||||
requires a more complex apparatus (the equipment of the domain
|
||||
with a decidable equality) than [Permutation] in [Permutation.v].
|
||||
|
||||
The relation between the two relations are in lemma
|
||||
[permutation_Permutation].
|
||||
|
||||
File [Permutation] concerns Leibniz equality : it shows in particular
|
||||
that [List.Permutation] and [permutation] are equivalent in this context.
|
||||
*)
|
||||
|
||||
Set Implicit Arguments.
|
||||
|
||||
Local Notation "[ ]" := nil.
|
||||
Local Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..).
|
||||
|
||||
Section Permut.
|
||||
|
||||
(** * From lists to multisets *)
|
||||
|
||||
Variable A : Type.
|
||||
Variable eqA : relation A.
|
||||
Hypothesis eqA_equiv : Equivalence eqA.
|
||||
Hypothesis eqA_dec : forall x y:A, {eqA x y} + {~ eqA x y}.
|
||||
|
||||
Let emptyBag := EmptyBag A.
|
||||
Let singletonBag := SingletonBag _ eqA_dec.
|
||||
|
||||
(** contents of a list *)
|
||||
|
||||
Fixpoint list_contents (l:list A) : multiset A :=
|
||||
match l with
|
||||
| [] => emptyBag
|
||||
| a :: l => munion (singletonBag a) (list_contents l)
|
||||
end.
|
||||
|
||||
Lemma list_contents_app :
|
||||
forall l m:list A,
|
||||
meq (list_contents (l ++ m)) (munion (list_contents l) (list_contents m)).
|
||||
Proof.
|
||||
simple induction l; simpl; auto with datatypes.
|
||||
intros.
|
||||
apply meq_trans with
|
||||
(munion (singletonBag a) (munion (list_contents l0) (list_contents m)));
|
||||
auto with datatypes.
|
||||
Qed.
|
||||
|
||||
(** * [permutation]: definition and basic properties *)
|
||||
|
||||
Definition permutation (l m:list A) := meq (list_contents l) (list_contents m).
|
||||
|
||||
Lemma permut_refl : forall l:list A, permutation l l.
|
||||
Proof.
|
||||
unfold permutation; auto with datatypes.
|
||||
Qed.
|
||||
|
||||
Lemma permut_sym :
|
||||
forall l1 l2 : list A, permutation l1 l2 -> permutation l2 l1.
|
||||
Proof.
|
||||
unfold permutation, meq; intros; symmetry; trivial.
|
||||
Qed.
|
||||
|
||||
Lemma permut_trans :
|
||||
forall l m n:list A, permutation l m -> permutation m n -> permutation l n.
|
||||
Proof.
|
||||
unfold permutation; intros.
|
||||
apply meq_trans with (list_contents m); auto with datatypes.
|
||||
Qed.
|
||||
|
||||
Lemma permut_cons_eq :
|
||||
forall l m:list A,
|
||||
permutation l m -> forall a a', eqA a a' -> permutation (a :: l) (a' :: m).
|
||||
Proof.
|
||||
unfold permutation; simpl; intros.
|
||||
apply meq_trans with (munion (singletonBag a') (list_contents l)).
|
||||
apply meq_left, meq_singleton; auto.
|
||||
auto with datatypes.
|
||||
Qed.
|
||||
|
||||
Lemma permut_cons :
|
||||
forall l m:list A,
|
||||
permutation l m -> forall a:A, permutation (a :: l) (a :: m).
|
||||
Proof.
|
||||
unfold permutation; simpl; auto with datatypes.
|
||||
Qed.
|
||||
|
||||
Lemma permut_app :
|
||||
forall l l' m m':list A,
|
||||
permutation l l' -> permutation m m' -> permutation (l ++ m) (l' ++ m').
|
||||
Proof.
|
||||
unfold permutation; intros.
|
||||
apply meq_trans with (munion (list_contents l) (list_contents m));
|
||||
auto using permut_cons, list_contents_app with datatypes.
|
||||
apply meq_trans with (munion (list_contents l') (list_contents m'));
|
||||
auto using permut_cons, list_contents_app with datatypes.
|
||||
apply meq_trans with (munion (list_contents l') (list_contents m));
|
||||
auto using permut_cons, list_contents_app with datatypes.
|
||||
Qed.
|
||||
|
||||
Lemma permut_add_inside_eq :
|
||||
forall a a' l1 l2 l3 l4, eqA a a' ->
|
||||
permutation (l1 ++ l2) (l3 ++ l4) ->
|
||||
permutation (l1 ++ a :: l2) (l3 ++ a' :: l4).
|
||||
Proof.
|
||||
unfold permutation, meq in *; intros.
|
||||
specialize H0 with a0.
|
||||
repeat rewrite list_contents_app in *; simpl in *.
|
||||
destruct (eqA_dec a a0) as [Ha|Ha]; rewrite H in Ha;
|
||||
decide (eqA_dec a' a0) with Ha; simpl; auto with arith.
|
||||
do 2 rewrite <- plus_n_Sm; f_equal; auto.
|
||||
Qed.
|
||||
|
||||
Lemma permut_add_inside :
|
||||
forall a l1 l2 l3 l4,
|
||||
permutation (l1 ++ l2) (l3 ++ l4) ->
|
||||
permutation (l1 ++ a :: l2) (l3 ++ a :: l4).
|
||||
Proof.
|
||||
unfold permutation, meq in *; intros.
|
||||
generalize (H a0); clear H.
|
||||
do 4 rewrite list_contents_app.
|
||||
simpl.
|
||||
destruct (eqA_dec a a0); simpl; auto with arith.
|
||||
do 2 rewrite <- plus_n_Sm; f_equal; auto.
|
||||
Qed.
|
||||
|
||||
Lemma permut_add_cons_inside_eq :
|
||||
forall a a' l l1 l2, eqA a a' ->
|
||||
permutation l (l1 ++ l2) ->
|
||||
permutation (a :: l) (l1 ++ a' :: l2).
|
||||
Proof.
|
||||
intros;
|
||||
replace (a :: l) with ([] ++ a :: l); trivial;
|
||||
apply permut_add_inside_eq; trivial.
|
||||
Qed.
|
||||
|
||||
Lemma permut_add_cons_inside :
|
||||
forall a l l1 l2,
|
||||
permutation l (l1 ++ l2) ->
|
||||
permutation (a :: l) (l1 ++ a :: l2).
|
||||
Proof.
|
||||
intros;
|
||||
replace (a :: l) with ([] ++ a :: l); trivial;
|
||||
apply permut_add_inside; trivial.
|
||||
Qed.
|
||||
|
||||
Lemma permut_middle :
|
||||
forall (l m:list A) (a:A), permutation (a :: l ++ m) (l ++ a :: m).
|
||||
Proof.
|
||||
intros; apply permut_add_cons_inside; auto using permut_sym, permut_refl.
|
||||
Qed.
|
||||
|
||||
Lemma permut_sym_app :
|
||||
forall l1 l2, permutation (l1 ++ l2) (l2 ++ l1).
|
||||
Proof.
|
||||
intros l1 l2;
|
||||
unfold permutation, meq;
|
||||
intro a; do 2 rewrite list_contents_app; simpl;
|
||||
auto with arith.
|
||||
Qed.
|
||||
|
||||
Lemma permut_rev :
|
||||
forall l, permutation l (rev l).
|
||||
Proof.
|
||||
induction l.
|
||||
simpl; trivial using permut_refl.
|
||||
simpl.
|
||||
apply permut_add_cons_inside.
|
||||
rewrite <- app_nil_end. trivial.
|
||||
Qed.
|
||||
|
||||
(** * Some inversion results. *)
|
||||
Lemma permut_conv_inv :
|
||||
forall e l1 l2, permutation (e :: l1) (e :: l2) -> permutation l1 l2.
|
||||
Proof.
|
||||
intros e l1 l2; unfold permutation, meq; simpl; intros H a;
|
||||
generalize (H a); apply plus_reg_l.
|
||||
Qed.
|
||||
|
||||
Lemma permut_app_inv1 :
|
||||
forall l l1 l2, permutation (l1 ++ l) (l2 ++ l) -> permutation l1 l2.
|
||||
Proof.
|
||||
intros l l1 l2; unfold permutation, meq; simpl;
|
||||
intros H a; generalize (H a); clear H.
|
||||
do 2 rewrite list_contents_app.
|
||||
simpl.
|
||||
intros; apply plus_reg_l with (multiplicity (list_contents l) a).
|
||||
rewrite plus_comm; rewrite H; rewrite plus_comm.
|
||||
trivial.
|
||||
Qed.
|
||||
|
||||
(** we can use [multiplicity] to define [InA] and [NoDupA]. *)
|
||||
|
||||
Fact if_eqA_then : forall a a' (B:Type)(b b':B),
|
||||
eqA a a' -> (if eqA_dec a a' then b else b') = b.
|
||||
Proof.
|
||||
intros. destruct eqA_dec as [_|NEQ]; auto.
|
||||
contradict NEQ; auto.
|
||||
Qed.
|
||||
|
||||
Lemma permut_app_inv2 :
|
||||
forall l l1 l2, permutation (l ++ l1) (l ++ l2) -> permutation l1 l2.
|
||||
Proof.
|
||||
intros l l1 l2; unfold permutation, meq; simpl;
|
||||
intros H a; generalize (H a); clear H.
|
||||
do 2 rewrite list_contents_app.
|
||||
simpl.
|
||||
intros; apply plus_reg_l with (multiplicity (list_contents l) a).
|
||||
trivial.
|
||||
Qed.
|
||||
|
||||
Lemma permut_remove_hd_eq :
|
||||
forall l l1 l2 a b, eqA a b ->
|
||||
permutation (a :: l) (l1 ++ b :: l2) -> permutation l (l1 ++ l2).
|
||||
Proof.
|
||||
unfold permutation, meq; simpl; intros l l1 l2 a b Heq H a0.
|
||||
specialize H with a0.
|
||||
rewrite list_contents_app in *; simpl in *.
|
||||
apply plus_reg_l with (if eqA_dec a a0 then 1 else 0).
|
||||
rewrite H; clear H.
|
||||
symmetry; rewrite plus_comm, <- ! plus_assoc; f_equal.
|
||||
rewrite plus_comm.
|
||||
destruct (eqA_dec a a0) as [Ha|Ha]; rewrite Heq in Ha;
|
||||
decide (eqA_dec b a0) with Ha; reflexivity.
|
||||
Qed.
|
||||
|
||||
Lemma permut_remove_hd :
|
||||
forall l l1 l2 a,
|
||||
permutation (a :: l) (l1 ++ a :: l2) -> permutation l (l1 ++ l2).
|
||||
Proof.
|
||||
eauto using permut_remove_hd_eq, Equivalence_Reflexive.
|
||||
Qed.
|
||||
|
||||
Fact if_eqA_else : forall a a' (B:Type)(b b':B),
|
||||
~eqA a a' -> (if eqA_dec a a' then b else b') = b'.
|
||||
Proof.
|
||||
intros. decide (eqA_dec a a') with H; auto.
|
||||
Qed.
|
||||
|
||||
Fact if_eqA_refl : forall a (B:Type)(b b':B),
|
||||
(if eqA_dec a a then b else b') = b.
|
||||
Proof.
|
||||
intros; apply (decide_left (eqA_dec a a)); auto with *.
|
||||
Qed.
|
||||
|
||||
(** PL: Inutilisable dans un rewrite sans un change prealable. *)
|
||||
|
||||
Global Instance if_eqA (B:Type)(b b':B) :
|
||||
Proper (eqA==>eqA==>@eq _) (fun x y => if eqA_dec x y then b else b').
|
||||
Proof.
|
||||
intros x x' Hxx' y y' Hyy'.
|
||||
intros; destruct (eqA_dec x y) as [H|H];
|
||||
destruct (eqA_dec x' y') as [H'|H']; auto.
|
||||
contradict H'; transitivity x; auto with *; transitivity y; auto with *.
|
||||
contradict H; transitivity x'; auto with *; transitivity y'; auto with *.
|
||||
Qed.
|
||||
|
||||
Fact if_eqA_rewrite_l : forall a1 a1' a2 (B:Type)(b b':B),
|
||||
eqA a1 a1' -> (if eqA_dec a1 a2 then b else b') =
|
||||
(if eqA_dec a1' a2 then b else b').
|
||||
Proof.
|
||||
intros; destruct (eqA_dec a1 a2) as [A1|A1];
|
||||
destruct (eqA_dec a1' a2) as [A1'|A1']; auto.
|
||||
contradict A1'; transitivity a1; eauto with *.
|
||||
contradict A1; transitivity a1'; eauto with *.
|
||||
Qed.
|
||||
|
||||
Fact if_eqA_rewrite_r : forall a1 a2 a2' (B:Type)(b b':B),
|
||||
eqA a2 a2' -> (if eqA_dec a1 a2 then b else b') =
|
||||
(if eqA_dec a1 a2' then b else b').
|
||||
Proof.
|
||||
intros; destruct (eqA_dec a1 a2) as [A2|A2];
|
||||
destruct (eqA_dec a1 a2') as [A2'|A2']; auto.
|
||||
contradict A2'; transitivity a2; eauto with *.
|
||||
contradict A2; transitivity a2'; eauto with *.
|
||||
Qed.
|
||||
|
||||
|
||||
Global Instance multiplicity_eqA (l:list A) :
|
||||
Proper (eqA==>@eq _) (multiplicity (list_contents l)).
|
||||
Proof.
|
||||
intros x x' Hxx'.
|
||||
induction l as [|y l Hl]; simpl; auto.
|
||||
rewrite (@if_eqA_rewrite_r y x x'); auto.
|
||||
Qed.
|
||||
|
||||
Lemma multiplicity_InA :
|
||||
forall l a, InA eqA a l <-> 0 < multiplicity (list_contents l) a.
|
||||
Proof.
|
||||
induction l.
|
||||
simpl.
|
||||
split; inversion 1.
|
||||
simpl.
|
||||
intros a'; split; intros H. inversion_clear H.
|
||||
apply (decide_left (eqA_dec a a')); auto with *.
|
||||
destruct (eqA_dec a a'); auto with *. simpl; rewrite <- IHl; auto.
|
||||
destruct (eqA_dec a a'); auto with *. right. rewrite IHl; auto.
|
||||
Qed.
|
||||
|
||||
Lemma multiplicity_InA_O :
|
||||
forall l a, ~ InA eqA a l -> multiplicity (list_contents l) a = 0.
|
||||
Proof.
|
||||
intros l a; rewrite multiplicity_InA;
|
||||
destruct (multiplicity (list_contents l) a); auto with arith.
|
||||
destruct 1; auto with arith.
|
||||
Qed.
|
||||
|
||||
Lemma multiplicity_InA_S :
|
||||
forall l a, InA eqA a l -> multiplicity (list_contents l) a >= 1.
|
||||
Proof.
|
||||
intros l a; rewrite multiplicity_InA; auto with arith.
|
||||
Qed.
|
||||
|
||||
Lemma multiplicity_NoDupA : forall l,
|
||||
NoDupA eqA l <-> (forall a, multiplicity (list_contents l) a <= 1).
|
||||
Proof.
|
||||
induction l.
|
||||
simpl.
|
||||
split; auto with arith.
|
||||
split; simpl.
|
||||
inversion_clear 1.
|
||||
rewrite IHl in H1.
|
||||
intros; destruct (eqA_dec a a0) as [EQ|NEQ]; simpl; auto with *.
|
||||
rewrite <- EQ.
|
||||
rewrite multiplicity_InA_O; auto.
|
||||
intros; constructor.
|
||||
rewrite multiplicity_InA.
|
||||
specialize (H a).
|
||||
rewrite if_eqA_refl in H.
|
||||
clear IHl; omega.
|
||||
rewrite IHl; intros.
|
||||
specialize (H a0). omega.
|
||||
Qed.
|
||||
|
||||
(** Permutation is compatible with InA. *)
|
||||
Lemma permut_InA_InA :
|
||||
forall l1 l2 e, permutation l1 l2 -> InA eqA e l1 -> InA eqA e l2.
|
||||
Proof.
|
||||
intros l1 l2 e.
|
||||
do 2 rewrite multiplicity_InA.
|
||||
unfold permutation, meq.
|
||||
intros H;rewrite H; auto.
|
||||
Qed.
|
||||
|
||||
Lemma permut_cons_InA :
|
||||
forall l1 l2 e, permutation (e :: l1) l2 -> InA eqA e l2.
|
||||
Proof.
|
||||
intros; apply (permut_InA_InA (e:=e) H); auto with *.
|
||||
Qed.
|
||||
|
||||
(** Permutation of an empty list. *)
|
||||
Lemma permut_nil :
|
||||
forall l, permutation l [] -> l = [].
|
||||
Proof.
|
||||
intro l; destruct l as [ | e l ]; trivial.
|
||||
assert (InA eqA e (e::l)) by (auto with *).
|
||||
intro Abs; generalize (permut_InA_InA Abs H).
|
||||
inversion 1.
|
||||
Qed.
|
||||
|
||||
(** Permutation for short lists. *)
|
||||
|
||||
Lemma permut_length_1:
|
||||
forall a b, permutation [a] [b] -> eqA a b.
|
||||
Proof.
|
||||
intros a b; unfold permutation, meq.
|
||||
intro P; specialize (P b); simpl in *.
|
||||
rewrite if_eqA_refl in *.
|
||||
destruct (eqA_dec a b); simpl; auto; discriminate.
|
||||
Qed.
|
||||
|
||||
Lemma permut_length_2 :
|
||||
forall a1 b1 a2 b2, permutation [a1; b1] [a2; b2] ->
|
||||
(eqA a1 a2) /\ (eqA b1 b2) \/ (eqA a1 b2) /\ (eqA a2 b1).
|
||||
Proof.
|
||||
intros a1 b1 a2 b2 P.
|
||||
assert (H:=permut_cons_InA P).
|
||||
inversion_clear H.
|
||||
left; split; auto.
|
||||
apply permut_length_1.
|
||||
red; red; intros.
|
||||
specialize (P a). simpl in *.
|
||||
rewrite (@if_eqA_rewrite_l a1 a2 a) in P by auto. omega.
|
||||
right.
|
||||
inversion_clear H0; [|inversion H].
|
||||
split; auto.
|
||||
apply permut_length_1.
|
||||
red; red; intros.
|
||||
specialize (P a); simpl in *.
|
||||
rewrite (@if_eqA_rewrite_l a1 b2 a) in P by auto. omega.
|
||||
Qed.
|
||||
|
||||
(** Permutation is compatible with length. *)
|
||||
Lemma permut_length :
|
||||
forall l1 l2, permutation l1 l2 -> length l1 = length l2.
|
||||
Proof.
|
||||
induction l1; intros l2 H.
|
||||
rewrite (permut_nil (permut_sym H)); auto.
|
||||
assert (H0:=permut_cons_InA H).
|
||||
destruct (InA_split H0) as (h2,(b,(t2,(H1,H2)))).
|
||||
subst l2.
|
||||
rewrite app_length.
|
||||
simpl; rewrite <- plus_n_Sm; f_equal.
|
||||
rewrite <- app_length.
|
||||
apply IHl1.
|
||||
apply permut_remove_hd with b.
|
||||
apply permut_trans with (a::l1); auto.
|
||||
revert H1; unfold permutation, meq; simpl.
|
||||
intros; f_equal; auto.
|
||||
rewrite (@if_eqA_rewrite_l a b a0); auto.
|
||||
Qed.
|
||||
|
||||
Lemma NoDupA_equivlistA_permut :
|
||||
forall l l', NoDupA eqA l -> NoDupA eqA l' ->
|
||||
equivlistA eqA l l' -> permutation l l'.
|
||||
Proof.
|
||||
intros.
|
||||
red; unfold meq; intros.
|
||||
rewrite multiplicity_NoDupA in H, H0.
|
||||
generalize (H a) (H0 a) (H1 a); clear H H0 H1.
|
||||
do 2 rewrite multiplicity_InA.
|
||||
destruct 3; omega.
|
||||
Qed.
|
||||
|
||||
End Permut.
|
||||
|
||||
Section Permut_map.
|
||||
|
||||
Variables A B : Type.
|
||||
|
||||
Variable eqA : relation A.
|
||||
Hypothesis eqA_dec : forall x y:A, {eqA x y} + {~ eqA x y}.
|
||||
Hypothesis eqA_equiv : Equivalence eqA.
|
||||
|
||||
Variable eqB : B->B->Prop.
|
||||
Hypothesis eqB_dec : forall x y:B, { eqB x y }+{ ~eqB x y }.
|
||||
Hypothesis eqB_trans : Transitive eqB.
|
||||
|
||||
(** Permutation is compatible with map. *)
|
||||
|
||||
Lemma permut_map :
|
||||
forall f,
|
||||
(Proper (eqA==>eqB) f) ->
|
||||
forall l1 l2, permutation _ eqA_dec l1 l2 ->
|
||||
permutation _ eqB_dec (map f l1) (map f l2).
|
||||
Proof.
|
||||
intros f; induction l1.
|
||||
intros l2 P; rewrite (permut_nil eqA_equiv (permut_sym P)); apply permut_refl.
|
||||
intros l2 P.
|
||||
simpl.
|
||||
assert (H0:=permut_cons_InA eqA_equiv P).
|
||||
destruct (InA_split H0) as (h2,(b,(t2,(H1,H2)))).
|
||||
subst l2.
|
||||
rewrite map_app.
|
||||
simpl.
|
||||
apply permut_trans with (f b :: map f l1).
|
||||
revert H1; unfold permutation, meq; simpl.
|
||||
intros; f_equal; auto.
|
||||
destruct (eqB_dec (f b) a0) as [H2|H2];
|
||||
destruct (eqB_dec (f a) a0) as [H3|H3]; auto.
|
||||
destruct H3; transitivity (f b); auto with *.
|
||||
destruct H2; transitivity (f a); auto with *.
|
||||
apply permut_add_cons_inside.
|
||||
rewrite <- map_app.
|
||||
apply IHl1; auto.
|
||||
apply permut_remove_hd with b; trivial.
|
||||
apply permut_trans with (a::l1); auto.
|
||||
revert H1; unfold permutation, meq; simpl.
|
||||
intros; f_equal; auto.
|
||||
rewrite (@if_eqA_rewrite_l _ _ eqA_equiv eqA_dec a b a0); auto.
|
||||
Qed.
|
||||
|
||||
End Permut_map.
|
||||
|
||||
Require Import Permutation.
|
||||
|
||||
Section Permut_permut.
|
||||
|
||||
Variable A : Type.
|
||||
|
||||
Variable eqA : relation A.
|
||||
Hypothesis eqA_dec : forall x y:A, {eqA x y} + {~ eqA x y}.
|
||||
Hypothesis eqA_equiv : Equivalence eqA.
|
||||
|
||||
Lemma Permutation_impl_permutation : forall l l',
|
||||
Permutation l l' -> permutation _ eqA_dec l l'.
|
||||
Proof.
|
||||
induction 1.
|
||||
apply permut_refl.
|
||||
apply permut_cons; auto using Equivalence_Reflexive.
|
||||
change (x :: y :: l) with ([x] ++ y :: l);
|
||||
apply permut_add_cons_inside; simpl;
|
||||
apply permut_cons_eq; auto using Equivalence_Reflexive, permut_refl.
|
||||
apply permut_trans with l'; trivial.
|
||||
Qed.
|
||||
|
||||
Lemma permut_eqA : forall l l', Forall2 eqA l l' -> permutation _ eqA_dec l l'.
|
||||
Proof.
|
||||
induction 1.
|
||||
apply permut_refl.
|
||||
apply permut_cons_eq; trivial.
|
||||
Qed.
|
||||
|
||||
Lemma permutation_Permutation : forall l l',
|
||||
permutation _ eqA_dec l l' <->
|
||||
exists l'', Permutation l l'' /\ Forall2 eqA l'' l'.
|
||||
Proof.
|
||||
split; intro H.
|
||||
(* -> *)
|
||||
induction l in l', H |- *.
|
||||
exists []; apply permut_sym, permut_nil in H as ->; auto using Forall2.
|
||||
pose proof H as H'.
|
||||
apply permut_cons_InA, InA_split in H
|
||||
as (l1 & y & l2 & Heq & ->); trivial.
|
||||
apply permut_remove_hd_eq, IHl in H'
|
||||
as (l'' & IHP & IHA); clear IHl; trivial.
|
||||
apply Forall2_app_inv_r in IHA as (l1'' & l2'' & Hl1 & Hl2 & ->).
|
||||
exists (l1'' ++ a :: l2''); split.
|
||||
apply Permutation_cons_app; trivial.
|
||||
apply Forall2_app, Forall2_cons; trivial.
|
||||
(* <- *)
|
||||
destruct H as (l'' & H & Heq).
|
||||
apply permut_trans with l''.
|
||||
apply Permutation_impl_permutation; trivial.
|
||||
apply permut_eqA; trivial.
|
||||
Qed.
|
||||
|
||||
End Permut_permut.
|
||||
|
||||
(* begin hide *)
|
||||
(** For compatibilty *)
|
||||
Notation permut_right := permut_cons (only parsing).
|
||||
Notation permut_tran := permut_trans (only parsing).
|
||||
(* end hide *)
|
||||
632
samples/Coq/Permutation.v
Executable file
632
samples/Coq/Permutation.v
Executable file
@@ -0,0 +1,632 @@
|
||||
(* Adapted in May 2006 by Jean-Marc Notin from initial contents by
|
||||
Laurent Thery (Huffmann contribution, October 2003) *)
|
||||
|
||||
Require Import List Setoid Compare_dec Morphisms.
|
||||
Import ListNotations. (* For notations [] and [a;b;c] *)
|
||||
Set Implicit Arguments.
|
||||
|
||||
Section Permutation.
|
||||
|
||||
Variable A:Type.
|
||||
|
||||
Inductive Permutation : list A -> list A -> Prop :=
|
||||
| perm_nil: Permutation [] []
|
||||
| perm_skip x l l' : Permutation l l' -> Permutation (x::l) (x::l')
|
||||
| perm_swap x y l : Permutation (y::x::l) (x::y::l)
|
||||
| perm_trans l l' l'' :
|
||||
Permutation l l' -> Permutation l' l'' -> Permutation l l''.
|
||||
|
||||
Local Hint Constructors Permutation.
|
||||
|
||||
(** Some facts about [Permutation] *)
|
||||
|
||||
Theorem Permutation_nil : forall (l : list A), Permutation [] l -> l = [].
|
||||
Proof.
|
||||
intros l HF.
|
||||
remember (@nil A) as m in HF.
|
||||
induction HF; discriminate || auto.
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_nil_cons : forall (l : list A) (x : A),
|
||||
~ Permutation nil (x::l).
|
||||
Proof.
|
||||
intros l x HF.
|
||||
apply Permutation_nil in HF; discriminate.
|
||||
Qed.
|
||||
|
||||
(** Permutation over lists is a equivalence relation *)
|
||||
|
||||
Theorem Permutation_refl : forall l : list A, Permutation l l.
|
||||
Proof.
|
||||
induction l; constructor. exact IHl.
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_sym : forall l l' : list A,
|
||||
Permutation l l' -> Permutation l' l.
|
||||
Proof.
|
||||
intros l l' Hperm; induction Hperm; auto.
|
||||
apply perm_trans with (l':=l'); assumption.
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_trans : forall l l' l'' : list A,
|
||||
Permutation l l' -> Permutation l' l'' -> Permutation l l''.
|
||||
Proof.
|
||||
exact perm_trans.
|
||||
Qed.
|
||||
|
||||
End Permutation.
|
||||
|
||||
Hint Resolve Permutation_refl perm_nil perm_skip.
|
||||
|
||||
(* These hints do not reduce the size of the problem to solve and they
|
||||
must be used with care to avoid combinatoric explosions *)
|
||||
|
||||
Local Hint Resolve perm_swap perm_trans.
|
||||
Local Hint Resolve Permutation_sym Permutation_trans.
|
||||
|
||||
(* This provides reflexivity, symmetry and transitivity and rewriting
|
||||
on morphims to come *)
|
||||
|
||||
Instance Permutation_Equivalence A : Equivalence (@Permutation A) | 10 := {
|
||||
Equivalence_Reflexive := @Permutation_refl A ;
|
||||
Equivalence_Symmetric := @Permutation_sym A ;
|
||||
Equivalence_Transitive := @Permutation_trans A }.
|
||||
|
||||
Instance Permutation_cons A :
|
||||
Proper (Logic.eq ==> @Permutation A ==> @Permutation A) (@cons A) | 10.
|
||||
Proof.
|
||||
repeat intro; subst; auto using perm_skip.
|
||||
Qed.
|
||||
|
||||
Section Permutation_properties.
|
||||
|
||||
Variable A:Type.
|
||||
|
||||
Implicit Types a b : A.
|
||||
Implicit Types l m : list A.
|
||||
|
||||
(** Compatibility with others operations on lists *)
|
||||
|
||||
Theorem Permutation_in : forall (l l' : list A) (x : A),
|
||||
Permutation l l' -> In x l -> In x l'.
|
||||
Proof.
|
||||
intros l l' x Hperm; induction Hperm; simpl; tauto.
|
||||
Qed.
|
||||
|
||||
Global Instance Permutation_in' :
|
||||
Proper (Logic.eq ==> @Permutation A ==> iff) (@In A) | 10.
|
||||
Proof.
|
||||
repeat red; intros; subst; eauto using Permutation_in.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_app_tail : forall (l l' tl : list A),
|
||||
Permutation l l' -> Permutation (l++tl) (l'++tl).
|
||||
Proof.
|
||||
intros l l' tl Hperm; induction Hperm as [|x l l'|x y l|l l' l'']; simpl; auto.
|
||||
eapply Permutation_trans with (l':=l'++tl); trivial.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_app_head : forall (l tl tl' : list A),
|
||||
Permutation tl tl' -> Permutation (l++tl) (l++tl').
|
||||
Proof.
|
||||
intros l tl tl' Hperm; induction l;
|
||||
[trivial | repeat rewrite <- app_comm_cons; constructor; assumption].
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_app : forall (l m l' m' : list A),
|
||||
Permutation l l' -> Permutation m m' -> Permutation (l++m) (l'++m').
|
||||
Proof.
|
||||
intros l m l' m' Hpermll' Hpermmm';
|
||||
induction Hpermll' as [|x l l'|x y l|l l' l''];
|
||||
repeat rewrite <- app_comm_cons; auto.
|
||||
apply Permutation_trans with (l' := (x :: y :: l ++ m));
|
||||
[idtac | repeat rewrite app_comm_cons; apply Permutation_app_head]; trivial.
|
||||
apply Permutation_trans with (l' := (l' ++ m')); try assumption.
|
||||
apply Permutation_app_tail; assumption.
|
||||
Qed.
|
||||
|
||||
Global Instance Permutation_app' :
|
||||
Proper (@Permutation A ==> @Permutation A ==> @Permutation A) (@app A) | 10.
|
||||
Proof.
|
||||
repeat intro; now apply Permutation_app.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_add_inside : forall a (l l' tl tl' : list A),
|
||||
Permutation l l' -> Permutation tl tl' ->
|
||||
Permutation (l ++ a :: tl) (l' ++ a :: tl').
|
||||
Proof.
|
||||
intros; apply Permutation_app; auto.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_cons_append : forall (l : list A) x,
|
||||
Permutation (x :: l) (l ++ x :: nil).
|
||||
Proof. induction l; intros; auto. simpl. rewrite <- IHl; auto. Qed.
|
||||
Local Hint Resolve Permutation_cons_append.
|
||||
|
||||
Theorem Permutation_app_comm : forall (l l' : list A),
|
||||
Permutation (l ++ l') (l' ++ l).
|
||||
Proof.
|
||||
induction l as [|x l]; simpl; intro l'.
|
||||
rewrite app_nil_r; trivial. rewrite IHl.
|
||||
rewrite app_comm_cons, Permutation_cons_append.
|
||||
now rewrite <- app_assoc.
|
||||
Qed.
|
||||
Local Hint Resolve Permutation_app_comm.
|
||||
|
||||
Theorem Permutation_cons_app : forall (l l1 l2:list A) a,
|
||||
Permutation l (l1 ++ l2) -> Permutation (a :: l) (l1 ++ a :: l2).
|
||||
Proof.
|
||||
intros l l1 l2 a H. rewrite H.
|
||||
rewrite app_comm_cons, Permutation_cons_append.
|
||||
now rewrite <- app_assoc.
|
||||
Qed.
|
||||
Local Hint Resolve Permutation_cons_app.
|
||||
|
||||
Theorem Permutation_middle : forall (l1 l2:list A) a,
|
||||
Permutation (a :: l1 ++ l2) (l1 ++ a :: l2).
|
||||
Proof.
|
||||
auto.
|
||||
Qed.
|
||||
Local Hint Resolve Permutation_middle.
|
||||
|
||||
Theorem Permutation_rev : forall (l : list A), Permutation l (rev l).
|
||||
Proof.
|
||||
induction l as [| x l]; simpl; trivial. now rewrite IHl at 1.
|
||||
Qed.
|
||||
|
||||
Global Instance Permutation_rev' :
|
||||
Proper (@Permutation A ==> @Permutation A) (@rev A) | 10.
|
||||
Proof.
|
||||
repeat intro; now rewrite <- 2 Permutation_rev.
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_length : forall (l l' : list A),
|
||||
Permutation l l' -> length l = length l'.
|
||||
Proof.
|
||||
intros l l' Hperm; induction Hperm; simpl; auto. now transitivity (length l').
|
||||
Qed.
|
||||
|
||||
Global Instance Permutation_length' :
|
||||
Proper (@Permutation A ==> Logic.eq) (@length A) | 10.
|
||||
Proof.
|
||||
exact Permutation_length.
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_ind_bis :
|
||||
forall P : list A -> list A -> Prop,
|
||||
P [] [] ->
|
||||
(forall x l l', Permutation l l' -> P l l' -> P (x :: l) (x :: l')) ->
|
||||
(forall x y l l', Permutation l l' -> P l l' -> P (y :: x :: l) (x :: y :: l')) ->
|
||||
(forall l l' l'', Permutation l l' -> P l l' -> Permutation l' l'' -> P l' l'' -> P l l'') ->
|
||||
forall l l', Permutation l l' -> P l l'.
|
||||
Proof.
|
||||
intros P Hnil Hskip Hswap Htrans.
|
||||
induction 1; auto.
|
||||
apply Htrans with (x::y::l); auto.
|
||||
apply Hswap; auto.
|
||||
induction l; auto.
|
||||
apply Hskip; auto.
|
||||
apply Hskip; auto.
|
||||
induction l; auto.
|
||||
eauto.
|
||||
Qed.
|
||||
|
||||
Ltac break_list l x l' H :=
|
||||
destruct l as [|x l']; simpl in *;
|
||||
injection H; intros; subst; clear H.
|
||||
|
||||
Theorem Permutation_nil_app_cons : forall (l l' : list A) (x : A),
|
||||
~ Permutation nil (l++x::l').
|
||||
Proof.
|
||||
intros l l' x HF.
|
||||
apply Permutation_nil in HF. destruct l; discriminate.
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_app_inv : forall (l1 l2 l3 l4:list A) a,
|
||||
Permutation (l1++a::l2) (l3++a::l4) -> Permutation (l1++l2) (l3 ++ l4).
|
||||
Proof.
|
||||
intros l1 l2 l3 l4 a; revert l1 l2 l3 l4.
|
||||
set (P l l' :=
|
||||
forall l1 l2 l3 l4, l=l1++a::l2 -> l'=l3++a::l4 ->
|
||||
Permutation (l1++l2) (l3++l4)).
|
||||
cut (forall l l', Permutation l l' -> P l l').
|
||||
intros H; intros; eapply H; eauto.
|
||||
apply (Permutation_ind_bis P); unfold P; clear P.
|
||||
- (* nil *)
|
||||
intros; now destruct l1.
|
||||
- (* skip *)
|
||||
intros x l l' H IH; intros.
|
||||
break_list l1 b l1' H0; break_list l3 c l3' H1.
|
||||
auto.
|
||||
now rewrite H.
|
||||
now rewrite <- H.
|
||||
now rewrite (IH _ _ _ _ eq_refl eq_refl).
|
||||
- (* swap *)
|
||||
intros x y l l' Hp IH; intros.
|
||||
break_list l1 b l1' H; break_list l3 c l3' H0.
|
||||
auto.
|
||||
break_list l3' b l3'' H.
|
||||
auto.
|
||||
constructor. now rewrite Permutation_middle.
|
||||
break_list l1' c l1'' H1.
|
||||
auto.
|
||||
constructor. now rewrite Permutation_middle.
|
||||
break_list l3' d l3'' H; break_list l1' e l1'' H1.
|
||||
auto.
|
||||
rewrite perm_swap. constructor. now rewrite Permutation_middle.
|
||||
rewrite perm_swap. constructor. now rewrite Permutation_middle.
|
||||
now rewrite perm_swap, (IH _ _ _ _ eq_refl eq_refl).
|
||||
- (*trans*)
|
||||
intros.
|
||||
destruct (In_split a l') as (l'1,(l'2,H6)).
|
||||
rewrite <- H.
|
||||
subst l.
|
||||
apply in_or_app; right; red; auto.
|
||||
apply perm_trans with (l'1++l'2).
|
||||
apply (H0 _ _ _ _ H3 H6).
|
||||
apply (H2 _ _ _ _ H6 H4).
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_cons_inv l l' a :
|
||||
Permutation (a::l) (a::l') -> Permutation l l'.
|
||||
Proof.
|
||||
intro H; exact (Permutation_app_inv [] l [] l' a H).
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_cons_app_inv l l1 l2 a :
|
||||
Permutation (a :: l) (l1 ++ a :: l2) -> Permutation l (l1 ++ l2).
|
||||
Proof.
|
||||
intro H; exact (Permutation_app_inv [] l l1 l2 a H).
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_app_inv_l : forall l l1 l2,
|
||||
Permutation (l ++ l1) (l ++ l2) -> Permutation l1 l2.
|
||||
Proof.
|
||||
induction l; simpl; auto.
|
||||
intros.
|
||||
apply IHl.
|
||||
apply Permutation_cons_inv with a; auto.
|
||||
Qed.
|
||||
|
||||
Theorem Permutation_app_inv_r : forall l l1 l2,
|
||||
Permutation (l1 ++ l) (l2 ++ l) -> Permutation l1 l2.
|
||||
Proof.
|
||||
induction l.
|
||||
intros l1 l2; do 2 rewrite app_nil_r; auto.
|
||||
intros.
|
||||
apply IHl.
|
||||
apply Permutation_app_inv with a; auto.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_length_1_inv: forall a l, Permutation [a] l -> l = [a].
|
||||
Proof.
|
||||
intros a l H; remember [a] as m in H.
|
||||
induction H; try (injection Heqm as -> ->; clear Heqm);
|
||||
discriminate || auto.
|
||||
apply Permutation_nil in H as ->; trivial.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_length_1: forall a b, Permutation [a] [b] -> a = b.
|
||||
Proof.
|
||||
intros a b H.
|
||||
apply Permutation_length_1_inv in H; injection H as ->; trivial.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_length_2_inv :
|
||||
forall a1 a2 l, Permutation [a1;a2] l -> l = [a1;a2] \/ l = [a2;a1].
|
||||
Proof.
|
||||
intros a1 a2 l H; remember [a1;a2] as m in H.
|
||||
revert a1 a2 Heqm.
|
||||
induction H; intros; try (injection Heqm; intros; subst; clear Heqm);
|
||||
discriminate || (try tauto).
|
||||
apply Permutation_length_1_inv in H as ->; left; auto.
|
||||
apply IHPermutation1 in Heqm as [H1|H1]; apply IHPermutation2 in H1 as ();
|
||||
auto.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_length_2 :
|
||||
forall a1 a2 b1 b2, Permutation [a1;a2] [b1;b2] ->
|
||||
a1 = b1 /\ a2 = b2 \/ a1 = b2 /\ a2 = b1.
|
||||
Proof.
|
||||
intros a1 b1 a2 b2 H.
|
||||
apply Permutation_length_2_inv in H as [H|H]; injection H as -> ->; auto.
|
||||
Qed.
|
||||
|
||||
Let in_middle l l1 l2 (a:A) : l = l1 ++ a :: l2 ->
|
||||
forall x, In x l <-> a = x \/ In x (l1++l2).
|
||||
Proof.
|
||||
intros; subst; rewrite !in_app_iff; simpl. tauto.
|
||||
Qed.
|
||||
|
||||
Lemma NoDup_cardinal_incl (l l' : list A) : NoDup l -> NoDup l' ->
|
||||
length l = length l' -> incl l l' -> incl l' l.
|
||||
Proof.
|
||||
intros N. revert l'. induction N as [|a l Hal Hl IH].
|
||||
- destruct l'; now auto.
|
||||
- intros l' Hl' E H x Hx.
|
||||
assert (Ha : In a l') by (apply H; simpl; auto).
|
||||
destruct (in_split _ _ Ha) as (l1 & l2 & H12). clear Ha.
|
||||
rewrite in_middle in Hx; eauto.
|
||||
destruct Hx as [Hx|Hx]; [left|right]; auto.
|
||||
apply (IH (l1++l2)); auto.
|
||||
* apply NoDup_remove_1 with a; rewrite <- H12; auto.
|
||||
* apply eq_add_S.
|
||||
simpl in E; rewrite E, H12, !app_length; simpl; auto with arith.
|
||||
* intros y Hy. assert (Hy' : In y l') by (apply H; simpl; auto).
|
||||
rewrite in_middle in Hy'; eauto.
|
||||
destruct Hy'; auto. subst y; intuition.
|
||||
Qed.
|
||||
|
||||
Lemma NoDup_Permutation l l' : NoDup l -> NoDup l' ->
|
||||
(forall x:A, In x l <-> In x l') -> Permutation l l'.
|
||||
Proof.
|
||||
intros N. revert l'. induction N as [|a l Hal Hl IH].
|
||||
- destruct l'; simpl; auto.
|
||||
intros Hl' H. exfalso. rewrite (H a); auto.
|
||||
- intros l' Hl' H.
|
||||
assert (Ha : In a l') by (apply H; simpl; auto).
|
||||
destruct (In_split _ _ Ha) as (l1 & l2 & H12).
|
||||
rewrite H12.
|
||||
apply Permutation_cons_app.
|
||||
apply IH; auto.
|
||||
* apply NoDup_remove_1 with a; rewrite <- H12; auto.
|
||||
* intro x. split; intros Hx.
|
||||
+ assert (Hx' : In x l') by (apply H; simpl; auto).
|
||||
rewrite in_middle in Hx'; eauto.
|
||||
destruct Hx'; auto. subst; intuition.
|
||||
+ assert (Hx' : In x l') by (rewrite (in_middle l1 l2 a); eauto).
|
||||
rewrite <- H in Hx'. destruct Hx'; auto.
|
||||
subst. destruct (NoDup_remove_2 _ _ _ Hl' Hx).
|
||||
Qed.
|
||||
|
||||
Lemma NoDup_Permutation_bis l l' : NoDup l -> NoDup l' ->
|
||||
length l = length l' -> incl l l' -> Permutation l l'.
|
||||
Proof.
|
||||
intros. apply NoDup_Permutation; auto.
|
||||
split; auto. apply NoDup_cardinal_incl; auto.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_NoDup l l' : Permutation l l' -> NoDup l -> NoDup l'.
|
||||
Proof.
|
||||
induction 1; auto.
|
||||
* inversion_clear 1; constructor; eauto using Permutation_in.
|
||||
* inversion_clear 1 as [|? ? H1 H2]. inversion_clear H2; simpl in *.
|
||||
constructor. simpl; intuition. constructor; intuition.
|
||||
Qed.
|
||||
|
||||
Global Instance Permutation_NoDup' :
|
||||
Proper (@Permutation A ==> iff) (@NoDup A) | 10.
|
||||
Proof.
|
||||
repeat red; eauto using Permutation_NoDup.
|
||||
Qed.
|
||||
|
||||
End Permutation_properties.
|
||||
|
||||
Section Permutation_map.
|
||||
|
||||
Variable A B : Type.
|
||||
Variable f : A -> B.
|
||||
|
||||
Lemma Permutation_map l l' :
|
||||
Permutation l l' -> Permutation (map f l) (map f l').
|
||||
Proof.
|
||||
induction 1; simpl; eauto.
|
||||
Qed.
|
||||
|
||||
Global Instance Permutation_map' :
|
||||
Proper (@Permutation A ==> @Permutation B) (map f) | 10.
|
||||
Proof.
|
||||
exact Permutation_map.
|
||||
Qed.
|
||||
|
||||
End Permutation_map.
|
||||
|
||||
Section Injection.
|
||||
|
||||
Definition injective {A B} (f : A->B) :=
|
||||
forall x y, f x = f y -> x = y.
|
||||
|
||||
Lemma injective_map_NoDup {A B} (f:A->B) (l:list A) :
|
||||
injective f -> NoDup l -> NoDup (map f l).
|
||||
Proof.
|
||||
intros Hf. induction 1 as [|x l Hx Hl IH]; simpl; constructor; trivial.
|
||||
rewrite in_map_iff. intros (y & Hy & Hy'). apply Hf in Hy. now subst.
|
||||
Qed.
|
||||
|
||||
Lemma injective_bounded_surjective n f :
|
||||
injective f ->
|
||||
(forall x, x < n -> f x < n) ->
|
||||
(forall y, y < n -> exists x, x < n /\ f x = y).
|
||||
Proof.
|
||||
intros Hf H.
|
||||
set (l := seq 0 n).
|
||||
assert (P : incl (map f l) l).
|
||||
{ intros x. rewrite in_map_iff. intros (y & <- & Hy').
|
||||
unfold l in *. rewrite in_seq in *. simpl in *.
|
||||
destruct Hy' as (_,Hy'). auto with arith. }
|
||||
assert (P' : incl l (map f l)).
|
||||
{ unfold l.
|
||||
apply NoDup_cardinal_incl; auto using injective_map_NoDup, seq_NoDup.
|
||||
now rewrite map_length. }
|
||||
intros x Hx.
|
||||
assert (Hx' : In x l) by (unfold l; rewrite in_seq; auto with arith).
|
||||
apply P' in Hx'.
|
||||
rewrite in_map_iff in Hx'. destruct Hx' as (y & Hy & Hy').
|
||||
exists y; split; auto. unfold l in *; rewrite in_seq in Hy'.
|
||||
destruct Hy'; auto with arith.
|
||||
Qed.
|
||||
|
||||
Lemma nat_bijection_Permutation n f :
|
||||
injective f -> (forall x, x < n -> f x < n) ->
|
||||
let l := seq 0 n in Permutation (map f l) l.
|
||||
Proof.
|
||||
intros Hf BD.
|
||||
apply NoDup_Permutation_bis; auto using injective_map_NoDup, seq_NoDup.
|
||||
* now rewrite map_length.
|
||||
* intros x. rewrite in_map_iff. intros (y & <- & Hy').
|
||||
rewrite in_seq in *. simpl in *.
|
||||
destruct Hy' as (_,Hy'). auto with arith.
|
||||
Qed.
|
||||
|
||||
End Injection.
|
||||
|
||||
Section Permutation_alt.
|
||||
Variable A:Type.
|
||||
Implicit Type a : A.
|
||||
Implicit Type l : list A.
|
||||
|
||||
(** Alternative characterization of permutation
|
||||
via [nth_error] and [nth] *)
|
||||
|
||||
Let adapt f n :=
|
||||
let m := f (S n) in if le_lt_dec m (f 0) then m else pred m.
|
||||
|
||||
Let adapt_injective f : injective f -> injective (adapt f).
|
||||
Proof.
|
||||
unfold adapt. intros Hf x y EQ.
|
||||
destruct le_lt_dec as [LE|LT]; destruct le_lt_dec as [LE'|LT'].
|
||||
- now apply eq_add_S, Hf.
|
||||
- apply Lt.le_lt_or_eq in LE.
|
||||
destruct LE as [LT|EQ']; [|now apply Hf in EQ'].
|
||||
unfold lt in LT. rewrite EQ in LT.
|
||||
rewrite <- (Lt.S_pred _ _ LT') in LT.
|
||||
elim (Lt.lt_not_le _ _ LT' LT).
|
||||
- apply Lt.le_lt_or_eq in LE'.
|
||||
destruct LE' as [LT'|EQ']; [|now apply Hf in EQ'].
|
||||
unfold lt in LT'. rewrite <- EQ in LT'.
|
||||
rewrite <- (Lt.S_pred _ _ LT) in LT'.
|
||||
elim (Lt.lt_not_le _ _ LT LT').
|
||||
- apply eq_add_S, Hf.
|
||||
now rewrite (Lt.S_pred _ _ LT), (Lt.S_pred _ _ LT'), EQ.
|
||||
Qed.
|
||||
|
||||
Let adapt_ok a l1 l2 f : injective f -> length l1 = f 0 ->
|
||||
forall n, nth_error (l1++a::l2) (f (S n)) = nth_error (l1++l2) (adapt f n).
|
||||
Proof.
|
||||
unfold adapt. intros Hf E n.
|
||||
destruct le_lt_dec as [LE|LT].
|
||||
- apply Lt.le_lt_or_eq in LE.
|
||||
destruct LE as [LT|EQ]; [|now apply Hf in EQ].
|
||||
rewrite <- E in LT.
|
||||
rewrite 2 nth_error_app1; auto.
|
||||
- rewrite (Lt.S_pred _ _ LT) at 1.
|
||||
rewrite <- E, (Lt.S_pred _ _ LT) in LT.
|
||||
rewrite 2 nth_error_app2; auto with arith.
|
||||
rewrite <- Minus.minus_Sn_m; auto with arith.
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_nth_error l l' :
|
||||
Permutation l l' <->
|
||||
(length l = length l' /\
|
||||
exists f:nat->nat,
|
||||
injective f /\ forall n, nth_error l' n = nth_error l (f n)).
|
||||
Proof.
|
||||
split.
|
||||
{ intros P.
|
||||
split; [now apply Permutation_length|].
|
||||
induction P.
|
||||
- exists (fun n => n).
|
||||
split; try red; auto.
|
||||
- destruct IHP as (f & Hf & Hf').
|
||||
exists (fun n => match n with O => O | S n => S (f n) end).
|
||||
split; try red.
|
||||
* intros [|y] [|z]; simpl; now auto.
|
||||
* intros [|n]; simpl; auto.
|
||||
- exists (fun n => match n with 0 => 1 | 1 => 0 | n => n end).
|
||||
split; try red.
|
||||
* intros [|[|z]] [|[|t]]; simpl; now auto.
|
||||
* intros [|[|n]]; simpl; auto.
|
||||
- destruct IHP1 as (f & Hf & Hf').
|
||||
destruct IHP2 as (g & Hg & Hg').
|
||||
exists (fun n => f (g n)).
|
||||
split; try red.
|
||||
* auto.
|
||||
* intros n. rewrite <- Hf'; auto. }
|
||||
{ revert l. induction l'.
|
||||
- intros [|l] (E & _); now auto.
|
||||
- intros l (E & f & Hf & Hf').
|
||||
simpl in E.
|
||||
assert (Ha : nth_error l (f 0) = Some a)
|
||||
by (symmetry; apply (Hf' 0)).
|
||||
destruct (nth_error_split l (f 0) Ha) as (l1 & l2 & L12 & L1).
|
||||
rewrite L12. rewrite <- Permutation_middle. constructor.
|
||||
apply IHl'; split; [|exists (adapt f); split].
|
||||
* revert E. rewrite L12, !app_length. simpl.
|
||||
rewrite <- plus_n_Sm. now injection 1.
|
||||
* now apply adapt_injective.
|
||||
* intro n. rewrite <- (adapt_ok a), <- L12; auto.
|
||||
apply (Hf' (S n)). }
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_nth_error_bis l l' :
|
||||
Permutation l l' <->
|
||||
exists f:nat->nat,
|
||||
injective f /\
|
||||
(forall n, n < length l -> f n < length l) /\
|
||||
(forall n, nth_error l' n = nth_error l (f n)).
|
||||
Proof.
|
||||
rewrite Permutation_nth_error; split.
|
||||
- intros (E & f & Hf & Hf').
|
||||
exists f. do 2 (split; trivial).
|
||||
intros n Hn.
|
||||
destruct (Lt.le_or_lt (length l) (f n)) as [LE|LT]; trivial.
|
||||
rewrite <- nth_error_None, <- Hf', nth_error_None, <- E in LE.
|
||||
elim (Lt.lt_not_le _ _ Hn LE).
|
||||
- intros (f & Hf & Hf2 & Hf3); split; [|exists f; auto].
|
||||
assert (H : length l' <= length l') by auto with arith.
|
||||
rewrite <- nth_error_None, Hf3, nth_error_None in H.
|
||||
destruct (Lt.le_or_lt (length l) (length l')) as [LE|LT];
|
||||
[|apply Hf2 in LT; elim (Lt.lt_not_le _ _ LT H)].
|
||||
apply Lt.le_lt_or_eq in LE. destruct LE as [LT|EQ]; trivial.
|
||||
rewrite <- nth_error_Some, Hf3, nth_error_Some in LT.
|
||||
destruct (injective_bounded_surjective Hf Hf2 LT) as (y & Hy & Hy').
|
||||
apply Hf in Hy'. subst y. elim (Lt.lt_irrefl _ Hy).
|
||||
Qed.
|
||||
|
||||
Lemma Permutation_nth l l' d :
|
||||
Permutation l l' <->
|
||||
(let n := length l in
|
||||
length l' = n /\
|
||||
exists f:nat->nat,
|
||||
(forall x, x < n -> f x < n) /\
|
||||
(forall x y, x < n -> y < n -> f x = f y -> x = y) /\
|
||||
(forall x, x < n -> nth x l' d = nth (f x) l d)).
|
||||
Proof.
|
||||
split.
|
||||
- intros H.
|
||||
assert (E := Permutation_length H).
|
||||
split; auto.
|
||||
apply Permutation_nth_error_bis in H.
|
||||
destruct H as (f & Hf & Hf2 & Hf3).
|
||||
exists f. split; [|split]; auto.
|
||||
intros n Hn. rewrite <- 2 nth_default_eq. unfold nth_default.
|
||||
now rewrite Hf3.
|
||||
- intros (E & f & Hf1 & Hf2 & Hf3).
|
||||
rewrite Permutation_nth_error.
|
||||
split; auto.
|
||||
exists (fun n => if le_lt_dec (length l) n then n else f n).
|
||||
split.
|
||||
* intros x y.
|
||||
destruct le_lt_dec as [LE|LT];
|
||||
destruct le_lt_dec as [LE'|LT']; auto.
|
||||
+ apply Hf1 in LT'. intros ->.
|
||||
elim (Lt.lt_irrefl (f y)). eapply Lt.lt_le_trans; eauto.
|
||||
+ apply Hf1 in LT. intros <-.
|
||||
elim (Lt.lt_irrefl (f x)). eapply Lt.lt_le_trans; eauto.
|
||||
* intros n.
|
||||
destruct le_lt_dec as [LE|LT].
|
||||
+ assert (LE' : length l' <= n) by (now rewrite E).
|
||||
rewrite <- nth_error_None in LE, LE'. congruence.
|
||||
+ assert (LT' : n < length l') by (now rewrite E).
|
||||
specialize (Hf3 n LT). rewrite <- 2 nth_default_eq in Hf3.
|
||||
unfold nth_default in Hf3.
|
||||
apply Hf1 in LT.
|
||||
rewrite <- nth_error_Some in LT, LT'.
|
||||
do 2 destruct nth_error; congruence.
|
||||
Qed.
|
||||
|
||||
End Permutation_alt.
|
||||
|
||||
(* begin hide *)
|
||||
Notation Permutation_app_swap := Permutation_app_comm (only parsing).
|
||||
(* end hide *)
|
||||
875
samples/Coq/Poly.v
Executable file
875
samples/Coq/Poly.v
Executable file
@@ -0,0 +1,875 @@
|
||||
Require Export Lists.
|
||||
Require Export Basics.
|
||||
|
||||
Import Playground1.
|
||||
|
||||
Inductive list (X : Type) : Type :=
|
||||
| nil : list X
|
||||
| cons : X -> list X -> list X.
|
||||
|
||||
Fixpoint length (X:Type) (l:list X) : nat :=
|
||||
match l with
|
||||
| nil => O
|
||||
| cons h t => S (length X t)
|
||||
end.
|
||||
|
||||
Fixpoint app (X : Type) (l1 l2 : list X)
|
||||
: (list X) :=
|
||||
match l1 with
|
||||
| nil => l2
|
||||
| cons h t => cons X h (app X t l2)
|
||||
end.
|
||||
|
||||
Fixpoint snoc (X:Type) (l:list X) (v:X) : (list X) :=
|
||||
match l with
|
||||
| nil => cons X v (nil X)
|
||||
| cons h t => cons X h (snoc X t v)
|
||||
end.
|
||||
|
||||
Fixpoint rev (X:Type) (l:list X) : list X :=
|
||||
match l with
|
||||
| nil => nil X
|
||||
| cons h t => snoc X (rev X t) h
|
||||
end.
|
||||
|
||||
|
||||
Implicit Arguments nil [[X]].
|
||||
Implicit Arguments cons [[X]].
|
||||
Implicit Arguments length [[X]].
|
||||
Implicit Arguments app [[X]].
|
||||
Implicit Arguments rev [[X]].
|
||||
Implicit Arguments snoc [[X]].
|
||||
|
||||
Definition list123 := cons 1 (cons 2 (cons 3 (nil))).
|
||||
|
||||
Notation "x :: y" := (cons x y) (at level 60, right associativity).
|
||||
Notation "[]" := nil.
|
||||
Notation "[ x , .. , y ]" := (cons x .. (cons y []) ..).
|
||||
Notation "x ++ y" := (app x y) (at level 60, right associativity).
|
||||
|
||||
Fixpoint repeat (X : Type) (n : X) (count : nat) : list X :=
|
||||
match count with
|
||||
| O => nil
|
||||
| S count' => n :: (repeat _ n count')
|
||||
end.
|
||||
|
||||
Example test_repeat1:
|
||||
repeat bool true (S (S O)) = [true, true].
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Theorem nil_app : forall X:Type, forall l:list X,
|
||||
app [] l = l.
|
||||
Proof.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem rev_snoc : forall X : Type,
|
||||
forall v : X,
|
||||
forall s : list X,
|
||||
rev (snoc s v) = v :: (rev s).
|
||||
Proof.
|
||||
intros X v s.
|
||||
induction s.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> IHs.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem snoc_with_append : forall X : Type,
|
||||
forall l1 l2 : list X,
|
||||
forall v : X,
|
||||
snoc (l1 ++ l2) v = l1 ++ (snoc l2 v).
|
||||
Proof.
|
||||
intros X l1 l2 v.
|
||||
induction l1.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> IHl1.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Inductive prod (X Y : Type) : Type :=
|
||||
pair : X -> Y -> prod X Y.
|
||||
|
||||
Implicit Arguments pair [X Y].
|
||||
|
||||
Notation "( x , y )" := (pair x y).
|
||||
Notation "X * Y" := (prod X Y) : type_scope.
|
||||
|
||||
Definition fst (X Y : Type) (p : X * Y) : X :=
|
||||
match p with (x,y) => x end.
|
||||
Definition snd (X Y : Type) (p : X * Y) : Y :=
|
||||
match p with (x,y) => y end.
|
||||
|
||||
Fixpoint combine (X Y : Type) (lx : list X) (ly : list Y)
|
||||
: list (X * Y) :=
|
||||
match lx, ly with
|
||||
| [], _ => []
|
||||
| _,[] => []
|
||||
| x::tx, y::ty => (x,y) :: (combine _ _ tx ty)
|
||||
end.
|
||||
|
||||
Implicit Arguments combine [X Y].
|
||||
|
||||
Fixpoint split {X Y: Type} (s : list (X * Y)) : (list X)*(list Y) :=
|
||||
match s with
|
||||
| nil => (nil, nil)
|
||||
| (x,y) :: tp => match split tp with
|
||||
| (lx, ly) => (x :: lx, y :: ly)
|
||||
end
|
||||
end.
|
||||
|
||||
Inductive option (X : Type) : Type :=
|
||||
| Some : X -> option X
|
||||
| None : option X.
|
||||
|
||||
Implicit Arguments Some [X].
|
||||
Implicit Arguments None [X].
|
||||
|
||||
Fixpoint index (X : Type) (n : nat)
|
||||
(l : list X) : option X :=
|
||||
match n with
|
||||
| O => match l with
|
||||
| nil => None
|
||||
| x :: xs => Some x
|
||||
end
|
||||
| S n' => match l with
|
||||
| nil => None
|
||||
| x :: xs => index X n' xs
|
||||
end
|
||||
end.
|
||||
|
||||
Definition hd_opt (X : Type) (l : list X) : option X :=
|
||||
match l with
|
||||
| nil => None
|
||||
| x :: xs => Some x
|
||||
end.
|
||||
|
||||
Implicit Arguments hd_opt [X].
|
||||
|
||||
Example test_hd_opt1 : hd_opt [S O, S (S O)] = Some (S O).
|
||||
Proof. reflexivity. Qed.
|
||||
Example test_hd_opt2 : hd_opt [[S O], [S (S O)]] = Some [S O].
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Definition plus3 := plus (S (S (S O))).
|
||||
|
||||
Definition prod_curry {X Y Z : Type}
|
||||
(f : X * Y -> Z) (x : X) (y : Y) : Z := f (x,y).
|
||||
|
||||
Definition prod_uncurry {X Y Z : Type}
|
||||
(f : X -> Y -> Z) (p : X * Y) : Z :=
|
||||
f (fst X Y p) (snd X Y p).
|
||||
|
||||
Theorem uncurry_uncurry : forall (X Y Z : Type) (f : X -> Y -> Z) x y,
|
||||
prod_curry (prod_uncurry f) x y = f x y.
|
||||
Proof.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem curry_uncurry : forall (X Y Z : Type) (f : (X * Y) -> Z)
|
||||
(p : X * Y),
|
||||
prod_uncurry (prod_curry f) p = f p.
|
||||
Proof.
|
||||
destruct p.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Fixpoint filter (X : Type) (test : X -> bool) (l:list X)
|
||||
: (list X) :=
|
||||
match l with
|
||||
| [] => []
|
||||
| h :: t => if test h then h :: (filter _ test t)
|
||||
else filter _ test t
|
||||
end.
|
||||
|
||||
Definition countoddmembers' (l:list nat) : nat :=
|
||||
length (filter _ oddb l).
|
||||
|
||||
Definition partition (X : Type) (test : X -> bool) (l : list X)
|
||||
: list X * list X :=
|
||||
(filter _ test l, filter _ (fun el => negb (test el)) l).
|
||||
|
||||
Example test_partition1: partition _ oddb [S O, S (S O), S (S (S O)), S (S (S (S O))), S (S (S (S (S O))))] = ([S O, S (S (S O)), S (S (S (S (S O))))], [S (S O), S (S (S (S O)))]).
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Fixpoint map {X Y : Type} (f : X -> Y) (l : list X) : (list Y ) :=
|
||||
match l with
|
||||
| [] => []
|
||||
| h :: t => (f h) :: (map f t)
|
||||
end.
|
||||
|
||||
Example test_map1: map (plus (S (S (S O)))) [S (S O), O, S (S O)] = [S (S (S (S (S O)))), S (S (S O)), S (S (S (S (S O))))].
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Theorem map_rev_1 : forall (X Y: Type) (f: X -> Y) (l : list X) (x : X),
|
||||
map f (snoc l x) = snoc (map f l) (f x).
|
||||
Proof.
|
||||
intros X Y f l x.
|
||||
induction l.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite -> IHl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem map_rev : forall (X Y : Type) (f : X -> Y) (l : list X),
|
||||
map f (rev l) = rev (map f l).
|
||||
Proof.
|
||||
intros X Y f l.
|
||||
induction l.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite <- IHl.
|
||||
rewrite -> map_rev_1.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Fixpoint flat_map {X Y : Type} (f : X -> list Y) (l : list X)
|
||||
: (list Y) :=
|
||||
match l with
|
||||
| [] => []
|
||||
| x :: xs => (f x) ++ (flat_map f xs)
|
||||
end.
|
||||
|
||||
Definition map_option {X Y : Type} (f : X -> Y) (xo : option X)
|
||||
: option Y :=
|
||||
match xo with
|
||||
| None => None
|
||||
| Some x => Some (f x)
|
||||
end.
|
||||
|
||||
Fixpoint fold {X Y: Type} (f: X -> Y -> Y) (l:list X) (b:Y) : Y :=
|
||||
match l with
|
||||
| nil => b
|
||||
| h :: t => f h (fold f t b)
|
||||
end.
|
||||
|
||||
Example fold_example : fold andb [true, true, false, true] true = false.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Definition constfun {X : Type} (x: X) : nat -> X :=
|
||||
fun (k:nat) => x.
|
||||
|
||||
Definition ftrue := constfun true.
|
||||
Example constfun_example : ftrue O = true.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Definition override {X : Type} (f: nat -> X) (k:nat) (x:X) : nat->X :=
|
||||
fun (k':nat) => if beq_nat k k' then x else f k'.
|
||||
|
||||
Definition fmostlytrue := override (override ftrue (S O) false) (S (S (S O))) false.
|
||||
|
||||
Example override_example1 : fmostlytrue O = true.
|
||||
Proof. reflexivity. Qed.
|
||||
Example override_example2 : fmostlytrue (S O) = false.
|
||||
Proof. reflexivity. Qed.
|
||||
Example override_example3 : fmostlytrue (S (S O)) = true.
|
||||
Proof. reflexivity. Qed.
|
||||
Example override_example4 : fmostlytrue (S (S (S O))) = false.
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Theorem override_example : forall (b: bool),
|
||||
(override (constfun b) (S (S (S O))) true) (S (S O)) = b.
|
||||
Proof.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem unfold_example_bad : forall m n,
|
||||
(S (S (S O))) + n = m ->
|
||||
plus3 n = m.
|
||||
Proof.
|
||||
intros m n H.
|
||||
unfold plus3.
|
||||
rewrite -> H.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem override_eq : forall {X : Type} x k (f : nat -> X),
|
||||
(override f k x) k = x.
|
||||
Proof.
|
||||
intros X x k f.
|
||||
unfold override.
|
||||
rewrite <- beq_nat_refl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem override_neq : forall {X : Type} x1 x2 k1 k2 (f : nat->X),
|
||||
f k1 = x1 ->
|
||||
beq_nat k2 k1 = false ->
|
||||
(override f k2 x2) k1 = x1.
|
||||
Proof.
|
||||
intros X x1 x2 k1 k2 f eq1 eq2.
|
||||
unfold override.
|
||||
rewrite -> eq2.
|
||||
rewrite -> eq1.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem eq_add_S : forall (n m : nat),
|
||||
S n = S m ->
|
||||
n = m.
|
||||
Proof.
|
||||
intros n m eq.
|
||||
inversion eq.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem silly4 : forall (n m : nat),
|
||||
[n] = [m] ->
|
||||
n = m.
|
||||
Proof.
|
||||
intros n o eq.
|
||||
inversion eq.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem silly5 : forall (n m o : nat),
|
||||
[n,m] = [o,o] ->
|
||||
[n] = [m].
|
||||
Proof.
|
||||
intros n m o eq.
|
||||
inversion eq.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem sillyex1 : forall (X : Type) (x y z : X) (l j : list X),
|
||||
x :: y :: l = z :: j ->
|
||||
y :: l = x :: j ->
|
||||
x = y.
|
||||
Proof.
|
||||
intros X x y z l j.
|
||||
intros eq1 eq2.
|
||||
inversion eq1.
|
||||
inversion eq2.
|
||||
symmetry.
|
||||
rewrite -> H0.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem silly6 : forall (n : nat),
|
||||
S n = O ->
|
||||
(S (S O)) + (S (S O)) = (S (S (S (S (S O))))).
|
||||
Proof.
|
||||
intros n contra.
|
||||
inversion contra.
|
||||
Qed.
|
||||
|
||||
Theorem silly7 : forall (n m : nat),
|
||||
false = true ->
|
||||
[n] = [m].
|
||||
Proof.
|
||||
intros n m contra.
|
||||
inversion contra.
|
||||
Qed.
|
||||
|
||||
Theorem sillyex2 : forall (X : Type) (x y z : X) (l j : list X),
|
||||
x :: y :: l = [] ->
|
||||
y :: l = z :: j ->
|
||||
x = z.
|
||||
Proof.
|
||||
intros X x y z l j contra.
|
||||
inversion contra.
|
||||
Qed.
|
||||
|
||||
Theorem beq_nat_eq : forall n m,
|
||||
true = beq_nat n m -> n = m.
|
||||
Proof.
|
||||
intros n. induction n as [| n'].
|
||||
Case "n = O".
|
||||
intros m. destruct m as [| m'].
|
||||
SCase "m = 0". reflexivity.
|
||||
SCase "m = S m'". simpl. intros contra. inversion contra.
|
||||
Case "n = S n'".
|
||||
intros m. destruct m as [| m'].
|
||||
SCase "m = 0". simpl. intros contra. inversion contra.
|
||||
SCase "m = S m'". simpl. intros H.
|
||||
assert(n' = m') as Hl.
|
||||
SSCase "Proof of assertion". apply IHn'. apply H.
|
||||
rewrite -> Hl. reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem beq_nat_eq' : forall m n,
|
||||
beq_nat n m = true -> n = m.
|
||||
Proof.
|
||||
intros m. induction m as [| m'].
|
||||
Case "m = O".
|
||||
destruct n.
|
||||
SCase "n = O".
|
||||
reflexivity.
|
||||
SCase "n = S n'".
|
||||
simpl. intros contra. inversion contra.
|
||||
Case "m = S m'".
|
||||
simpl.
|
||||
destruct n.
|
||||
SCase "n = O".
|
||||
simpl. intros contra. inversion contra.
|
||||
SCase "n = S n'".
|
||||
simpl. intros H.
|
||||
assert (n = m') as Hl.
|
||||
apply IHm'.
|
||||
apply H.
|
||||
rewrite -> Hl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem length_snoc' : forall (X : Type) (v : X)
|
||||
(l : list X) (n : nat),
|
||||
length l = n ->
|
||||
length (snoc l v) = S n.
|
||||
Proof.
|
||||
intros X v l. induction l as [| v' l'].
|
||||
Case "l = []". intros n eq. rewrite <- eq. reflexivity.
|
||||
Case "l = v' :: l'". intros n eq. simpl. destruct n as [| n'].
|
||||
SCase "n = 0". inversion eq.
|
||||
SCase "n = S n'".
|
||||
assert (length (snoc l' v) = S n').
|
||||
SSCase "Proof of assertion". apply IHl'.
|
||||
inversion eq. reflexivity.
|
||||
rewrite -> H. reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem beq_nat_O_l : forall n,
|
||||
true = beq_nat O n -> O = n.
|
||||
Proof.
|
||||
intros n. destruct n.
|
||||
reflexivity.
|
||||
simpl.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
Qed.
|
||||
|
||||
Theorem beq_nat_O_r : forall n,
|
||||
true = beq_nat n O -> O = n.
|
||||
Proof.
|
||||
intros n.
|
||||
induction n.
|
||||
Case "n = O".
|
||||
reflexivity.
|
||||
Case "n = S n'".
|
||||
simpl.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
Qed.
|
||||
|
||||
Theorem double_injective : forall n m,
|
||||
double n = double m ->
|
||||
n = m.
|
||||
Proof.
|
||||
intros n. induction n as [| n'].
|
||||
Case "n = O".
|
||||
simpl. intros m eq.
|
||||
destruct m as [|m'].
|
||||
SCase "m = O". reflexivity.
|
||||
SCase "m = S m'". inversion eq.
|
||||
Case "n = S n'". intros m eq. destruct m as [| m'].
|
||||
SCase "m = O". inversion eq.
|
||||
SCase "m = S m'".
|
||||
assert(n' = m') as H.
|
||||
SSCase "Proof of assertion". apply IHn'. inversion eq. reflexivity.
|
||||
rewrite -> H. reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem silly3' : forall (n : nat),
|
||||
(beq_nat n (S (S (S (S (S O))))) = true ->
|
||||
beq_nat (S (S n)) (S (S (S (S (S (S (S O))))))) = true) ->
|
||||
true = beq_nat n (S (S (S (S (S O))))) ->
|
||||
true = beq_nat (S (S n)) (S (S (S (S (S (S (S O))))))).
|
||||
Proof.
|
||||
intros n eq H.
|
||||
symmetry in H.
|
||||
apply eq in H.
|
||||
symmetry in H.
|
||||
apply H.
|
||||
Qed.
|
||||
|
||||
Theorem plus_n_n_injective : forall n m,
|
||||
n + n = m + m ->
|
||||
n = m.
|
||||
Proof.
|
||||
intros n. induction n as [| n'].
|
||||
Case "n = O".
|
||||
simpl. intros m.
|
||||
destruct m.
|
||||
SCase "m = O".
|
||||
reflexivity.
|
||||
SCase "m = S m'".
|
||||
simpl.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
Case "n = S n".
|
||||
intros m.
|
||||
destruct m.
|
||||
SCase "m = O".
|
||||
intros contra.
|
||||
inversion contra.
|
||||
SCase "m = S m'".
|
||||
intros eq.
|
||||
inversion eq.
|
||||
rewrite <- plus_n_Sm in H0.
|
||||
rewrite <- plus_n_Sm in H0.
|
||||
inversion H0.
|
||||
apply IHn' in H1.
|
||||
rewrite -> H1.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem override_shadow : forall {X : Type} x1 x2 k1 k2 (f : nat -> X),
|
||||
(override (override f k1 x2) k1 x1) k2 = (override f k1 x1) k2.
|
||||
Proof.
|
||||
intros X x1 x2 k1 k2 f.
|
||||
unfold override.
|
||||
destruct (beq_nat k1 k2).
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem combine_split : forall (X : Type) (Y : Type) (l : list (X * Y)) (l1: list X) (l2: list Y),
|
||||
split l = (l1, l2) -> combine l1 l2 = l.
|
||||
Proof.
|
||||
intros X Y l.
|
||||
induction l as [| x y].
|
||||
Case "l = nil".
|
||||
intros l1 l2.
|
||||
intros eq.
|
||||
simpl.
|
||||
simpl in eq.
|
||||
inversion eq.
|
||||
reflexivity.
|
||||
Case "l = ::".
|
||||
intros l1 l2.
|
||||
simpl.
|
||||
destruct x.
|
||||
destruct (split y).
|
||||
simpl.
|
||||
destruct l1.
|
||||
SCase "l1 = []".
|
||||
simpl.
|
||||
induction l2.
|
||||
SSCase "l2 = []".
|
||||
intros contra.
|
||||
inversion contra.
|
||||
SSCase "l2 = ::".
|
||||
intros contra.
|
||||
inversion contra.
|
||||
SCase "l1 = ::".
|
||||
induction l2.
|
||||
SSCase "l2 = []".
|
||||
simpl.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
SSCase "l2 = ::".
|
||||
simpl.
|
||||
intros eq.
|
||||
inversion eq.
|
||||
simpl.
|
||||
rewrite IHy.
|
||||
reflexivity.
|
||||
simpl.
|
||||
rewrite H1.
|
||||
rewrite H3.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem split_combine : forall (X : Type) (Y : Type) (l1: list X) (l2: list Y),
|
||||
length l1 = length l2 -> split (combine l1 l2) = (l1, l2).
|
||||
Proof.
|
||||
intros X Y.
|
||||
intros l1.
|
||||
induction l1.
|
||||
simpl.
|
||||
intros l2.
|
||||
induction l2.
|
||||
reflexivity.
|
||||
|
||||
intros contra.
|
||||
inversion contra.
|
||||
|
||||
destruct l2.
|
||||
simpl.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
|
||||
simpl.
|
||||
intros eq.
|
||||
inversion eq.
|
||||
apply IHl1 in H0.
|
||||
rewrite H0.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Definition sillyfun1 (n : nat) : bool :=
|
||||
if beq_nat n (S (S (S O))) then true
|
||||
else if beq_nat n (S (S (S (S (S O))))) then true
|
||||
else false.
|
||||
|
||||
Theorem beq_equal : forall (a b : nat),
|
||||
beq_nat a b = true ->
|
||||
a = b.
|
||||
Proof.
|
||||
intros a.
|
||||
induction a.
|
||||
destruct b.
|
||||
reflexivity.
|
||||
|
||||
intros contra.
|
||||
inversion contra.
|
||||
|
||||
destruct b.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
|
||||
simpl.
|
||||
intros eq.
|
||||
apply IHa in eq.
|
||||
rewrite eq.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem override_same : forall {X : Type} x1 k1 k2 (f : nat->X),
|
||||
f k1 = x1 ->
|
||||
(override f k1 x1) k2 = f k2.
|
||||
Proof.
|
||||
intros X x1 k1 k2 f eq.
|
||||
unfold override.
|
||||
remember (beq_nat k1 k2) as a.
|
||||
destruct a.
|
||||
rewrite <- eq.
|
||||
symmetry in Heqa.
|
||||
apply beq_equal in Heqa.
|
||||
rewrite -> Heqa.
|
||||
reflexivity.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
|
||||
Theorem filter_exercise : forall (X : Type) (test : X -> bool)
|
||||
(x : X) (l lf : list X),
|
||||
filter _ test l = x :: lf ->
|
||||
test x = true.
|
||||
Proof.
|
||||
intros X.
|
||||
intros test.
|
||||
intros x.
|
||||
induction l.
|
||||
simpl.
|
||||
intros lf.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
|
||||
simpl.
|
||||
remember (test x0) as a.
|
||||
destruct a.
|
||||
simpl.
|
||||
intros lf.
|
||||
intros eq.
|
||||
rewrite Heqa.
|
||||
inversion eq.
|
||||
reflexivity.
|
||||
|
||||
intros lf.
|
||||
intros eq.
|
||||
apply IHl in eq.
|
||||
rewrite eq.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem trans_eq : forall {X:Type} (n m o : X),
|
||||
n = m -> m = o -> n = o.
|
||||
Proof.
|
||||
intros X n m o eq1 eq2. rewrite -> eq1. rewrite -> eq2.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Example trans_eq_example' : forall (a b c d e f : nat),
|
||||
[a,b] = [c,d] ->
|
||||
[c,d] = [e,f] ->
|
||||
[a,b] = [e,f].
|
||||
Proof.
|
||||
intros a b c d e f eq1 eq2.
|
||||
apply trans_eq with (m := [c,d]). apply eq1. apply eq2.
|
||||
Qed.
|
||||
|
||||
Theorem trans_eq_exercise : forall (n m o p : nat),
|
||||
m = (minustwo o) ->
|
||||
(n + p) = m ->
|
||||
(n + p) = (minustwo o).
|
||||
Proof.
|
||||
intros n m o p.
|
||||
intros eq1 eq2.
|
||||
rewrite eq2.
|
||||
rewrite <- eq1.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem beq_nat_trans : forall n m p,
|
||||
true = beq_nat n m ->
|
||||
true = beq_nat m p ->
|
||||
true = beq_nat n p.
|
||||
Proof.
|
||||
intros n m p.
|
||||
intros eq1 eq2.
|
||||
symmetry in eq1.
|
||||
symmetry in eq2.
|
||||
apply beq_equal in eq1.
|
||||
apply beq_equal in eq2.
|
||||
rewrite eq1.
|
||||
rewrite <- eq2.
|
||||
apply beq_nat_refl.
|
||||
Qed.
|
||||
|
||||
Theorem override_permute : forall {X:Type} x1 x2 k1 k2 k3 (f : nat->X),
|
||||
false = beq_nat k2 k1 ->
|
||||
(override (override f k2 x2) k1 x1) k3 = (override (override f k1 x1) k2 x2) k3.
|
||||
Proof.
|
||||
intros X x1 x2 k1 k2 k3 f.
|
||||
simpl.
|
||||
unfold override.
|
||||
remember (beq_nat k1 k3).
|
||||
remember (beq_nat k2 k3).
|
||||
destruct b.
|
||||
destruct b0.
|
||||
symmetry in Heqb.
|
||||
symmetry in Heqb0.
|
||||
apply beq_equal in Heqb.
|
||||
apply beq_equal in Heqb0.
|
||||
rewrite <- Heqb in Heqb0.
|
||||
assert (k2 = k1 -> true = beq_nat k2 k1).
|
||||
destruct k2.
|
||||
destruct k1.
|
||||
reflexivity.
|
||||
|
||||
intros contra.
|
||||
inversion contra.
|
||||
|
||||
destruct k1.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
|
||||
simpl.
|
||||
intros eq.
|
||||
inversion eq.
|
||||
symmetry .
|
||||
symmetry .
|
||||
apply beq_nat_refl.
|
||||
|
||||
apply H in Heqb0.
|
||||
rewrite <- Heqb0.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
|
||||
intros eq.
|
||||
reflexivity.
|
||||
|
||||
destruct b0.
|
||||
intros eq.
|
||||
reflexivity.
|
||||
|
||||
intros eq.
|
||||
reflexivity.
|
||||
|
||||
Qed.
|
||||
|
||||
Definition fold_length {X : Type} (l : list X) : nat :=
|
||||
fold (fun _ n => S n) l O.
|
||||
|
||||
Example test_fold_length1 : fold_length [S (S (S (S O))), S (S (S (S (S (S (S O)))))), O] = S (S (S O)).
|
||||
Proof. reflexivity. Qed.
|
||||
|
||||
Theorem fold_length_correct : forall X (l :list X),
|
||||
fold_length l = length l.
|
||||
Proof.
|
||||
intros X l.
|
||||
unfold fold_length.
|
||||
induction l.
|
||||
Case "l = O".
|
||||
reflexivity.
|
||||
Case "l = ::".
|
||||
simpl.
|
||||
rewrite IHl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Definition fold_map {X Y: Type} (f : X -> Y) (l : list X) : list Y :=
|
||||
fold (fun x total => (f x) :: total) l [].
|
||||
|
||||
Theorem fold_map_correct : forall (X Y: Type) (f : X -> Y) (l : list X),
|
||||
fold_map f l = map f l.
|
||||
Proof.
|
||||
intros X Y f l.
|
||||
unfold fold_map.
|
||||
induction l.
|
||||
reflexivity.
|
||||
|
||||
simpl.
|
||||
rewrite IHl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Fixpoint forallb {X : Type} (f : X -> bool) (l : list X) :=
|
||||
match l with
|
||||
| nil => true
|
||||
| x :: xs => andb (f x) (forallb f xs)
|
||||
end.
|
||||
|
||||
Fixpoint existsb {X : Type} (f : X -> bool) (l : list X) :=
|
||||
match l with
|
||||
| nil => false
|
||||
| x :: xs => orb (f x) (existsb f xs)
|
||||
end.
|
||||
|
||||
Definition existsb2 {X : Type} (f: X -> bool) (l : list X) :=
|
||||
negb (forallb (fun x => negb (f x)) l).
|
||||
|
||||
Theorem existsb_correct : forall (X : Type) (f : X -> bool) (l : list X),
|
||||
existsb f l = existsb2 f l.
|
||||
Proof.
|
||||
intros X f l.
|
||||
induction l.
|
||||
reflexivity.
|
||||
|
||||
simpl.
|
||||
rewrite IHl.
|
||||
unfold existsb2.
|
||||
simpl.
|
||||
destruct (forallb (fun x0 : X => negb (f x0)) l).
|
||||
simpl.
|
||||
destruct (f x).
|
||||
reflexivity.
|
||||
|
||||
reflexivity.
|
||||
|
||||
destruct (f x).
|
||||
reflexivity.
|
||||
|
||||
reflexivity.
|
||||
|
||||
Qed.
|
||||
|
||||
Theorem index_okx : forall (X:Type) (l : list X) (n : nat),
|
||||
length l = n -> index X (S n) l = None.
|
||||
Proof.
|
||||
intros X l.
|
||||
induction l.
|
||||
reflexivity.
|
||||
|
||||
intros n.
|
||||
destruct n.
|
||||
intros contra.
|
||||
inversion contra.
|
||||
|
||||
intros eq.
|
||||
inversion eq.
|
||||
apply IHl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Inductive mumble : Type :=
|
||||
| a : mumble
|
||||
| b : mumble -> nat -> mumble
|
||||
| c : mumble.
|
||||
Inductive grumble (X:Type) : Type :=
|
||||
| d : mumble -> grumble X
|
||||
| e : X -> grumble X.
|
||||
|
||||
312
samples/Coq/Rel.v
Executable file
312
samples/Coq/Rel.v
Executable file
@@ -0,0 +1,312 @@
|
||||
Require Export Logic.
|
||||
Import Playground1.
|
||||
|
||||
Definition relation (X:Type) := X -> X -> Prop.
|
||||
|
||||
Definition partial_function {X:Type} (R: relation X) :=
|
||||
forall x y1 y2 : X, R x y1 -> R x y2 -> y1 = y2.
|
||||
|
||||
Theorem next_nat_partial_function :
|
||||
partial_function next_nat.
|
||||
Proof.
|
||||
unfold partial_function.
|
||||
intros x y1 y2 P Q.
|
||||
inversion P.
|
||||
inversion Q.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Theorem le_not_a_partial_function :
|
||||
~ (partial_function le).
|
||||
Proof.
|
||||
unfold not.
|
||||
unfold partial_function.
|
||||
intros H.
|
||||
assert (O = S O) as Nonsense.
|
||||
Case "Proof of assertion.".
|
||||
apply H with O.
|
||||
apply le_n.
|
||||
|
||||
apply le_S.
|
||||
apply le_n.
|
||||
|
||||
inversion Nonsense.
|
||||
Qed.
|
||||
|
||||
Theorem total_relation_not_partial_function :
|
||||
~ (partial_function total_relation).
|
||||
Proof.
|
||||
unfold not.
|
||||
unfold partial_function.
|
||||
intros H.
|
||||
assert (O = S O) as Nonsense.
|
||||
apply H with O.
|
||||
apply total_relation1.
|
||||
|
||||
apply total_relation1.
|
||||
|
||||
inversion Nonsense.
|
||||
Qed.
|
||||
|
||||
Theorem empty_relation_not_partial_funcion :
|
||||
partial_function empty_relation.
|
||||
Proof.
|
||||
unfold partial_function.
|
||||
intros x y1 y2.
|
||||
intros H.
|
||||
inversion H.
|
||||
Qed.
|
||||
|
||||
Definition reflexive {X:Type} (R: relation X) :=
|
||||
forall a : X, R a a.
|
||||
|
||||
Theorem le_reflexive :
|
||||
reflexive le.
|
||||
Proof.
|
||||
unfold reflexive.
|
||||
intros n. apply le_n.
|
||||
Qed.
|
||||
|
||||
Definition transitive {X:Type} (R: relation X) :=
|
||||
forall a b c : X, (R a b) -> (R b c) -> (R a c).
|
||||
|
||||
Theorem le_trans:
|
||||
transitive le.
|
||||
Proof.
|
||||
intros n m o Hnm Hmo.
|
||||
induction Hmo.
|
||||
Case "le_n". apply Hnm.
|
||||
Case "le_S". apply le_S. apply IHHmo.
|
||||
Qed.
|
||||
|
||||
Theorem lt_trans:
|
||||
transitive lt.
|
||||
Proof.
|
||||
unfold lt. unfold transitive.
|
||||
intros n m o Hnm Hmo.
|
||||
apply le_S in Hnm.
|
||||
apply le_trans with (a := (S n)) (b := (S m)) (c := o).
|
||||
apply Hnm.
|
||||
apply Hmo.
|
||||
Qed.
|
||||
|
||||
Theorem lt_trans' :
|
||||
transitive lt.
|
||||
Proof.
|
||||
unfold lt. unfold transitive.
|
||||
intros n m o Hnm Hmo.
|
||||
induction Hmo as [| m' Hm'o].
|
||||
apply le_S.
|
||||
apply Hnm.
|
||||
|
||||
apply le_S.
|
||||
apply IHHm'o.
|
||||
Qed.
|
||||
|
||||
Theorem le_Sn_le: forall n m, S n <= m -> n <= m.
|
||||
Proof.
|
||||
intros n m H. apply le_trans with (S n).
|
||||
apply le_S. apply le_n.
|
||||
apply H. Qed.
|
||||
|
||||
Theorem le_S_n : forall n m,
|
||||
(S n <= S m) -> (n <= m).
|
||||
Proof.
|
||||
intros n m H.
|
||||
apply Sn_le_Sm__n_le_m.
|
||||
apply H.
|
||||
Qed.
|
||||
|
||||
Theorem le_Sn_n : forall n,
|
||||
~ (S n <= n).
|
||||
Proof.
|
||||
induction n.
|
||||
intros H.
|
||||
inversion H.
|
||||
|
||||
unfold not in IHn.
|
||||
intros H.
|
||||
apply le_S_n in H.
|
||||
apply IHn.
|
||||
apply H.
|
||||
Qed.
|
||||
|
||||
(*
|
||||
TODO
|
||||
Theorem lt_trans'' :
|
||||
transitive lt.
|
||||
Proof.
|
||||
unfold lt. unfold transitive.
|
||||
intros n m o Hnm Hmo.
|
||||
induction o as [| o'].
|
||||
*)
|
||||
|
||||
Definition symmetric {X: Type} (R: relation X) :=
|
||||
forall a b : X, (R a b) -> (R b a).
|
||||
|
||||
Definition antisymmetric {X : Type} (R: relation X) :=
|
||||
forall a b : X, (R a b) -> (R b a) -> a = b.
|
||||
|
||||
Theorem le_antisymmetric :
|
||||
antisymmetric le.
|
||||
Proof.
|
||||
intros a b.
|
||||
generalize dependent a.
|
||||
induction b.
|
||||
intros a.
|
||||
intros H.
|
||||
intros H1.
|
||||
inversion H.
|
||||
reflexivity.
|
||||
|
||||
intros a H1 H2.
|
||||
destruct a.
|
||||
inversion H2.
|
||||
|
||||
apply Sn_le_Sm__n_le_m in H1.
|
||||
apply Sn_le_Sm__n_le_m in H2.
|
||||
apply IHb in H1.
|
||||
rewrite H1 in |- *.
|
||||
reflexivity.
|
||||
|
||||
apply H2.
|
||||
Qed.
|
||||
|
||||
(*
|
||||
TODO
|
||||
Theorem le_step : forall n m p,
|
||||
n < m ->
|
||||
n <= S p ->
|
||||
n <= p.
|
||||
Proof.
|
||||
*)
|
||||
|
||||
Definition equivalence {X:Type} (R: relation X) :=
|
||||
(reflexive R) /\ (symmetric R) /\ (transitive R).
|
||||
|
||||
Definition order {X:Type} (R: relation X) :=
|
||||
(reflexive R) /\ (antisymmetric R) /\ (transitive R).
|
||||
|
||||
Definition preorder {X:Type} (R: relation X) :=
|
||||
(reflexive R) /\ (transitive R).
|
||||
|
||||
Theorem le_order :
|
||||
order le.
|
||||
Proof.
|
||||
unfold order. split.
|
||||
Case "refl". apply le_reflexive.
|
||||
split.
|
||||
Case "antisym". apply le_antisymmetric.
|
||||
Case "transitive". apply le_trans. Qed.
|
||||
|
||||
Inductive clos_refl_trans {A:Type} (R: relation A) : relation A :=
|
||||
| rt_step : forall x y, R x y -> clos_refl_trans R x y
|
||||
| rt_refl : forall x, clos_refl_trans R x x
|
||||
| rt_trans : forall x y z,
|
||||
clos_refl_trans R x y -> clos_refl_trans R y z -> clos_refl_trans R x z.
|
||||
|
||||
Theorem next_nat_closure_is_le : forall n m,
|
||||
(n <= m) <-> ((clos_refl_trans next_nat) n m).
|
||||
Proof.
|
||||
intros n m.
|
||||
split.
|
||||
intro H.
|
||||
induction H.
|
||||
apply rt_refl.
|
||||
|
||||
apply rt_trans with m.
|
||||
apply IHle.
|
||||
|
||||
apply rt_step.
|
||||
apply nn.
|
||||
|
||||
intro H.
|
||||
induction H.
|
||||
inversion H.
|
||||
apply le_S.
|
||||
apply le_n.
|
||||
|
||||
apply le_n.
|
||||
|
||||
apply le_trans with y.
|
||||
apply IHclos_refl_trans1.
|
||||
|
||||
apply IHclos_refl_trans2.
|
||||
Qed.
|
||||
|
||||
Inductive refl_step_closure {X : Type} (R: relation X)
|
||||
: X -> X -> Prop :=
|
||||
| rsc_refl : forall (x : X), refl_step_closure R x x
|
||||
| rsc_step : forall (x y z : X), R x y ->
|
||||
refl_step_closure R y z ->
|
||||
refl_step_closure R x z.
|
||||
|
||||
Tactic Notation "rt_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "rt_step" | Case_aux c "rt_refl" | Case_aux c "rt_trans" ].
|
||||
|
||||
Tactic Notation "rsc_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "rsc_refl" | Case_aux c "rsc_step" ].
|
||||
|
||||
Theorem rsc_R : forall (X:Type) (R:relation X) (x y:X),
|
||||
R x y -> refl_step_closure R x y.
|
||||
Proof.
|
||||
intros X R x y r.
|
||||
apply rsc_step with y.
|
||||
apply r.
|
||||
|
||||
apply rsc_refl.
|
||||
Qed.
|
||||
|
||||
Theorem rsc_trans :
|
||||
forall (X : Type) (R : relation X) (x y z : X),
|
||||
refl_step_closure R x y ->
|
||||
refl_step_closure R y z ->
|
||||
refl_step_closure R x z.
|
||||
Proof.
|
||||
intros X.
|
||||
intros R x y z.
|
||||
intros H.
|
||||
induction H.
|
||||
intros H1.
|
||||
apply H1.
|
||||
|
||||
intros H1.
|
||||
apply IHrefl_step_closure in H1.
|
||||
apply rsc_step with y.
|
||||
apply H.
|
||||
|
||||
apply H1.
|
||||
Qed.
|
||||
|
||||
Theorem rtc_rsc_coincide:
|
||||
forall (X:Type) (R: relation X) (x y : X),
|
||||
clos_refl_trans R x y <-> refl_step_closure R x y.
|
||||
Proof.
|
||||
intros X R x y.
|
||||
split.
|
||||
intros H.
|
||||
induction H.
|
||||
apply rsc_step with y.
|
||||
apply H.
|
||||
|
||||
apply rsc_refl.
|
||||
|
||||
apply rsc_refl.
|
||||
|
||||
apply rsc_trans with y.
|
||||
apply IHclos_refl_trans1.
|
||||
|
||||
apply IHclos_refl_trans2.
|
||||
|
||||
intros H1.
|
||||
induction H1.
|
||||
apply rt_refl.
|
||||
|
||||
apply rt_trans with y.
|
||||
apply rt_step.
|
||||
apply H.
|
||||
|
||||
apply IHrefl_step_closure.
|
||||
Qed.
|
||||
701
samples/Coq/Smallstep.v
Executable file
701
samples/Coq/Smallstep.v
Executable file
@@ -0,0 +1,701 @@
|
||||
Require Export Imp.
|
||||
Require Export Relations.
|
||||
|
||||
Inductive tm : Type :=
|
||||
| tm_const : nat -> tm
|
||||
| tm_plus : tm -> tm -> tm.
|
||||
|
||||
Tactic Notation "tm_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "tm_const" | Case_aux c "tm_plus" ].
|
||||
|
||||
Module SimpleArith0.
|
||||
|
||||
Fixpoint eval (t : tm) : nat :=
|
||||
match t with
|
||||
| tm_const n => n
|
||||
| tm_plus a1 a2 => eval a1 + eval a2
|
||||
end.
|
||||
|
||||
End SimpleArith0.
|
||||
|
||||
Module SimpleArith1.
|
||||
|
||||
Reserved Notation " t '===>' n " (at level 50, left associativity).
|
||||
|
||||
Inductive eval : tm -> nat -> Prop :=
|
||||
| E_Const : forall n,
|
||||
tm_const n ===> n
|
||||
| E_Plus : forall t1 t2 n1 n2,
|
||||
t1 ===> n1 ->
|
||||
t2 ===> n2 ->
|
||||
tm_plus t1 t2 ===> plus n1 n2
|
||||
|
||||
where " t '===>' n " := (eval t n).
|
||||
|
||||
End SimpleArith1.
|
||||
|
||||
Reserved Notation " t '===>' t' " (at level 50, left associativity).
|
||||
|
||||
Inductive eval : tm -> tm -> Prop :=
|
||||
| E_Const : forall n1,
|
||||
tm_const n1 ===> tm_const n1
|
||||
| E_Plus : forall t1 n1 t2 n2,
|
||||
t1 ===> tm_const n1 ->
|
||||
t2 ===> tm_const n2 ->
|
||||
tm_plus t1 t2 ===> tm_const (plus n1 n2)
|
||||
where " t '===>' t' " := (eval t t').
|
||||
|
||||
Tactic Notation "eval_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "E_Const" | Case_aux c "E_Plus" ].
|
||||
|
||||
Module SimpleArith2.
|
||||
|
||||
Reserved Notation " t '=>' t' " (at level 40).
|
||||
|
||||
Inductive step : tm -> tm -> Prop :=
|
||||
| ST_PlusConstConst : forall n1 n2,
|
||||
tm_plus (tm_const n1) (tm_const n2) => tm_const (plus n1 n2)
|
||||
| ST_Plus1 : forall t1 t1' t2,
|
||||
t1 => t1' ->
|
||||
tm_plus t1 t2 => tm_plus t1' t2
|
||||
| ST_Plus2 : forall n1 t2 t2',
|
||||
t2 => t2' ->
|
||||
tm_plus (tm_const n1) t2 => tm_plus (tm_const n1) t2'
|
||||
|
||||
where " t '=>' t' " := (step t t').
|
||||
|
||||
Tactic Notation "step_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "ST_PlusConstConst"
|
||||
| Case_aux c "ST_Plus1" | Case_aux c "ST_Plus2" ].
|
||||
|
||||
Example test_step_1 :
|
||||
tm_plus
|
||||
(tm_plus (tm_const 0) (tm_const 3))
|
||||
(tm_plus (tm_const 2) (tm_const 4))
|
||||
=>
|
||||
tm_plus
|
||||
(tm_const (plus 0 3))
|
||||
(tm_plus (tm_const 2) (tm_const 4)).
|
||||
Proof.
|
||||
apply ST_Plus1. apply ST_PlusConstConst. Qed.
|
||||
|
||||
Example test_step_2 :
|
||||
tm_plus
|
||||
(tm_const 0)
|
||||
(tm_plus
|
||||
(tm_const 2)
|
||||
(tm_plus (tm_const 0) (tm_const 3)))
|
||||
=>
|
||||
tm_plus
|
||||
(tm_const 0)
|
||||
(tm_plus
|
||||
(tm_const 2)
|
||||
(tm_const (plus 0 3))).
|
||||
Proof.
|
||||
apply ST_Plus2.
|
||||
simpl.
|
||||
apply ST_Plus2.
|
||||
apply ST_PlusConstConst.
|
||||
Qed.
|
||||
|
||||
Theorem step_deterministic:
|
||||
partial_function step.
|
||||
Proof.
|
||||
unfold partial_function. intros x y1 y2 Hy1 Hy2.
|
||||
generalize dependent y2.
|
||||
step_cases (induction Hy1) Case; intros y2 Hy2.
|
||||
Case "ST_PlusConstConst". step_cases (inversion Hy2) SCase.
|
||||
SCase "ST_PlusConstConst". reflexivity.
|
||||
SCase "ST_Plus1". inversion H2.
|
||||
SCase "ST_Plus2". inversion H2.
|
||||
Case "ST_Plus1". step_cases (inversion Hy2) SCase.
|
||||
SCase "ST_PlusConstConst". rewrite <- H0 in Hy1. inversion Hy1.
|
||||
SCase "ST_Plus1".
|
||||
rewrite <- (IHHy1 t1'0).
|
||||
reflexivity. assumption.
|
||||
SCase "ST_Plus2". rewrite <- H in Hy1. inversion Hy1.
|
||||
Case "ST_Plus2". step_cases (inversion Hy2) SCase.
|
||||
SCase "ST_PlusConstConst". rewrite <- H1 in Hy1. inversion Hy1.
|
||||
SCase "ST_Plus1". inversion H2.
|
||||
SCase "ST_Plus2".
|
||||
rewrite <- (IHHy1 t2'0).
|
||||
reflexivity. assumption. Qed.
|
||||
|
||||
End SimpleArith2.
|
||||
|
||||
Inductive value : tm -> Prop :=
|
||||
v_const: forall n, value (tm_const n).
|
||||
|
||||
Reserved Notation " t '=>' t' " (at level 40).
|
||||
|
||||
Inductive step : tm -> tm -> Prop :=
|
||||
| ST_PlusConstConst : forall n1 n2,
|
||||
tm_plus (tm_const n1) (tm_const n2)
|
||||
=> tm_const (plus n1 n2)
|
||||
| ST_Plus1 : forall t1 t1' t2,
|
||||
t1 => t1' ->
|
||||
tm_plus t1 t2 => tm_plus t1' t2
|
||||
| ST_Plus2 : forall v1 t2 t2',
|
||||
value v1 ->
|
||||
t2 => t2' ->
|
||||
tm_plus v1 t2 => tm_plus v1 t2'
|
||||
|
||||
where " t '=>' t' " := (step t t').
|
||||
|
||||
Tactic Notation "step_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "ST_PlusConstConst"
|
||||
| Case_aux c "ST_Plus1" | Case_aux c "ST_Plus2" ].
|
||||
|
||||
Theorem step_deterministic :
|
||||
partial_function step.
|
||||
Proof.
|
||||
unfold partial_function.
|
||||
intros x y1 y2 Hy1 Hy2.
|
||||
generalize dependent y2.
|
||||
step_cases (induction Hy1) Case; intros y2 Hy2.
|
||||
step_cases (inversion Hy2) SCase.
|
||||
reflexivity.
|
||||
|
||||
inversion H2.
|
||||
|
||||
inversion Hy2.
|
||||
subst.
|
||||
assumption.
|
||||
|
||||
subst.
|
||||
inversion H3.
|
||||
|
||||
subst.
|
||||
inversion H3.
|
||||
|
||||
step_cases (inversion Hy2) SCase.
|
||||
rewrite <- H0 in Hy1.
|
||||
inversion Hy1.
|
||||
|
||||
rewrite <- (IHHy1 t1'0).
|
||||
reflexivity.
|
||||
|
||||
assumption.
|
||||
|
||||
rewrite <- H in Hy1.
|
||||
rewrite <- H in H1.
|
||||
subst.
|
||||
inversion H1.
|
||||
subst.
|
||||
inversion Hy1.
|
||||
|
||||
step_cases (inversion Hy2) SCase.
|
||||
subst.
|
||||
inversion Hy1.
|
||||
|
||||
subst.
|
||||
inversion H.
|
||||
subst.
|
||||
inversion H3.
|
||||
|
||||
subst.
|
||||
inversion H2.
|
||||
subst.
|
||||
rewrite <- (IHHy1 t2'0).
|
||||
reflexivity.
|
||||
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
Theorem strong_progress : forall t,
|
||||
value t \/ (exists t', t => t').
|
||||
Proof.
|
||||
tm_cases (induction t) Case.
|
||||
Case "tm_const". left. apply v_const.
|
||||
Case "tm_plus". right. inversion IHt1.
|
||||
SCase "l". inversion IHt2.
|
||||
SSCase "l". inversion H. inversion H0.
|
||||
exists (tm_const (plus n n0)).
|
||||
apply ST_PlusConstConst.
|
||||
SSCase "r". inversion H0 as [t' H1].
|
||||
exists (tm_plus t1 t').
|
||||
apply ST_Plus2. apply H. apply H1.
|
||||
SCase "r". inversion H as [t' H0].
|
||||
exists (tm_plus t' t2).
|
||||
apply ST_Plus1. apply H0. Qed.
|
||||
|
||||
Definition normal_form {X:Type} (R: relation X) (t: X) : Prop :=
|
||||
~ (exists t', R t t').
|
||||
|
||||
Lemma value_is_nf: forall t,
|
||||
value t -> normal_form step t.
|
||||
Proof.
|
||||
unfold normal_form. intros t H. inversion H.
|
||||
intros contra. inversion contra. inversion H1.
|
||||
Qed.
|
||||
|
||||
Lemma nf_is_value: forall t,
|
||||
normal_form step t -> value t.
|
||||
Proof.
|
||||
unfold normal_form. intros t H.
|
||||
assert (G: value t \/ (exists t', t => t')).
|
||||
SCase "Proof of assertion". apply strong_progress.
|
||||
inversion G.
|
||||
SCase "l". assumption.
|
||||
SCase "r". apply ex_falso_quodlibet. apply H. assumption. Qed.
|
||||
|
||||
Corollary nf_same_as_value : forall t,
|
||||
normal_form step t <-> value t.
|
||||
Proof.
|
||||
split. apply nf_is_value. apply value_is_nf.
|
||||
Qed.
|
||||
|
||||
Module Temp1.
|
||||
|
||||
Inductive value : tm -> Prop :=
|
||||
| v_const : forall n, value (tm_const n)
|
||||
| v_funny : forall t1 n2, (* <---- *)
|
||||
value (tm_plus t1 (tm_const n2)).
|
||||
|
||||
Reserved Notation " t '=>' t' " (at level 40).
|
||||
|
||||
Inductive step : tm -> tm -> Prop :=
|
||||
| ST_PlusConstConst : forall n1 n2,
|
||||
tm_plus (tm_const n1) (tm_const n2) => tm_const (plus n1 n2)
|
||||
| ST_Plus1 : forall t1 t1' t2,
|
||||
t1 => t1' ->
|
||||
tm_plus t1 t2 => tm_plus t1' t2
|
||||
| ST_Plus2 : forall v1 t2 t2',
|
||||
value v1 ->
|
||||
t2 => t2' ->
|
||||
tm_plus v1 t2 => tm_plus v1 t2'
|
||||
|
||||
where " t '=>' t' " := (step t t').
|
||||
|
||||
Lemma value_not_same_as_normal_form:
|
||||
exists t, value t /\ ~ normal_form step t.
|
||||
Proof.
|
||||
intros.
|
||||
unfold normal_form.
|
||||
exists (tm_plus (tm_plus (tm_const 1) (tm_const 2)) (tm_const 2)).
|
||||
split.
|
||||
apply v_funny.
|
||||
|
||||
unfold not.
|
||||
intros.
|
||||
apply H.
|
||||
exists (tm_plus (tm_const (1 + 2)) (tm_const 2)).
|
||||
apply ST_Plus1.
|
||||
apply ST_PlusConstConst.
|
||||
Qed.
|
||||
|
||||
End Temp1.
|
||||
|
||||
Module Temp2.
|
||||
|
||||
Inductive value : tm -> Prop :=
|
||||
| v_const : forall n, value (tm_const n).
|
||||
|
||||
(*Reserved Notation " t '===>' t' " (at level 40).*)
|
||||
|
||||
Inductive step : tm -> tm -> Prop :=
|
||||
| ST_Funny : forall n, (* <---- *)
|
||||
tm_const n ===> tm_plus (tm_const n) (tm_const 0)
|
||||
| ST_PlusConstConst : forall n1 n2,
|
||||
tm_plus (tm_const n1) (tm_const n2) ===> tm_const (plus n1 n2)
|
||||
| ST_Plus1 : forall t1 t1' t2,
|
||||
t1 ===> t1' ->
|
||||
tm_plus t1 t2 ===> tm_plus t1' t2
|
||||
| ST_Plus2 : forall v1 t2 t2',
|
||||
value v1 ->
|
||||
t2 ===> t2' ->
|
||||
tm_plus v1 t2 ===> tm_plus v1 t2'
|
||||
|
||||
where " t '===>' t' " := (step t t').
|
||||
|
||||
Lemma value_not_same_as_normal_form :
|
||||
exists t, value t /\ ~ normal_form step t.
|
||||
Proof.
|
||||
exists (tm_const 0).
|
||||
split.
|
||||
apply v_const.
|
||||
|
||||
unfold normal_form.
|
||||
unfold not.
|
||||
intro H.
|
||||
apply H.
|
||||
exists (tm_plus (tm_const 0) (tm_const 0)).
|
||||
apply ST_Funny.
|
||||
Qed.
|
||||
|
||||
End Temp2.
|
||||
|
||||
Module Temp3.
|
||||
|
||||
Inductive value : tm -> Prop :=
|
||||
| v_const : forall n, value (tm_const n).
|
||||
|
||||
(*Reserved Notation " t '===>' t' " (at level 40).*)
|
||||
|
||||
Inductive step : tm -> tm -> Prop :=
|
||||
| ST_PlusConstConst : forall n1 n2,
|
||||
tm_plus (tm_const n1) (tm_const n2) ===> tm_const (plus n1 n2)
|
||||
| ST_Plus1 : forall t1 t1' t2,
|
||||
t1 ===> t1' ->
|
||||
tm_plus t1 t2 ===> tm_plus t1' t2
|
||||
|
||||
where " t '===>' t' " := (step t t').
|
||||
|
||||
Lemma value_not_same_as_normal_form:
|
||||
exists t, ~ value t /\ normal_form step t.
|
||||
Proof.
|
||||
exists (tm_plus (tm_const 1) (tm_plus (tm_const 0) (tm_const 0))).
|
||||
split.
|
||||
intros H.
|
||||
inversion H.
|
||||
|
||||
unfold normal_form.
|
||||
intros H.
|
||||
inversion H.
|
||||
inversion H0.
|
||||
inversion H4.
|
||||
Qed.
|
||||
|
||||
End Temp3.
|
||||
|
||||
Module Temp4.
|
||||
Inductive tm : Type :=
|
||||
| tm_true : tm
|
||||
| tm_false : tm
|
||||
| tm_if : tm -> tm -> tm -> tm.
|
||||
|
||||
Inductive value : tm -> Prop :=
|
||||
| v_true : value tm_true
|
||||
| v_false : value tm_false.
|
||||
|
||||
Inductive step : tm -> tm -> Prop :=
|
||||
| ST_IfTrue : forall t1 t2,
|
||||
tm_if tm_true t1 t2 ===> t1
|
||||
| ST_IfFalse : forall t1 t2,
|
||||
tm_if tm_false t1 t2 ===> t2
|
||||
| ST_If : forall t1 t1' t2 t3,
|
||||
t1 ===> t1' ->
|
||||
tm_if t1 t2 t3 ===> tm_if t1' t2 t3
|
||||
|
||||
where " t '===>' t' " := (step t t').
|
||||
|
||||
Example bool_step_prop3 :
|
||||
tm_if
|
||||
(tm_if tm_true tm_true tm_true)
|
||||
(tm_if tm_true tm_true tm_true)
|
||||
tm_false
|
||||
===>
|
||||
tm_if
|
||||
tm_true
|
||||
(tm_if tm_true tm_true tm_true)
|
||||
tm_false.
|
||||
Proof.
|
||||
apply ST_If.
|
||||
apply ST_IfTrue.
|
||||
Qed.
|
||||
|
||||
Theorem strong_progress: forall t,
|
||||
value t \/ (exists t', t ===> t').
|
||||
Proof.
|
||||
induction t.
|
||||
left.
|
||||
constructor.
|
||||
|
||||
left.
|
||||
constructor.
|
||||
|
||||
right.
|
||||
inversion IHt1.
|
||||
inversion H.
|
||||
exists t2.
|
||||
apply ST_IfTrue.
|
||||
|
||||
exists t3.
|
||||
apply ST_IfFalse.
|
||||
|
||||
inversion H.
|
||||
exists (tm_if x t2 t3).
|
||||
apply ST_If.
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
Theorem step_deterministic :
|
||||
partial_function step.
|
||||
Proof.
|
||||
unfold partial_function.
|
||||
intros x y1 y2 Hy1 Hy2.
|
||||
generalize dependent y2.
|
||||
induction Hy1.
|
||||
intros.
|
||||
inversion Hy2.
|
||||
reflexivity.
|
||||
|
||||
subst.
|
||||
inversion H3.
|
||||
|
||||
intros.
|
||||
inversion Hy2.
|
||||
reflexivity.
|
||||
|
||||
inversion H3.
|
||||
|
||||
intros.
|
||||
inversion Hy2.
|
||||
subst.
|
||||
inversion Hy1.
|
||||
|
||||
subst.
|
||||
inversion Hy1.
|
||||
|
||||
subst.
|
||||
apply IHHy1 in H3.
|
||||
subst.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Module Temp5.
|
||||
|
||||
|
||||
Inductive step : tm -> tm -> Prop :=
|
||||
| ST_IfTrue : forall t1 t2,
|
||||
tm_if tm_true t1 t2 ===> t1
|
||||
| ST_IfFalse : forall t1 t2,
|
||||
tm_if tm_false t1 t2 ===> t2
|
||||
| ST_If : forall t1 t1' t2 t3,
|
||||
t1 ===> t1' ->
|
||||
tm_if t1 t2 t3 ===> tm_if t1' t2 t3
|
||||
| ST_ShortCut : forall v t,
|
||||
value v ->
|
||||
tm_if t v v ===> v
|
||||
|
||||
where " t '===>' t' " := (step t t').
|
||||
|
||||
Definition bool_step_prop4 :=
|
||||
tm_if
|
||||
(tm_if tm_true tm_true tm_true)
|
||||
tm_false
|
||||
tm_false
|
||||
===>
|
||||
tm_false.
|
||||
|
||||
Example bool_step_prop4_holds :
|
||||
bool_step_prop4.
|
||||
Proof.
|
||||
unfold bool_step_prop4.
|
||||
apply ST_ShortCut.
|
||||
constructor.
|
||||
Qed.
|
||||
|
||||
Theorem strong_progress: forall t,
|
||||
value t \/ (exists t', t ===> t').
|
||||
Proof.
|
||||
induction t.
|
||||
left.
|
||||
constructor.
|
||||
|
||||
left.
|
||||
constructor.
|
||||
|
||||
inversion IHt1.
|
||||
right.
|
||||
inversion H.
|
||||
exists t2.
|
||||
constructor.
|
||||
|
||||
exists t3.
|
||||
constructor.
|
||||
|
||||
right.
|
||||
inversion H.
|
||||
exists (tm_if x t2 t3).
|
||||
apply ST_If.
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
End Temp5.
|
||||
End Temp4.
|
||||
|
||||
Definition stepmany := refl_step_closure step.
|
||||
|
||||
Notation " t '===>*' t' " := (stepmany t t') (at level 40).
|
||||
|
||||
Lemma test_stepmany_1:
|
||||
tm_plus
|
||||
(tm_plus (tm_const 0) (tm_const 3))
|
||||
(tm_plus (tm_const 2) (tm_const 4))
|
||||
===>*
|
||||
tm_const (plus (plus 0 3) (plus 2 4)).
|
||||
Proof.
|
||||
eapply rsc_step. apply ST_Plus1. apply ST_PlusConstConst.
|
||||
eapply rsc_step. apply ST_Plus2. apply v_const.
|
||||
apply ST_PlusConstConst.
|
||||
eapply rsc_step. apply ST_PlusConstConst.
|
||||
apply rsc_refl. Qed.
|
||||
|
||||
Lemma test_stepmany_2:
|
||||
tm_const 3 ===>* tm_const 3.
|
||||
Proof.
|
||||
eapply rsc_refl.
|
||||
Qed.
|
||||
|
||||
Lemma test_stepmany_3:
|
||||
tm_plus (tm_const 0) (tm_const 3)
|
||||
===>*
|
||||
tm_plus (tm_const 0) (tm_const 3).
|
||||
Proof.
|
||||
eapply rsc_refl.
|
||||
Qed.
|
||||
|
||||
Lemma test_stepmany_4:
|
||||
tm_plus
|
||||
(tm_const 0)
|
||||
(tm_plus
|
||||
(tm_const 2)
|
||||
(tm_plus (tm_const 0) (tm_const 3)))
|
||||
===>*
|
||||
tm_plus
|
||||
(tm_const 0)
|
||||
(tm_const (plus 2 (plus 0 3))).
|
||||
Proof.
|
||||
eapply rsc_step.
|
||||
apply ST_Plus2.
|
||||
apply v_const.
|
||||
|
||||
apply ST_Plus2.
|
||||
apply v_const.
|
||||
|
||||
apply ST_PlusConstConst.
|
||||
|
||||
eapply rsc_step.
|
||||
apply ST_Plus2.
|
||||
apply v_const.
|
||||
|
||||
apply ST_PlusConstConst.
|
||||
|
||||
eapply rsc_refl.
|
||||
Qed.
|
||||
|
||||
Definition step_normal_form := normal_form step.
|
||||
|
||||
Definition normal_form_of (t t' : tm) :=
|
||||
(t ===>* t' /\ step_normal_form t').
|
||||
|
||||
(*
|
||||
Theorem normal_forms_unique:
|
||||
partial_function normal_form_of.
|
||||
Proof.
|
||||
unfold partial_function. unfold normal_form_of. intros x y1 y2 P1 P2.
|
||||
destruct P1 as [P11 P12]. destruct P2 as [P21 P22].
|
||||
generalize dependent y2.
|
||||
|
||||
unfold step_normal_form in P12.
|
||||
unfold step_normal_form.
|
||||
unfold normal_form.
|
||||
unfold normal_form in P12.
|
||||
induction x.
|
||||
intros.
|
||||
unfold stepmany.
|
||||
inversion P11.
|
||||
subst.
|
||||
inversion P21.
|
||||
subst.
|
||||
reflexivity.
|
||||
|
||||
subst.
|
||||
inversion P21.
|
||||
reflexivity.
|
||||
|
||||
subst.
|
||||
inversion H1.
|
||||
|
||||
inversion H.
|
||||
*)
|
||||
|
||||
Definition normalizing {X:Type} (R:relation X) :=
|
||||
forall t, exists t',
|
||||
(refl_step_closure R) t t' /\ normal_form R t'.
|
||||
|
||||
Lemma stepmany_congr_1 : forall t1 t1' t2,
|
||||
t1 ===>* t1' ->
|
||||
tm_plus t1 t2 ===>* tm_plus t1' t2.
|
||||
Proof.
|
||||
intros t1 t1' t2 H.
|
||||
rsc_cases (induction H) Case.
|
||||
apply rsc_refl.
|
||||
|
||||
apply rsc_step with (tm_plus y t2).
|
||||
apply ST_Plus1.
|
||||
apply H.
|
||||
|
||||
apply IHrefl_step_closure.
|
||||
Qed.
|
||||
|
||||
Lemma stepmany_congr2 : forall t1 t2 t2',
|
||||
value t1 ->
|
||||
t2 ===>* t2' ->
|
||||
tm_plus t1 t2 ===>* tm_plus t1 t2'.
|
||||
Proof.
|
||||
intros t1 t2 t2'.
|
||||
intros H1.
|
||||
intros H2.
|
||||
induction H2.
|
||||
apply rsc_refl.
|
||||
|
||||
apply rsc_step with (tm_plus t1 y).
|
||||
apply ST_Plus2.
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
Theorem step_normalizing :
|
||||
normalizing step.
|
||||
Proof.
|
||||
unfold normalizing.
|
||||
tm_cases (induction t) Case.
|
||||
Case "tm_const".
|
||||
exists (tm_const n).
|
||||
split.
|
||||
SCase "l". apply rsc_refl.
|
||||
SCase "r".
|
||||
(* We can use rewrite with "iff" statements, not
|
||||
just equalities: *)
|
||||
rewrite nf_same_as_value. apply v_const.
|
||||
Case "tm_plus".
|
||||
destruct IHt1 as [t1' H1]. destruct IHt2 as [t2' H2].
|
||||
destruct H1 as [H11 H12]. destruct H2 as [H21 H22].
|
||||
rewrite nf_same_as_value in H12. rewrite nf_same_as_value in H22.
|
||||
inversion H12 as [n1]. inversion H22 as [n2].
|
||||
rewrite <- H in H11.
|
||||
rewrite <- H0 in H21.
|
||||
exists (tm_const (plus n1 n2)).
|
||||
split.
|
||||
SCase "l".
|
||||
apply rsc_trans with (tm_plus (tm_const n1) t2).
|
||||
apply stepmany_congr_1. apply H11.
|
||||
apply rsc_trans with
|
||||
(tm_plus (tm_const n1) (tm_const n2)).
|
||||
apply stepmany_congr2. apply v_const. apply H21.
|
||||
apply rsc_R. apply ST_PlusConstConst.
|
||||
SCase "r".
|
||||
rewrite nf_same_as_value. apply v_const. Qed.
|
||||
|
||||
Lemma eval__value : forall t1 t2,
|
||||
eval t1 t2 ->
|
||||
value t2.
|
||||
Proof.
|
||||
intros t1 t2 HE.
|
||||
eval_cases (inversion HE) Case; apply v_const. Qed.
|
||||
|
||||
|
||||
(*
|
||||
Theorem eval__stepmany: forall t v,
|
||||
eval t v -> t ===>* v.
|
||||
Proof.
|
||||
*)
|
||||
2
samples/Coq/Sorting.v
Executable file
2
samples/Coq/Sorting.v
Executable file
@@ -0,0 +1,2 @@
|
||||
Require Export Sorted.
|
||||
Require Export Mergesort.
|
||||
733
samples/Coq/Stlc.v
Executable file
733
samples/Coq/Stlc.v
Executable file
@@ -0,0 +1,733 @@
|
||||
|
||||
Require Export SfLib.
|
||||
|
||||
Module STLC.
|
||||
|
||||
Inductive ty : Type :=
|
||||
| ty_Bool : ty
|
||||
| ty_arrow : ty -> ty -> ty.
|
||||
|
||||
Inductive tm : Type :=
|
||||
| tm_var : id -> tm
|
||||
| tm_app : tm -> tm -> tm
|
||||
| tm_abs : id -> ty -> tm -> tm
|
||||
| tm_true : tm
|
||||
| tm_false : tm
|
||||
| tm_if : tm -> tm -> tm -> tm.
|
||||
|
||||
Tactic Notation "tm_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "tm_var" | Case_aux c "tm_app"
|
||||
| Case_aux c "tm_abs" | Case_aux c "tm_true"
|
||||
| Case_aux c "tm_false" | Case_aux c "tm_if" ].
|
||||
|
||||
Notation a := (Id 0).
|
||||
Notation b := (Id 1).
|
||||
Notation c := (Id 2).
|
||||
|
||||
Notation idB :=
|
||||
(tm_abs a ty_Bool (tm_var a)).
|
||||
|
||||
Notation idBB :=
|
||||
(tm_abs a (ty_arrow ty_Bool ty_Bool) (tm_var a)).
|
||||
|
||||
Notation idBBBB :=
|
||||
(tm_abs a (ty_arrow (ty_arrow ty_Bool ty_Bool)
|
||||
(ty_arrow ty_Bool ty_Bool))
|
||||
(tm_var a)).
|
||||
|
||||
Notation k := (tm_abs a ty_Bool (tm_abs b ty_Bool (tm_var a))).
|
||||
|
||||
Inductive value : tm -> Prop :=
|
||||
| v_abs : forall x T t,
|
||||
value (tm_abs x T t)
|
||||
| t_true :
|
||||
value tm_true
|
||||
| t_false :
|
||||
value tm_false.
|
||||
|
||||
Hint Constructors value.
|
||||
|
||||
Fixpoint subst (s:tm) (x:id) (t:tm) : tm :=
|
||||
match t with
|
||||
| tm_var x' => if beq_id x x' then s else t
|
||||
| tm_abs x' T t1 => tm_abs x' T (if beq_id x x' then t1 else (subst s x t1))
|
||||
| tm_app t1 t2 => tm_app (subst s x t1) (subst s x t2)
|
||||
| tm_true => tm_true
|
||||
| tm_false => tm_false
|
||||
| tm_if t1 t2 t3 => tm_if (subst s x t1) (subst s x t2) (subst s x t3)
|
||||
end.
|
||||
|
||||
Reserved Notation "t1 '==>' t2" (at level 40).
|
||||
|
||||
Inductive step : tm -> tm -> Prop :=
|
||||
| ST_AppAbs : forall x T t12 v2,
|
||||
value v2 ->
|
||||
(tm_app (tm_abs x T t12) v2) ==> (subst v2 x t12)
|
||||
| ST_App1 : forall t1 t1' t2,
|
||||
t1 ==> t1' ->
|
||||
tm_app t1 t2 ==> tm_app t1' t2
|
||||
| ST_App2 : forall v1 t2 t2',
|
||||
value v1 ->
|
||||
t2 ==> t2' ->
|
||||
tm_app v1 t2 ==> tm_app v1 t2'
|
||||
| ST_IfTrue : forall t1 t2,
|
||||
(tm_if tm_true t1 t2) ==> t1
|
||||
| ST_IfFalse : forall t1 t2,
|
||||
(tm_if tm_false t1 t2) ==> t2
|
||||
| ST_If : forall t1 t1' t2 t3,
|
||||
t1 ==> t1' ->
|
||||
(tm_if t1 t2 t3) ==> (tm_if t1' t2 t3)
|
||||
|
||||
where "t1 '==>' t2" := (step t1 t2).
|
||||
|
||||
Tactic Notation "step_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "ST_AppAbs" | Case_aux c "ST_App1"
|
||||
| Case_aux c "ST_App2" | Case_aux c "ST_IfTrue"
|
||||
| Case_aux c "ST_IfFalse" | Case_aux c "ST_If" ].
|
||||
|
||||
Notation stepmany := (refl_step_closure step).
|
||||
Notation "t1 '==>*' t2" := (stepmany t1 t2) (at level 40).
|
||||
|
||||
Hint Constructors step.
|
||||
|
||||
Lemma step_example3 :
|
||||
(tm_app (tm_app idBBBB idBB) idB)
|
||||
==>* idB.
|
||||
Proof.
|
||||
eapply rsc_step.
|
||||
apply ST_App1.
|
||||
apply ST_AppAbs.
|
||||
apply v_abs.
|
||||
|
||||
simpl.
|
||||
eapply rsc_step.
|
||||
apply ST_AppAbs.
|
||||
apply v_abs.
|
||||
|
||||
simpl.
|
||||
apply rsc_refl.
|
||||
Qed.
|
||||
|
||||
Definition context := partial_map ty.
|
||||
Module Context.
|
||||
|
||||
Definition partial_map (A:Type) := id -> option A.
|
||||
Definition empty {A:Type} : partial_map A := (fun _ => None).
|
||||
Definition extend {A:Type} (Gamma : partial_map A) (x:id) (T : A) :=
|
||||
fun x' => if beq_id x x' then Some T else Gamma x'.
|
||||
|
||||
Lemma extend_eq : forall A (ctxt: partial_map A) x T,
|
||||
(extend ctxt x T) x = Some T.
|
||||
Proof.
|
||||
intros. unfold extend. rewrite <- beq_id_refl. auto.
|
||||
Qed.
|
||||
|
||||
Lemma extend_neq : forall A (ctxt: partial_map A) x1 T x2,
|
||||
beq_id x2 x1 = false ->
|
||||
(extend ctxt x2 T) x1 = ctxt x1.
|
||||
Proof.
|
||||
intros. unfold extend. rewrite H. auto.
|
||||
Qed.
|
||||
|
||||
End Context.
|
||||
|
||||
Inductive has_type : context -> tm -> ty -> Prop :=
|
||||
| T_Var : forall Gamma x T,
|
||||
Gamma x = Some T ->
|
||||
has_type Gamma (tm_var x) T
|
||||
| T_Abs : forall Gamma x T11 T12 t12,
|
||||
has_type (extend Gamma x T11) t12 T12 ->
|
||||
has_type Gamma (tm_abs x T11 t12) (ty_arrow T11 T12)
|
||||
| T_App : forall T11 T12 Gamma t1 t2,
|
||||
has_type Gamma t1 (ty_arrow T11 T12) ->
|
||||
has_type Gamma t2 T11 ->
|
||||
has_type Gamma (tm_app t1 t2) T12
|
||||
| T_True : forall Gamma,
|
||||
has_type Gamma tm_true ty_Bool
|
||||
| T_False : forall Gamma,
|
||||
has_type Gamma tm_false ty_Bool
|
||||
| T_If : forall t1 t2 t3 T Gamma,
|
||||
has_type Gamma t1 ty_Bool ->
|
||||
has_type Gamma t2 T ->
|
||||
has_type Gamma t3 T ->
|
||||
has_type Gamma (tm_if t1 t2 t3) T.
|
||||
|
||||
Tactic Notation "has_type_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "T_Var" | Case_aux c "T_Abs"
|
||||
| Case_aux c "T_App" | Case_aux c "T_True"
|
||||
| Case_aux c "T_False" | Case_aux c "T_If" ].
|
||||
|
||||
Hint Constructors has_type.
|
||||
|
||||
Hint Unfold beq_id beq_nat extend.
|
||||
|
||||
Example typing_example_2_full :
|
||||
has_type empty
|
||||
(tm_abs a ty_Bool
|
||||
(tm_abs b (ty_arrow ty_Bool ty_Bool)
|
||||
(tm_app (tm_var b) (tm_app (tm_var b) (tm_var a)))))
|
||||
(ty_arrow ty_Bool (ty_arrow (ty_arrow ty_Bool ty_Bool) ty_Bool)).
|
||||
Proof.
|
||||
apply T_Abs.
|
||||
apply T_Abs.
|
||||
apply T_App with (T11 := ty_Bool).
|
||||
apply T_Var.
|
||||
unfold extend.
|
||||
simpl.
|
||||
reflexivity.
|
||||
|
||||
apply T_App with (T11 := ty_Bool).
|
||||
apply T_Var.
|
||||
unfold extend.
|
||||
simpl.
|
||||
reflexivity.
|
||||
|
||||
apply T_Var.
|
||||
unfold extend.
|
||||
simpl.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Example typing_example_3 :
|
||||
exists T,
|
||||
has_type empty
|
||||
(tm_abs a (ty_arrow ty_Bool ty_Bool)
|
||||
(tm_abs b (ty_arrow ty_Bool ty_Bool)
|
||||
(tm_abs c ty_Bool
|
||||
(tm_app (tm_var b) (tm_app (tm_var a) (tm_var c))))))
|
||||
T.
|
||||
|
||||
Proof with auto.
|
||||
exists
|
||||
(ty_arrow (ty_arrow ty_Bool ty_Bool)
|
||||
(ty_arrow (ty_arrow ty_Bool ty_Bool) (ty_arrow ty_Bool ty_Bool))).
|
||||
apply T_Abs.
|
||||
apply T_Abs.
|
||||
apply T_Abs.
|
||||
apply T_App with (T11 := ty_Bool).
|
||||
apply T_Var.
|
||||
unfold extend.
|
||||
simpl.
|
||||
reflexivity.
|
||||
|
||||
apply T_App with (T11 := ty_Bool).
|
||||
auto.
|
||||
|
||||
auto.
|
||||
Qed.
|
||||
|
||||
|
||||
Theorem coiso : forall a b e,
|
||||
a ==>* b ->
|
||||
tm_app a e ==>* tm_app b e.
|
||||
Proof.
|
||||
intros.
|
||||
induction H.
|
||||
apply rsc_refl.
|
||||
|
||||
apply rsc_step with (tm_app y e).
|
||||
apply ST_App1.
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
Theorem reptrans : forall a b c,
|
||||
a ==>* b ->
|
||||
b ==>* c ->
|
||||
a ==>* c.
|
||||
Proof.
|
||||
|
||||
intros a b c H.
|
||||
induction H.
|
||||
intros.
|
||||
assumption.
|
||||
|
||||
intros H1.
|
||||
apply IHrefl_step_closure in H1.
|
||||
apply rsc_step with y.
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
(* TODO
|
||||
Example typing_nonexample_3 :
|
||||
~ (exists S, exists T,
|
||||
has_type empty
|
||||
(tm_abs a S
|
||||
(tm_app (tm_var a) (tm_var a)))
|
||||
T).
|
||||
Proof.
|
||||
*)
|
||||
|
||||
Inductive appears_free_in : id -> tm -> Prop :=
|
||||
| afi_var : forall x,
|
||||
appears_free_in x (tm_var x)
|
||||
| afi_app1 : forall x t1 t2,
|
||||
appears_free_in x t1 -> appears_free_in x (tm_app t1 t2)
|
||||
| afi_app2 : forall x t1 t2,
|
||||
appears_free_in x t2 -> appears_free_in x (tm_app t1 t2)
|
||||
| afi_abs : forall x y T11 t12,
|
||||
y <> x ->
|
||||
appears_free_in x t12 ->
|
||||
appears_free_in x (tm_abs y T11 t12)
|
||||
| afi_if1 : forall x t1 t2 t3,
|
||||
appears_free_in x t1 ->
|
||||
appears_free_in x (tm_if t1 t2 t3)
|
||||
| afi_if2 : forall x t1 t2 t3,
|
||||
appears_free_in x t2 ->
|
||||
appears_free_in x (tm_if t1 t2 t3)
|
||||
| afi_if3 : forall x t1 t2 t3,
|
||||
appears_free_in x t3 ->
|
||||
appears_free_in x (tm_if t1 t2 t3).
|
||||
|
||||
Tactic Notation "afi_cases" tactic(first) ident(c) :=
|
||||
first;
|
||||
[ Case_aux c "afi_var"
|
||||
| Case_aux c "afi_app1" | Case_aux c "afi_app2"
|
||||
| Case_aux c "afi_abs"
|
||||
| Case_aux c "afi_if1" | Case_aux c "afi_if2"
|
||||
| Case_aux c "afi_if3" ].
|
||||
|
||||
Hint Constructors appears_free_in.
|
||||
|
||||
Definition closed (t:tm) :=
|
||||
forall x, ~ appears_free_in x t.
|
||||
|
||||
Lemma free_in_context : forall x t T Gamma,
|
||||
appears_free_in x t ->
|
||||
has_type Gamma t T ->
|
||||
exists T', Gamma x = Some T'.
|
||||
Proof.
|
||||
intros. generalize dependent Gamma. generalize dependent T.
|
||||
afi_cases (induction H) Case;
|
||||
intros; try solve [inversion H0; eauto].
|
||||
Case "afi_abs".
|
||||
inversion H1; subst.
|
||||
apply IHappears_free_in in H7.
|
||||
apply not_eq_beq_id_false in H.
|
||||
rewrite extend_neq in H7; assumption.
|
||||
Qed.
|
||||
|
||||
Corollary typable_empty__closed : forall t T,
|
||||
has_type empty t T ->
|
||||
closed t.
|
||||
Proof.
|
||||
intros t T H x H1.
|
||||
remember (@empty ty) as Gamma.
|
||||
assert (exists t' : _, Gamma x = Some t').
|
||||
apply free_in_context with (t := t) (T := T).
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
|
||||
inversion H0.
|
||||
rewrite HeqGamma in H2.
|
||||
inversion H2.
|
||||
Qed.
|
||||
|
||||
Lemma context_invariance : forall Gamma Gamma' t S,
|
||||
has_type Gamma t S ->
|
||||
(forall x, appears_free_in x t -> Gamma x = Gamma' x) ->
|
||||
has_type Gamma' t S.
|
||||
Proof with auto.
|
||||
intros.
|
||||
generalize dependent Gamma'.
|
||||
has_type_cases (induction H) Case; intros; auto.
|
||||
apply T_Var.
|
||||
rewrite <- H0...
|
||||
|
||||
apply T_Abs.
|
||||
apply IHhas_type.
|
||||
intros x0 Hafi.
|
||||
unfold extend.
|
||||
remember (beq_id x x0) as e.
|
||||
destruct e.
|
||||
reflexivity.
|
||||
|
||||
auto.
|
||||
apply H0.
|
||||
apply afi_abs.
|
||||
auto.
|
||||
eauto .
|
||||
apply beq_id_false_not_eq.
|
||||
rewrite Heqe.
|
||||
reflexivity.
|
||||
|
||||
assumption.
|
||||
|
||||
apply T_App with T11.
|
||||
auto.
|
||||
|
||||
auto.
|
||||
Qed.
|
||||
|
||||
Lemma substitution_preserves_typing : forall Gamma x U v t T,
|
||||
has_type (extend Gamma x U) t T ->
|
||||
has_type empty v U ->
|
||||
has_type Gamma (subst v x t) T.
|
||||
Proof with eauto.
|
||||
intros Gamma x U v t T Ht Hv.
|
||||
generalize dependent Gamma.
|
||||
generalize dependent T.
|
||||
tm_cases (induction t) Case; intros T Gamma H; inversion H; subst; simpl...
|
||||
Case "tm_var".
|
||||
rename i into y. remember (beq_id x y) as e. destruct e.
|
||||
SCase "x=y".
|
||||
apply beq_id_eq in Heqe. subst.
|
||||
rewrite extend_eq in H2.
|
||||
inversion H2; subst.
|
||||
clear H2.
|
||||
eapply context_invariance...
|
||||
intros x Hcontra.
|
||||
destruct (free_in_context _ _ T empty Hcontra) as (T', HT')...
|
||||
inversion HT'.
|
||||
|
||||
apply T_Var.
|
||||
rewrite extend_neq in H2.
|
||||
assumption.
|
||||
|
||||
rewrite Heqe.
|
||||
reflexivity.
|
||||
|
||||
rename i into y.
|
||||
apply T_Abs.
|
||||
remember (beq_id x y) as e.
|
||||
destruct e.
|
||||
eapply context_invariance...
|
||||
apply beq_id_eq in Heqe.
|
||||
subst.
|
||||
intros x Hafi.
|
||||
unfold extend.
|
||||
destruct (beq_id y x).
|
||||
reflexivity.
|
||||
|
||||
reflexivity.
|
||||
|
||||
apply IHt.
|
||||
eapply context_invariance...
|
||||
intros x0 Hafi.
|
||||
unfold extend.
|
||||
remember (beq_id y x0) as Coiso1.
|
||||
remember (beq_id x x0) as Coiso2.
|
||||
destruct Coiso1.
|
||||
auto.
|
||||
eauto .
|
||||
destruct Coiso2.
|
||||
eauto .
|
||||
auto.
|
||||
apply beq_id_eq in HeqCoiso1.
|
||||
apply beq_id_eq in HeqCoiso2.
|
||||
subst.
|
||||
assert (x0 <> x0).
|
||||
apply beq_id_false_not_eq.
|
||||
rewrite Heqe.
|
||||
auto.
|
||||
|
||||
apply ex_falso_quodlibet.
|
||||
apply H0.
|
||||
reflexivity.
|
||||
|
||||
reflexivity.
|
||||
|
||||
destruct Coiso2.
|
||||
auto.
|
||||
|
||||
auto.
|
||||
Qed.
|
||||
|
||||
Theorem preservation : forall t t' T,
|
||||
has_type empty t T ->
|
||||
t ==> t' ->
|
||||
has_type empty t' T.
|
||||
Proof.
|
||||
remember (@empty ty) as Gamma.
|
||||
intros t t' T HT.
|
||||
generalize dependent t'.
|
||||
induction HT.
|
||||
intros t' H1.
|
||||
inversion H1.
|
||||
|
||||
intros t' H1.
|
||||
inversion H1.
|
||||
|
||||
intros t' H1.
|
||||
inversion H1.
|
||||
apply substitution_preserves_typing with T11.
|
||||
subst.
|
||||
inversion HT1.
|
||||
subst.
|
||||
apply H2.
|
||||
|
||||
subst.
|
||||
assumption.
|
||||
|
||||
subst.
|
||||
apply T_App with T11.
|
||||
apply IHHT1.
|
||||
reflexivity.
|
||||
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
|
||||
subst.
|
||||
apply T_App with T11.
|
||||
assumption.
|
||||
|
||||
apply IHHT2.
|
||||
reflexivity.
|
||||
|
||||
assumption.
|
||||
|
||||
intros t' H.
|
||||
inversion H.
|
||||
|
||||
intros t' H.
|
||||
inversion H.
|
||||
|
||||
intros t' H.
|
||||
inversion H.
|
||||
subst.
|
||||
assumption.
|
||||
|
||||
subst.
|
||||
assumption.
|
||||
|
||||
subst.
|
||||
apply T_If.
|
||||
apply IHHT1.
|
||||
reflexivity.
|
||||
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
Theorem progress : forall t T,
|
||||
has_type empty t T ->
|
||||
value t \/ exists t', t ==> t'.
|
||||
Proof.
|
||||
intros t T.
|
||||
intros H.
|
||||
remember (@empty ty) as Gamma.
|
||||
induction H.
|
||||
rewrite HeqGamma in H.
|
||||
unfold empty in H.
|
||||
inversion H.
|
||||
|
||||
left.
|
||||
apply v_abs.
|
||||
|
||||
right.
|
||||
assert (value t1 \/ (exists t' : tm, t1 ==> t')).
|
||||
apply IHhas_type1.
|
||||
assumption.
|
||||
|
||||
assert (value t2 \/ (exists t' : tm, t2 ==> t')).
|
||||
apply IHhas_type2.
|
||||
assumption.
|
||||
|
||||
inversion H1.
|
||||
inversion H2.
|
||||
inversion H3.
|
||||
subst.
|
||||
exists (subst t2 x t).
|
||||
apply ST_AppAbs.
|
||||
assumption.
|
||||
|
||||
subst.
|
||||
inversion H.
|
||||
|
||||
subst.
|
||||
inversion H.
|
||||
|
||||
inversion H4.
|
||||
exists (tm_app t1 x).
|
||||
apply ST_App2.
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
|
||||
inversion H3.
|
||||
exists (tm_app x t2).
|
||||
apply ST_App1.
|
||||
assumption.
|
||||
|
||||
left.
|
||||
auto.
|
||||
|
||||
left.
|
||||
auto.
|
||||
|
||||
right.
|
||||
assert (value t1 \/ (exists t' : tm, t1 ==> t')).
|
||||
apply IHhas_type1.
|
||||
assumption.
|
||||
|
||||
inversion H2.
|
||||
inversion H3.
|
||||
subst.
|
||||
inversion H.
|
||||
|
||||
subst.
|
||||
exists t2.
|
||||
apply ST_IfTrue.
|
||||
|
||||
subst.
|
||||
exists t3.
|
||||
apply ST_IfFalse.
|
||||
|
||||
inversion H3.
|
||||
exists (tm_if x t2 t3).
|
||||
apply ST_If.
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
Theorem progress' : forall t T,
|
||||
has_type empty t T ->
|
||||
value t \/ exists t', t ==> t'.
|
||||
Proof.
|
||||
intros t.
|
||||
tm_cases (induction t) Case; intros T Ht; auto.
|
||||
inversion Ht.
|
||||
inversion H1.
|
||||
|
||||
right.
|
||||
inversion Ht.
|
||||
subst.
|
||||
assert (value t1 \/ (exists t' : tm, t1 ==> t')).
|
||||
apply IHt1 with (T := ty_arrow T11 T).
|
||||
assumption.
|
||||
|
||||
assert (value t2 \/ (exists t' : tm, t2 ==> t')).
|
||||
apply IHt2 with T11.
|
||||
assumption.
|
||||
|
||||
inversion H.
|
||||
inversion H1.
|
||||
subst.
|
||||
inversion H0.
|
||||
exists (subst t2 x t).
|
||||
apply ST_AppAbs.
|
||||
assumption.
|
||||
|
||||
inversion H3.
|
||||
exists (tm_app (tm_abs x T0 t) x0).
|
||||
apply ST_App2.
|
||||
assumption.
|
||||
|
||||
assumption.
|
||||
|
||||
subst.
|
||||
inversion H2.
|
||||
|
||||
subst.
|
||||
inversion H2.
|
||||
|
||||
inversion H1.
|
||||
exists (tm_app x t2).
|
||||
apply ST_App1.
|
||||
assumption.
|
||||
|
||||
right.
|
||||
inversion Ht.
|
||||
subst.
|
||||
assert (value t1 \/ (exists t' : tm, t1 ==> t')).
|
||||
apply IHt1 with ty_Bool.
|
||||
assumption.
|
||||
|
||||
assert (value t2 \/ (exists t' : tm, t2 ==> t')).
|
||||
apply IHt2 with T.
|
||||
assumption.
|
||||
|
||||
assert (value t3 \/ (exists t' : tm, t3 ==> t')).
|
||||
apply IHt3 with T.
|
||||
assumption.
|
||||
|
||||
inversion H.
|
||||
inversion H2.
|
||||
subst.
|
||||
inversion H3.
|
||||
|
||||
subst.
|
||||
subst.
|
||||
exists t2.
|
||||
apply ST_IfTrue.
|
||||
|
||||
exists t3.
|
||||
apply ST_IfFalse.
|
||||
|
||||
inversion H2.
|
||||
exists (tm_if x t2 t3).
|
||||
apply ST_If.
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
Theorem types_unique : forall t T Gamma,
|
||||
has_type Gamma t T ->
|
||||
(forall T', has_type Gamma t T' -> T' = T).
|
||||
Proof.
|
||||
intros t T Gamma H.
|
||||
induction H.
|
||||
intros T'.
|
||||
intros H1.
|
||||
inversion H1.
|
||||
subst.
|
||||
subst.
|
||||
auto.
|
||||
eauto .
|
||||
inversion H1.
|
||||
subst.
|
||||
assert (Some T = Some T').
|
||||
rewrite <- H3.
|
||||
rewrite <- H.
|
||||
reflexivity.
|
||||
|
||||
inversion H0.
|
||||
reflexivity.
|
||||
|
||||
intros T'.
|
||||
intros H1.
|
||||
inversion H1.
|
||||
subst.
|
||||
assert (T1 = T12).
|
||||
apply IHhas_type.
|
||||
assumption.
|
||||
|
||||
rewrite H0.
|
||||
reflexivity.
|
||||
|
||||
intros T' H1.
|
||||
subst.
|
||||
inversion H1.
|
||||
subst.
|
||||
assert (ty_arrow T0 T' = ty_arrow T11 T12).
|
||||
apply IHhas_type1.
|
||||
assumption.
|
||||
|
||||
inversion H2.
|
||||
reflexivity.
|
||||
|
||||
intros T'.
|
||||
intros H.
|
||||
inversion H.
|
||||
reflexivity.
|
||||
|
||||
intros.
|
||||
inversion H.
|
||||
reflexivity.
|
||||
|
||||
intros T'.
|
||||
intros H2.
|
||||
inversion H2.
|
||||
subst.
|
||||
apply IHhas_type2.
|
||||
assumption.
|
||||
Qed.
|
||||
419
samples/Coq/interval_discr.v
Normal file
419
samples/Coq/interval_discr.v
Normal file
@@ -0,0 +1,419 @@
|
||||
(** Sketch of the proof of {p:nat|p<=n} = {p:nat|p<=m} -> n=m
|
||||
|
||||
- preliminary results on the irrelevance of boundedness proofs
|
||||
- introduce the notion of finite cardinal |A|
|
||||
- prove that |{p:nat|p<=n}| = n
|
||||
- prove that |A| = n /\ |A| = m -> n = m if equality is decidable on A
|
||||
- prove that equality is decidable on A
|
||||
- conclude
|
||||
*)
|
||||
|
||||
(** * Preliminary results on [nat] and [le] *)
|
||||
|
||||
(** Proving axiom K on [nat] *)
|
||||
|
||||
Require Import Eqdep_dec.
|
||||
Require Import Arith.
|
||||
|
||||
Theorem eq_rect_eq_nat :
|
||||
forall (p:nat) (Q:nat->Type) (x:Q p) (h:p=p), x = eq_rect p Q x p h.
|
||||
Proof.
|
||||
intros.
|
||||
apply K_dec_set with (p := h).
|
||||
apply eq_nat_dec.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
(** Proving unicity of proofs of [(n<=m)%nat] *)
|
||||
|
||||
Scheme le_ind' := Induction for le Sort Prop.
|
||||
|
||||
Theorem le_uniqueness_proof : forall (n m : nat) (p q : n <= m), p = q.
|
||||
Proof.
|
||||
induction p using le_ind'; intro q.
|
||||
replace (le_n n) with
|
||||
(eq_rect _ (fun n0 => n <= n0) (le_n n) _ (refl_equal n)).
|
||||
2:reflexivity.
|
||||
generalize (refl_equal n).
|
||||
pattern n at 2 4 6 10, q; case q; [intro | intros m l e].
|
||||
rewrite <- eq_rect_eq_nat; trivial.
|
||||
contradiction (le_Sn_n m); rewrite <- e; assumption.
|
||||
replace (le_S n m p) with
|
||||
(eq_rect _ (fun n0 => n <= n0) (le_S n m p) _ (refl_equal (S m))).
|
||||
2:reflexivity.
|
||||
generalize (refl_equal (S m)).
|
||||
pattern (S m) at 1 3 4 6, q; case q; [intro Heq | intros m0 l HeqS].
|
||||
contradiction (le_Sn_n m); rewrite Heq; assumption.
|
||||
injection HeqS; intro Heq; generalize l HeqS.
|
||||
rewrite <- Heq; intros; rewrite <- eq_rect_eq_nat.
|
||||
rewrite (IHp l0); reflexivity.
|
||||
Qed.
|
||||
|
||||
(** Proving irrelevance of boundedness proofs while building
|
||||
elements of interval *)
|
||||
|
||||
Lemma dep_pair_intro :
|
||||
forall (n x y:nat) (Hx : x<=n) (Hy : y<=n), x=y ->
|
||||
exist (fun x => x <= n) x Hx = exist (fun x => x <= n) y Hy.
|
||||
Proof.
|
||||
intros n x y Hx Hy Heq.
|
||||
generalize Hy.
|
||||
rewrite <- Heq.
|
||||
intros.
|
||||
rewrite (le_uniqueness_proof x n Hx Hy0).
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
(** * Proving that {p:nat|p<=n} = {p:nat|p<=m} -> n=m *)
|
||||
|
||||
(** Definition of having finite cardinality [n+1] for a set [A] *)
|
||||
|
||||
Definition card (A:Set) n :=
|
||||
exists f,
|
||||
(forall x:A, f x <= n) /\
|
||||
(forall x y:A, f x = f y -> x = y) /\
|
||||
(forall m, m <= n -> exists x:A, f x = m).
|
||||
|
||||
Require Import Arith.
|
||||
|
||||
(** Showing that the interval [0;n] has cardinality [n+1] *)
|
||||
|
||||
Theorem card_interval : forall n, card {x:nat|x<=n} n.
|
||||
Proof.
|
||||
intro n.
|
||||
exists (fun x:{x:nat|x<=n} => proj1_sig x).
|
||||
split.
|
||||
(* bounded *)
|
||||
intro x; apply (proj2_sig x).
|
||||
split.
|
||||
(* injectivity *)
|
||||
intros (p,Hp) (q,Hq).
|
||||
simpl.
|
||||
intro Hpq.
|
||||
apply dep_pair_intro; assumption.
|
||||
(* surjectivity *)
|
||||
intros m Hmn.
|
||||
exists (exist (fun x : nat => x <= n) m Hmn).
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
(** Showing that equality on the interval [0;n] is decidable *)
|
||||
|
||||
Lemma interval_dec :
|
||||
forall n (x y : {m:nat|m<=n}), {x=y}+{x<>y}.
|
||||
Proof.
|
||||
intros n (p,Hp).
|
||||
induction p; intros ([|q],Hq).
|
||||
left.
|
||||
apply dep_pair_intro.
|
||||
reflexivity.
|
||||
right.
|
||||
intro H; discriminate H.
|
||||
right.
|
||||
intro H; discriminate H.
|
||||
assert (Hp' : p <= n).
|
||||
apply le_Sn_le; assumption.
|
||||
assert (Hq' : q <= n).
|
||||
apply le_Sn_le; assumption.
|
||||
destruct (IHp Hp' (exist (fun m => m <= n) q Hq'))
|
||||
as [Heq|Hneq].
|
||||
left.
|
||||
injection Heq; intro Heq'.
|
||||
apply dep_pair_intro.
|
||||
apply eq_S.
|
||||
assumption.
|
||||
right.
|
||||
intro HeqS.
|
||||
injection HeqS; intro Heq.
|
||||
apply Hneq.
|
||||
apply dep_pair_intro.
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
(** Showing that the cardinality relation is functional on decidable sets *)
|
||||
|
||||
Lemma card_inj_aux :
|
||||
forall (A:Type) f g n,
|
||||
(forall x:A, f x <= 0) ->
|
||||
(forall x y:A, f x = f y -> x = y) ->
|
||||
(forall m, m <= S n -> exists x:A, g x = m)
|
||||
-> False.
|
||||
Proof.
|
||||
intros A f g n Hfbound Hfinj Hgsurj.
|
||||
destruct (Hgsurj (S n) (le_n _)) as (x,Hx).
|
||||
destruct (Hgsurj n (le_S _ _ (le_n _))) as (x',Hx').
|
||||
assert (Hfx : 0 = f x).
|
||||
apply le_n_O_eq.
|
||||
apply Hfbound.
|
||||
assert (Hfx' : 0 = f x').
|
||||
apply le_n_O_eq.
|
||||
apply Hfbound.
|
||||
assert (x=x').
|
||||
apply Hfinj.
|
||||
rewrite <- Hfx.
|
||||
rewrite <- Hfx'.
|
||||
reflexivity.
|
||||
rewrite H in Hx.
|
||||
rewrite Hx' in Hx.
|
||||
apply (n_Sn _ Hx).
|
||||
Qed.
|
||||
|
||||
(** For [dec_restrict], we use a lemma on the negation of equality
|
||||
that requires proof-irrelevance. It should be possible to avoid this
|
||||
lemma by generalizing over a first-order definition of [x<>y], say
|
||||
[neq] such that [{x=y}+{neq x y}] and [~(x=y /\ neq x y)]; for such
|
||||
[neq], unicity of proofs could be proven *)
|
||||
|
||||
Require Import Classical.
|
||||
Lemma neq_dep_intro :
|
||||
forall (A:Set) (z x y:A) (p:x<>z) (q:y<>z), x=y ->
|
||||
exist (fun x => x <> z) x p = exist (fun x => x <> z) y q.
|
||||
Proof.
|
||||
intros A z x y p q Heq.
|
||||
generalize q; clear q; rewrite <- Heq; intro q.
|
||||
rewrite (proof_irrelevance _ p q); reflexivity.
|
||||
Qed.
|
||||
|
||||
Lemma dec_restrict :
|
||||
forall (A:Set),
|
||||
(forall x y :A, {x=y}+{x<>y}) ->
|
||||
forall z (x y :{a:A|a<>z}), {x=y}+{x<>y}.
|
||||
Proof.
|
||||
intros A Hdec z (x,Hx) (y,Hy).
|
||||
destruct (Hdec x y) as [Heq|Hneq].
|
||||
left; apply neq_dep_intro; assumption.
|
||||
right; intro Heq; injection Heq; exact Hneq.
|
||||
Qed.
|
||||
|
||||
Lemma pred_inj : forall n m,
|
||||
0 <> n -> 0 <> m -> pred m = pred n -> m = n.
|
||||
Proof.
|
||||
destruct n.
|
||||
intros m H; destruct H; reflexivity.
|
||||
destruct m.
|
||||
intros _ H; destruct H; reflexivity.
|
||||
simpl; intros _ _ H.
|
||||
rewrite H.
|
||||
reflexivity.
|
||||
Qed.
|
||||
|
||||
Lemma le_neq_lt : forall n m, n <= m -> n<>m -> n < m.
|
||||
Proof.
|
||||
intros n m Hle Hneq.
|
||||
destruct (le_lt_eq_dec n m Hle).
|
||||
assumption.
|
||||
contradiction.
|
||||
Qed.
|
||||
|
||||
Lemma inj_restrict :
|
||||
forall (A:Set) (f:A->nat) x y z,
|
||||
(forall x y : A, f x = f y -> x = y)
|
||||
-> x <> z -> f y < f z -> f z <= f x
|
||||
-> pred (f x) = f y
|
||||
-> False.
|
||||
|
||||
(* Search error sans le type de f !! *)
|
||||
Proof.
|
||||
intros A f x y z Hfinj Hneqx Hfy Hfx Heq.
|
||||
assert (f z <> f x).
|
||||
apply sym_not_eq.
|
||||
intro Heqf.
|
||||
apply Hneqx.
|
||||
apply Hfinj.
|
||||
assumption.
|
||||
assert (f x = S (f y)).
|
||||
assert (0 < f x).
|
||||
apply le_lt_trans with (f z).
|
||||
apply le_O_n.
|
||||
apply le_neq_lt; assumption.
|
||||
apply pred_inj.
|
||||
apply O_S.
|
||||
apply lt_O_neq; assumption.
|
||||
exact Heq.
|
||||
assert (f z <= f y).
|
||||
destruct (le_lt_or_eq _ _ Hfx).
|
||||
apply lt_n_Sm_le.
|
||||
rewrite <- H0.
|
||||
assumption.
|
||||
contradiction Hneqx.
|
||||
symmetry.
|
||||
apply Hfinj.
|
||||
assumption.
|
||||
contradiction (lt_not_le (f y) (f z)).
|
||||
Qed.
|
||||
|
||||
Theorem card_inj : forall m n (A:Set),
|
||||
(forall x y :A, {x=y}+{x<>y}) ->
|
||||
card A m -> card A n -> m = n.
|
||||
Proof.
|
||||
induction m; destruct n;
|
||||
intros A Hdec
|
||||
(f,(Hfbound,(Hfinj,Hfsurj)))
|
||||
(g,(Hgbound,(Hginj,Hgsurj))).
|
||||
(* 0/0 *)
|
||||
reflexivity.
|
||||
(* 0/Sm *)
|
||||
destruct (card_inj_aux _ _ _ _ Hfbound Hfinj Hgsurj).
|
||||
(* Sn/0 *)
|
||||
destruct (card_inj_aux _ _ _ _ Hgbound Hginj Hfsurj).
|
||||
(* Sn/Sm *)
|
||||
destruct (Hgsurj (S n) (le_n _)) as (xSn,HSnx).
|
||||
rewrite IHm with (n:=n) (A := {x:A|x<>xSn}).
|
||||
reflexivity.
|
||||
(* decidability of eq on {x:A|x<>xSm} *)
|
||||
apply dec_restrict.
|
||||
assumption.
|
||||
(* cardinality of {x:A|x<>xSn} is m *)
|
||||
pose (f' := fun x' : {x:A|x<>xSn} =>
|
||||
let (x,Hneq) := x' in
|
||||
if le_lt_dec (f xSn) (f x)
|
||||
then pred (f x)
|
||||
else f x).
|
||||
exists f'.
|
||||
split.
|
||||
(* f' is bounded *)
|
||||
unfold f'.
|
||||
intros (x,_).
|
||||
destruct (le_lt_dec (f xSn) (f x)) as [Hle|Hge].
|
||||
change m with (pred (S m)).
|
||||
apply le_pred.
|
||||
apply Hfbound.
|
||||
apply le_S_n.
|
||||
apply le_trans with (f xSn).
|
||||
exact Hge.
|
||||
apply Hfbound.
|
||||
split.
|
||||
(* f' is injective *)
|
||||
unfold f'.
|
||||
intros (x,Hneqx) (y,Hneqy) Heqf'.
|
||||
destruct (le_lt_dec (f xSn) (f x)) as [Hlefx|Hgefx];
|
||||
destruct (le_lt_dec (f xSn) (f y)) as [Hlefy|Hgefy].
|
||||
(* f xSn <= f x et f xSn <= f y *)
|
||||
assert (Heq : x = y).
|
||||
apply Hfinj.
|
||||
assert (f xSn <> f y).
|
||||
apply sym_not_eq.
|
||||
intro Heqf.
|
||||
apply Hneqy.
|
||||
apply Hfinj.
|
||||
assumption.
|
||||
assert (0 < f y).
|
||||
apply le_lt_trans with (f xSn).
|
||||
apply le_O_n.
|
||||
apply le_neq_lt; assumption.
|
||||
assert (f xSn <> f x).
|
||||
apply sym_not_eq.
|
||||
intro Heqf.
|
||||
apply Hneqx.
|
||||
apply Hfinj.
|
||||
assumption.
|
||||
assert (0 < f x).
|
||||
apply le_lt_trans with (f xSn).
|
||||
apply le_O_n.
|
||||
apply le_neq_lt; assumption.
|
||||
apply pred_inj.
|
||||
apply lt_O_neq; assumption.
|
||||
apply lt_O_neq; assumption.
|
||||
assumption.
|
||||
apply neq_dep_intro; assumption.
|
||||
(* f y < f xSn <= f x *)
|
||||
destruct (inj_restrict A f x y xSn); assumption.
|
||||
(* f x < f xSn <= f y *)
|
||||
symmetry in Heqf'.
|
||||
destruct (inj_restrict A f y x xSn); assumption.
|
||||
(* f x < f xSn et f y < f xSn *)
|
||||
assert (Heq : x=y).
|
||||
apply Hfinj; assumption.
|
||||
apply neq_dep_intro; assumption.
|
||||
(* f' is surjective *)
|
||||
intros p Hlep.
|
||||
destruct (le_lt_dec (f xSn) p) as [Hle|Hlt].
|
||||
(* case f xSn <= p *)
|
||||
destruct (Hfsurj (S p) (le_n_S _ _ Hlep)) as (x,Hx).
|
||||
assert (Hneq : x <> xSn).
|
||||
intro Heqx.
|
||||
rewrite Heqx in Hx.
|
||||
rewrite Hx in Hle.
|
||||
apply le_Sn_n with p; assumption.
|
||||
exists (exist (fun a => a<>xSn) x Hneq).
|
||||
unfold f'.
|
||||
destruct (le_lt_dec (f xSn) (f x)) as [Hle'|Hlt'].
|
||||
rewrite Hx; reflexivity.
|
||||
rewrite Hx in Hlt'.
|
||||
contradiction (le_not_lt (f xSn) p).
|
||||
apply lt_trans with (S p).
|
||||
apply lt_n_Sn.
|
||||
assumption.
|
||||
(* case p < f xSn *)
|
||||
destruct (Hfsurj p (le_S _ _ Hlep)) as (x,Hx).
|
||||
assert (Hneq : x <> xSn).
|
||||
intro Heqx.
|
||||
rewrite Heqx in Hx.
|
||||
rewrite Hx in Hlt.
|
||||
apply (lt_irrefl p).
|
||||
assumption.
|
||||
exists (exist (fun a => a<>xSn) x Hneq).
|
||||
unfold f'.
|
||||
destruct (le_lt_dec (f xSn) (f x)) as [Hle'|Hlt'].
|
||||
rewrite Hx in Hle'.
|
||||
contradiction (lt_irrefl p).
|
||||
apply lt_le_trans with (f xSn); assumption.
|
||||
assumption.
|
||||
(* cardinality of {x:A|x<>xSn} is n *)
|
||||
pose (g' := fun x' : {x:A|x<>xSn} =>
|
||||
let (x,Hneq) := x' in
|
||||
if Hdec x xSn then 0 else g x).
|
||||
exists g'.
|
||||
split.
|
||||
(* g is bounded *)
|
||||
unfold g'.
|
||||
intros (x,_).
|
||||
destruct (Hdec x xSn) as [_|Hneq].
|
||||
apply le_O_n.
|
||||
assert (Hle_gx:=Hgbound x).
|
||||
destruct (le_lt_or_eq _ _ Hle_gx).
|
||||
apply lt_n_Sm_le.
|
||||
assumption.
|
||||
contradiction Hneq.
|
||||
apply Hginj.
|
||||
rewrite HSnx.
|
||||
assumption.
|
||||
split.
|
||||
(* g is injective *)
|
||||
unfold g'.
|
||||
intros (x,Hneqx) (y,Hneqy) Heqg'.
|
||||
destruct (Hdec x xSn) as [Heqx|_].
|
||||
contradiction Hneqx.
|
||||
destruct (Hdec y xSn) as [Heqy|_].
|
||||
contradiction Hneqy.
|
||||
assert (Heq : x=y).
|
||||
apply Hginj; assumption.
|
||||
apply neq_dep_intro; assumption.
|
||||
(* g is surjective *)
|
||||
intros p Hlep.
|
||||
destruct (Hgsurj p (le_S _ _ Hlep)) as (x,Hx).
|
||||
assert (Hneq : x<>xSn).
|
||||
intro Heq.
|
||||
rewrite Heq in Hx.
|
||||
rewrite Hx in HSnx.
|
||||
rewrite HSnx in Hlep.
|
||||
contradiction (le_Sn_n _ Hlep).
|
||||
exists (exist (fun a => a<>xSn) x Hneq).
|
||||
simpl.
|
||||
destruct (Hdec x xSn) as [Heqx|_].
|
||||
contradiction Hneq.
|
||||
assumption.
|
||||
Qed.
|
||||
|
||||
(** Conclusion *)
|
||||
|
||||
Theorem interval_discr :
|
||||
forall n m, {p:nat|p<=n} = {p:nat|p<=m} -> n=m.
|
||||
Proof.
|
||||
intros n m Heq.
|
||||
apply card_inj with (A := {p:nat|p<=n}).
|
||||
apply interval_dec.
|
||||
apply card_interval.
|
||||
rewrite Heq.
|
||||
apply card_interval.
|
||||
Qed.
|
||||
15
samples/Dart/point.dart
Normal file
15
samples/Dart/point.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
class Point {
|
||||
Point(this.x, this.y);
|
||||
distanceTo(Point other) {
|
||||
var dx = x - other.x;
|
||||
var dy = y - other.y;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
var x, y;
|
||||
}
|
||||
|
||||
main() {
|
||||
Point p = new Point(2, 3);
|
||||
Point q = new Point(3, 4);
|
||||
print('distance from p to q = ${p.distanceTo(q)}');
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user